Tutorials, extensions, and source files for ActionScript, Flash, and other Adobe products.

 

senocular.com ActionScript Library

FreeTransform.as

Name: FREE Transform! (cheap!) [MX]
Author: senocular: www.senocular.com
Date: 1899-12-31T00:52:07.000
Documentation:
FreeTransform: adds a “free transform” tool box around a movieclip. 
Supported transformations are:
-	rotation
-	scaling
-	position
Each has a alternate reaction when combined with the SHIFT key. (scaling only on corner handles).

Basic usage: 
movieClipInstance.addFreeTransform();
movieClipInstance.removeFreeTransform();

Goings on:
When a movieclip has a free transform added to it, the movieclip is given a new property,
_FTobject which refers to the free transform object created in association with that clip.
This object is an instance of the FreeTransform class included in this prototype. Its visual
properties are dictated by another object, a free transform style object (from the
FreeTransformStyle class).  If no free transform style object is made, the default style for
the transform is used.  You can have as many styles as you want though a movieclip can only
display one style at a time, however, multiple movieclips can share the same style.  A style
can also be used to control other movieclips who possess the same style as done with the
autoRemove argument as it retains a property called _freetransforms listing all the movieclips
which contain a free transform of that style..

Basic usage with style: 
movieClipInstance.addFreeTransform(myStyle);
movieClipInstance.removeFreeTransform();

Styles:
Styles are created using the new command in combinations with FreeTransformStyle and a list of
accompanying arguments. ex:

customStyle = new FreeTransformStyle([3,0xFF0000,100], [15,0xFFEEAA,100], ["r",null,"r","s","s","s","r",null], true, 2);

There are 5 arguments total:
linestyle, fillstyle, layout, autoRaise, autoRemove
any ommited arguments will gain the properties of the default style.
Arguments: 
- linestyle: (in ex: [3,0xFF0000,100]) an array containing line thickness (3) line color
(0xFF0000) and line alpha (100).
default is [0,0x000000,100]
- fillstyle: (in ex: [15,0xFFEEAA,100]) an array containing transform handle size (15) fill
color (0xFFEEAA) and fill  alpha (100).
default is [10,0xFFFFFF,100]

- layout: an array specifying the type of handle to have in any of the 8 available positions along the bounding box of the free transform tool,  Given the array [a,b,c,d,e,f,g,h] here are the cooresponding positions

a--b--c
|     |
h     d
|     |
g--f--e

“r” represents a rotation handle, “s” a scale handle and null is no handle
default is ["r","s","r","s","r","s","r","s"]
- autoRaise: a boolean (true or false) specifying whether or not swapDepths should be used to
bring the free transformed clip to the top depth of that scope when selected. default is true
- autoRemove: a number (0-2) specifying the type of auto removal to be used for the free
transform.  0 is no auto removal, 1 is removal when a mouse down was initiated and the mouse
was not in contact with this movieclip, and 2 is auto removal only when another moveclip has
added to it a free transform of this same style.
default is 1.

additionally, custom cursors can be specified for a transfrom style using
FreeTransformStyleInstance.customCursor();
This can be used two ways, 1 with arguments 
FreeTransformStyleInstance.customCursor(“handleRef”,”cursorLinker”,cursorVisibility);
and the other with similar arguments in arrays allowing to add more than one cursor at a time 
FreeTransformStyleInstance.customCursor([“handleRef”,”cursorLinker”,cursorVisibility, rotation], [“handleRef”,”cursorLinker”,cursorVisibility]);
for however many cursors you want to add, though as style only supports 3 cursors, one for
movement, one for scaling and one for rotation. ex:
customStyle.customCursor(["r","spin",2],["s","size",2,true],["m","move",1]);

Arguments (customCursor): 
- handleRef: a letter similar to that in the style layout specifying which handle or action the
curor will be for.  “r” is rotation, “s” is scale and “m” is movement.
- cursorLinker: a string specifying the linkage ID of the item in the library you plan to use
as a custom cursor.
- cursorVisibility: a number (0-2) representing the type of cursor visibility you will allow
for the systems cursor when you apply the custom cursor. 0 is the default hand cursor, 1 is
the arrow cursor, and 2 is no cursor at all (aside from the custom cursor)
- rotation: a boolean (true or false) for whether or not a cursor will rotate (always
pointing inward) with the tranform handle when used.  Default is false.

a style also contains a removeAll method which will remove all free transforms on the screen
using that style. ex:
customStyle.removeAll();

and that’s about it. I tried to make it both easy and flexible and this is what came of it :)

update: now with rotation arm handle - example swf updated with an example of this in the custom style.

What this is, is a extended line from the center of the transform with a handle on the end which is commonly a rotation handle (though a scale handle can be specified).

Creating an arm handle:
Making a handle is similar to adding custom cursors in that they are added through calling a method on a freeTransformStyle instance.  There are two new methods for these handles, addHandle and removeHandle.  They are set up as follows
FreeTransformStyleInstance.addHandle("type", angle, size);
FreeTransformStyleInstance.removeHandle(angle);
with the option of adding many at one time with addHandle using
FreeTransformStyleInstance.addHandle(["type", angle, size],["type", angle, size]);
example:
customStyle.addHandle("s", 4, 1.5);

Arguments:
- type: either "r" or "s" for a rotation handle or scale handle respectively
- angle: a NUMBER specifying layout position.  These are not actual angle values in degrees, rather, like the layout array, numbers specifying the handle's position - err, direction. See diagram below. The removeHandle method uses this value to determine which handle to remove.
0--1--2
|     |
7     3
|     |
6--5--4
- size: multiplier for length of the handles extension beyond the size of the clip.  A size of 1 is right on the border, a size of .5 is half-way from the center of the clip to the edges and 1.5 (as the example uses) is 50% out past the border of the clip.

NOTE:
- You can only have 1 handle of this type for each of the 8 'angles' within the layout
- Angles 1,3,5 and 7 are 'straight' angles in that they dont follow the corner of the bounding box of the clip, but rather pertrude out the side of the clip from the clip's center.  Since the center of the bounding box is used as a direction for this pertrusion, if the clip's own center is NOT at its actual center, these side-based angles will appear slanted as they come from an irregular center through the center area of the bounding box.

-----------------
Other changes include:
- some minor changes in variable handling (nothing noticable or functionally different)
- now correctly using prototype values to specify the style of a raw freetransform style (one in which no arguments were passed).
- the default style of a freetransform is also, now, a raw style object which uses those style prototype objects as a style reference (as opposed to having an explicitly specified style added at its creation).
- protection against 0 scales preventing further scaling manipulation
- added MovieClipInstance.updateFreeTransform() to let you redraw the transform on that movieclip if its altered in any way outside of the FreeTransform's transformations.
- fixed small bug which reveresed the offsets of a SHIFT controlled movement.

added scale restriction
sizeRestrict property of a FreeTransformStyle object

new FreeTransformStyle(linestyle, fillstyle, layout, autoRaise, autoRemove, sizeRestrict);

in the form of a getBounds object

xmin: minimum _xscale for the transform. default -Infinity
xmax: maximum _xscale for the transform. default Infinity
ymin: minimum _yscale for the transform. default -Infinity
ymax: maximum _yscale for the transform. default Infinity

Example:
var restrict = {xmin:50, xmax:200, ymin:50, ymax:100};
var style = new FreeTransformStyle(myLinestyle, myFillstyle, undefined, true, true, restrict);
// (note undefined in new FreeTransformStyle results in default value)
myClip.addFreeTransform(style);
// ^ transform will be restricted to 50% min in _xscale, 100% max _xscale, 50% min _yscale and 100% max in _yscale.

Example:
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
FreeTransformStyle = function(linestyle, fillstyle, layout, autoRaise, autoRemove, sizeRestrict){
	if (linestyle != undefined) this.linestyle = linestyle;
	if (fillstyle != undefined) this.fillstyle = fillstyle;
	if (layout != undefined) this.layout = layout;
	if (autoRaise != undefined) this.autoRaise = autoRaise;
	if (autoRemove != undefined) this.autoRemove = autoRemove;
	if (sizeRestrict != undefined) this.sizeRestrict = sizeRestrict;
	this._freetransforms = [];
	this._arms = [];	
	return this;
}
FreeTransformStyle.prototype.linestyle = [0,0x000000,100];
FreeTransformStyle.prototype.fillstyle = [10,0xFFFFFF,100];
FreeTransformStyle.prototype.layout = ["r","s","r","s","r","s","r","s"];
FreeTransformStyle.prototype.autoRaise = true;
FreeTransformStyle.prototype.autoRemove = 1;
FreeTransformStyle.prototype.sizeRestrict = {xMin:Number.NEGATIVE_INFINITY, xMax:Number.POSITIVE_INFINITY, yMin:Number.NEGATIVE_INFINITY, yMax:Number.POSITIVE_INFINITY};
FreeTransformStyle.prototype.removeAll = function(){
	var L = this._freetransforms.length;
	while(L--){
		this._freetransforms[L]._FTobject.FT.removeMovieClip();
		delete this._freetransforms[L]._FTobject;
	}
	this._freetransforms = [];
}
FreeTransformStyle.prototype.customCursor = function(type, linker, visible, rotate){
	if (typeof type == "string"){
		this[type+"cursor"] = {linker:linker, visible:visible, rotate:rotate};
	}else{
		var L = arguments.length;
		while(L--) arguments.callee.apply(this, arguments[L]);
	}
}
FreeTransformStyle.prototype.removeHandle = function(angle, noRedraw){
	for (var i=0; i<this._arms.length; i++){
		if (this._arms[i].angle == angle){
			this._arms.splice(i,1);
			break;
		}
	}
	if (!noRedraw) for(i=0; i<this._freetransforms.length; i++) this._freetransforms[i].addFreeTransform(this);
}
FreeTransformStyle.prototype.addHandle = function(type, angle, size){
	if (typeof type == "string"){
		if (angle<0) angle = -angle;
		angle %= 8;
		this.removeHandle(angle, true)
		if (size == undefined) size = 1.5;
		this._arms[this._arms.length] = {type:type, angle:angle, size:size};
	}else{
		var L = arguments.length;
		while(L--) arguments.callee.apply(this, arguments[L]);
	}
	for(var i=0; i<this._freetransforms.length; i++) this._freetransforms[i].addFreeTransform(this);
}
FreeTransform = function(mc, style){
	this.clip = mc;
	if (style != undefined) this.style = style;
	this.create();
	return this;
}
FreeTransform.prototype.style = new FreeTransformStyle(); // default style
FreeTransform.prototype.create = function () {
	var i, a = this.style._arms, b = this.clip.getBoundaries();
	if (this.style.autoRaise) this.clip.swapDepths(this.clip._parent.topDepth()+1);
	this.FT = this.clip._parent.createEmptyMovieClip(this.clip._name + "FT_mc", this.clip._parent.topDepth()+1);
	this.FT.match(this.clip,"_alpha","_visible","_rotation","_x","_y");
	this.drawBounds(b);
	for (i=0;i<8;i++){
		if (this.style.layout[i] == "r") this.addRotateHandle(i, i);
		else if (this.style.layout[i] == "s") this.addScaleHandle(i, i);
	}
	for (i=0;i<a.length;i++){
		if (a[i].type == "r") this.addRotateHandle(a[i].angle, 8+i);
		else if (a[i].type == "s") this.addScaleHandle(a[i].angle, 8+i);
	}
	this.updateHandles(b);	
	this.addCenter();
	if (this.style.autoRemove == 1){
		this.FT.FTobj = this;
		this.FT.onMouseDown = function(){
			if (!this.hitTest(_root._xmouse,_root._ymouse,true) && !this.FTobj.clip.hitTest(_root._xmouse,_root._ymouse,true)){
				this.FTobj.clip.removeFreeTransform();
			}
		}
	}
	if (this.style.autoRemove == 2){
		var L = this.style._freetransforms.length;
		while (L--){
			this.style._freetransforms[L]._FTobject.FT.removeMovieClip();
			delete this.style._freetransforms[L]._FTobject;
		}
		this.style._freetransforms = [this.clip];
	}else this.style._freetransforms[this.style._freetransforms.length] = this.clip;
}
FreeTransform.prototype.handleCursor = function(c, handle, pos){
	var curs = this.style[handle+"cursor"];
	if (curs.visible == 1) c.useHandCursor = false;
	c.onRollOver = function(){
		var r = _root.attachMovie(curs.linker,"FT_CC",10101);
		r._x = _root._xmouse;
		r._y = _root._ymouse;
		if (curs.rotate){
			r._rotation = this._parent._rotation + 135 + pos*45
			r.c = this;
		}
		if (curs.visible == 2) Mouse.hide();
		r.onMouseMove = function(){
			this._x = _root._xmouse;
			this._y = _root._ymouse;
			if (curs.rotate){
				this._rotation = this.c._parent._rotation + 135 + pos*45
				var xs, ys;
				if (xs = (this.c.FTobj.clip._xscale < 0)){
					if (pos == 0 || pos == 4) this._rotation+=90;
					else if (pos == 2 || pos == 6) this._rotation-=90;
					else if (pos == 3 || pos == 7) this._rotation+=180;
				}
				if (ys = (this.c.FTobj.clip._yscale < 0)){
					if (pos == 0 || pos == 4) this._rotation-=90;
					else if (pos == 2 || pos == 6) this._rotation+=90;
					else if (pos == 1 || pos == 5) this._rotation+=180;
				}
				if (xs && ys) if (!(pos%2)) this._rotation+=180;
			}
			updateAfterEvent();
		}
	}
	c.onRollOut = function(){
		_root.FT_CC.removeMovieClip();
		if (curs.visible == 2) Mouse.show();
	}
	c.onReleaseOutside = function(){
		_root.FT_CC.removeMovieClip();
		if (curs.visible == 2) Mouse.show();
		delete this.onMouseMove;
	}
}
FreeTransform.prototype.drawBounds = function(b){
	var i, a = this.style._arms, c = this.FT;
	if (b == undefined) b = this.clip.getBoundaries();
	c.clear();
	lineStyle.apply(c, this.style.linestyle);
	for (i=0;i<9;i+=2) if (!i) moveTo.apply(c,b[i]); else lineTo.apply(c,b[i]);
	for (i=0;i<a.length;i++){
		moveTo.apply(c, [0,0]);
		lineTo.apply(c, [b[a[i].angle][0]*a[i].size, b[a[i].angle][1]*a[i].size]);
	}
}
FreeTransform.prototype.addRotateHandle = function(pos, ID){
	var c = this.FT.createEmptyMovieClip("h"+ID, ID+10);
	beginFill.apply(c, this.style.fillstyle.slice(1));
	lineStyle.apply(c, this.style.linestyle);
	c.DrawCircle(0,0,this.style.fillstyle[0]);
	c.endFill();
	c.FTobj = this;
	c.onPress = function(){
		var clickAngle = this._parent.getMouseAngle();
		var clickRotation = this._parent._rotation;
		this.onMouseMove = function(){
			var r = clickRotation - clickAngle + this._parent.getMouseAngle();
			this._parent._rotation = (Key.isDown(Key.SHIFT)) ? r.snap(45,clickRotation) : r;
			this.FTobj.clip.match(this._parent,"_alpha","_visible","_rotation","_x","_y");
			updateAfterEvent();
		}
	}
	c.onRelease = c.onReleaseOutside = function(){ delete this.onMouseMove; }
	if (this.style.rcursor) this.handleCursor(c, "r", pos);
}
FreeTransform.prototype.addScaleHandle = function(pos, ID){
	var s, c = this.FT.createEmptyMovieClip("h"+ID, ID+10);
	beginFill.apply(c, this.style.fillstyle.slice(1));
	lineStyle.apply(c, this.style.linestyle);
	c.DrawSquare(0,0,this.style.fillstyle[0]);
	c.endFill();
	c.FTobj = this;
	c.xsize = (!pos || pos > 5) ? "xMin" : (1 < pos && pos < 5) ? "xMax" : null;
	c.ysize = (pos < 3) ? "yMin" : (7 > pos && pos > 3) ? "yMax" : null;
	c.onPress = function(){
		var b = this.FTobj.clip.getBounds();
		var offx = this._xmouse;
		var offy = this._ymouse;
		var clickx = this._parent._xmouse;
		var clicky = this._parent._ymouse;
		var clickXscale = this.FTobj.clip._xscale;
		var clickYscale = this.FTobj.clip._yscale;
		s =  (ID<8) ? 100 : 100/this.FTobj.style._arms[ID-8].size;
		this.onMouseMove = function(){
			var r = this.FTobj.style.sizeRestrict;
			if (Key.isDown(Key.SHIFT) && this.xsize.length && this.ysize.length){
				var scale = Math.max(((this._parent._xmouse - offx)*s/clickXscale)/b[this.xsize], ((this._parent._ymouse - offy)*s/clickYscale)/b[this.ysize]);
				var scales = [clickXscale * scale, clickYscale * scale];
				this.FTobj.clip._xscale = scales[0].clamp(r.xMin, r.xMax);
				this.FTobj.clip._yscale = scales[1].clamp(r.yMin, r.yMax);
			}else{
				var scales = [clickXscale * (((this._parent._xmouse - offx)*s/clickXscale)/b[this.xsize]), clickYscale * (((this._parent._ymouse - offy)*s/clickYscale)/b[this.ysize])];
				if (this.xsize.length) this.FTobj.clip._xscale = scales[0].clamp(r.xMin, r.xMax);
				if (this.ysize.length) this.FTobj.clip._yscale = scales[1].clamp(r.yMin, r.yMax);
			}
			if (!this.FTobj.clip._xscale) this.FTobj.clip._xscale = .1;
			if (!this.FTobj.clip._yscale) this.FTobj.clip._yscale = .1;
			var b = c.FTobj.clip.getBoundaries();
			c.FTobj.updateHandles(b);
			c.FTobj.drawBounds(b);
			updateAfterEvent();
		}
	}
	c.onRelease = c.onReleaseOutside = function(){ delete this.onMouseMove; }
	if (this.style.scursor) this.handleCursor(c, "s", pos);
}
FreeTransform.prototype.updateHandles = function(b){
	var i, a = this.style._arms;
	if (!b) var b = this.clip.getBoundaries();
	for (i=0;i<8;i++){
		this.FT["h"+i]._x = b[i][0];
		this.FT["h"+i]._y = b[i][1];	
	}
	for (i=0;i<a.length;i++){
		this.FT["h"+(i+8)]._x = b[a[i].angle][0]*a[i].size;
		this.FT["h"+(i+8)]._y = b[a[i].angle][1]*a[i].size;
	}
}
FreeTransform.prototype.addCenter = function(){
	var c = this.FT.createEmptyMovieClip("center", 0);
	lineStyle.apply(c, this.style.linestyle);
	c.DrawCircle(0,0,this.style.fillstyle[0]);
	c.DrawCross(0,0,this.style.fillstyle[0]);
	c.hitArea = this.clip;
	c.FTobj = this;
	c.onPress = function(){
		if (this.FTobj.style.autoraise && this.FTobj.clip.getDepth() != this.FTobj.clip._parent.topDepth()-1){
			var t = this.FTobj.clip._parent.topDepth()+1;
			this.FTobj.clip.swapDepths(t);
			this.FTobj.FT.swapDepths(t+1);			
		}
		var offx = this._parent._parent._xmouse - this._parent._x;
		var offy = this._parent._parent._ymouse - this._parent._y;
		var clickx = this._parent._x;
		var clicky = this._parent._y;
		this.onMouseMove = function(){
			if (Key.isDown(Key.SHIFT)){
				var thisx = this._parent._parent._xmouse - clickx;
				var thisy = this._parent._parent._ymouse - clicky;
				if (Math.abs(thisx) > Math.abs(thisy)){
					this._parent._x = this._parent._parent._xmouse - offx
					this._parent._y = clicky;
				}else{
					this._parent._y = this._parent._parent._ymouse - offy;
					this._parent._x = clickx;
				}
			}else{
				this._parent._x = this._parent._parent._xmouse - offx;
				this._parent._y = this._parent._parent._ymouse - offy;
			}
			this.FTobj.clip.match(this._parent,"_alpha","_visible","_rotation","_x","_y");
			updateAfterEvent();
		}
	}
	c.onRelease = c.onReleaseOutside = function(){ delete this.onMouseMove; }
	if (this.style.mcursor) this.handleCursor(c, "m");
}
MovieClip.prototype.DrawCircle = function (x,y,diameter) {
	var r=diameter/2;
	var c1=r*(Math.SQRT2-1);
	var c2=r*Math.SQRT2/2;
	this.moveTo(x+r,y);
	this.curveTo(x+r,y+c1,x+c2,y+c2);
	this.curveTo(x+c1,y+r,x,y+r);
	this.curveTo(x-c1,y+r,x-c2,y+c2);
	this.curveTo(x-r,y+c1,x-r,y);
	this.curveTo(x-r,y-c1,x-c2,y-c2);
	this.curveTo(x-c1,y-r,x,y-r);
	this.curveTo(x+c1,y-r,x+c2,y-c2);
	this.curveTo(x+r,y-c1,x+r,y);
}
MovieClip.prototype.DrawSquare = function (x,y,size) {
	var b = size/2;
	this.moveTo(x-b,y-b);
	this.lineTo(x+b,y-b);
	this.lineTo(x+b,y+b);
	this.lineTo(x-b,y+b);
	this.lineTo(x-b,y-b);
}
MovieClip.prototype.DrawCross = function (x,y,size) {
	var b = size/2;
	this.moveTo(x,y-b);
	this.lineTo(x,y+b);
	this.moveTo(x-b,y);
	this.lineTo(x+b,y);
}
MovieClip.prototype.getBoundaries = function () {
	var b = this.getBounds();
	b.xMin *= this._xscale/100;
	b.xMax *= this._xscale/100;
	b.yMin *= this._yscale/100;
	b.yMax *= this._yscale/100;
	b.xhalf = b.xMin+(b.xMax-b.xMin)/2;
	b.yhalf = b.yMin+(b.yMax-b.yMin)/2;
	return [[b.xMin,b.yMin],[b.xhalf,b.yMin],[b.xMax,b.yMin],[b.xMax,b.yhalf],[b.xMax,b.yMax],[b.xhalf,b.yMax],[b.xMin,b.yMax],[b.xMin,b.yhalf],[b.xMin,b.yMin]];
}
Number.prototype.snap = function(range,base){
	var dif = (this-base) % range;
	var n = this - dif;
	if (dif > 0){
		if (dif > range/2) n += range;
	}else if (dif < -range/2) n -= range;
	return n;	
}
Number.prototype.clamp = function(low,high){
	if (this < low) return low;
	if (this > high) return high;
	return this;	
}
Array.prototype.findAndRemove = function(e){
	var L = this.length;
	while(L--) if (this[L] == e) return this.splice(L,1);
	return false;	
}
MovieClip.prototype.getMouseAngle = function(){
	return Math.atan2(this._parent._ymouse-this._y, this._parent._xmouse-this._x) * 180/Math.PI;
}
MovieClip.prototype.topDepth = function () {
	var mcs,depth = 0; // 0 is topmost removable depth
	for (mcs in this) if (typeof this[mcs] == "movieclip") if (this[mcs].getDepth() > depth) depth = this[mcs].getDepth();
	return depth;
}
MovieClip.prototype.match = function(mc, props){
	var L = (props = arguments).length;
	if (L == 1) L = (props = [null,"_alpha","_visible","_rotation","_xscale","_yscale","_x","_y"]).length;
	while(L--) this[props[L]] = mc[props[L]];
}
MovieClip.prototype.updateFreeTransform = function(){
	if (!this._FTobject) return false;
	var b = this.getBoundaries();
	this._FTobject.FT.match(this,"_alpha","_visible","_rotation","_x","_y");
	this._FTobject.updateHandles(b);
	this._FTobject.drawBounds(b);
	updateAfterEvent();
}
MovieClip.prototype.removeFreeTransform = function(){
	if (!this._FTobject) return;
	this._FTobject.FT.removeMovieClip();
	this._FTobject.style._freetransforms.findAndRemove(this);
	delete this._FTObject;
}
MovieClip.prototype.addFreeTransform = function(style){
	if (this._FTobject) this.removeFreeTransform();
	this._FTobject = new FreeTransform(this,style);
}