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

 

senocular.com ActionScript Library

SimpleFreeTransform.as

Name: SimpleFreeTransform [MX] - method of altering a clips visual properties via mouse interaction
Author: senocular: www.senocular.com
Date: 1899-12-31T00:11:27.700
Documentation:
SimpleFreeTransform - Ability to alter (transform) a
movieclip's properties through mouse interaction.  Such
interaction is based around click and drag.  Transforms
supported are Movement, Scale and Rotation.

myMovieClip.enableFreeTransform("tool");
myMovieClip.disableFreeTransform();


enableFreeTransform:
- adds the free transform interaction to the desired movieclip.

Arguments:
- tool: (string) a string specifying the tool to be used in the enabled transform behavior.
Available values are "move", "scale", "rotate", and "none" each coresponding to that kind of
transform behavior.  "none" will remove any existsing behavior - its use is equivalent to
disableFreeTransform.

Returns:
- nothing


disableFreeTransform:
- removes any free transform behavior from a movieclip.

Arguments:
- none

Returns:
- nothing


Note:
- using SHIFT will give more control in transform behaviors.


Note:
- other prototypes used here are
MovieClip.prototype.getMouseAngle
MovieClip.prototype.match
Number.prototype.snap

Warning:
- be careful in using the scale tool.  Scaling is based on the centerpoint of the movieclip; in
clicking directly on that centerpoint, or even near it, you can get some crazy scaling or even
no scaling at all.

Example:
// cycles through the transform tools using the up and down keys
// and applies each to the my_mc movieclip
Key.addListener(my_mc);
my_mc.onKeyDown = function(){
	if (Key.isDown(Key.UP) || Key.isDown(Key.DOWN)){
		this.index += Key.isDown(Key.UP) - Key.isDown(Key.DOWN);
		if (this.index < 0) this.index = SimpleFreeTransform.tools.length-1;
		else if (this.index >= SimpleFreeTransform.tools.length) this.index = 0;
		this.enableFreeTransform( SimpleFreeTransform.tools[this.index] );
		trace(SimpleFreeTransform.tools[this.index]);
	}
}

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
SimpleFreeTransform = {};
SimpleFreeTransform.tools = ["none","move","scale","rotate"];
SimpleFreeTransform.onRelease = function(){
	delete this.onMouseMove;
	this._parent.FTScaleRegulator.removeMovieClip();
}
SimpleFreeTransform.onPress = function(){
	var clip = this._parent;
	switch(this.tool){
		case "move":
			var orig_x = clip._x;
			var orig_y = clip._y;
			var clickx = clip._parent._xmouse;
			var clicky = clip._parent._ymouse;
			var offx = clickx - orig_x;
			var offy = clicky - orig_y;
			this.onMouseMove = function(){
				if (Key.isDown(Key.SHIFT)){
					var thisx = clip._parent._xmouse - clickx;
					var thisy = clip._parent._ymouse - clicky;
					if (Math.abs(thisx) > Math.abs(thisy)){
						clip._x = clip._parent._xmouse - offx;
						clip._y = orig_y;
					}else{
						clip._x = orig_x;
						clip._y = clip._parent._ymouse - offy;
					}
				}else{
					clip._x = clip._parent._xmouse - offx;
					clip._y = clip._parent._ymouse - offy;
				}
				updateAfterEvent();
			}
			break;
		case "scale":
			var r = clip._parent.createEmptyMovieClip("FTScaleRegulator",60000);
			r.match(clip,"_rotation","_x","_y");
			var b = this.getBounds(this);
			var clickXscale = clip._xscale;
			var clickYscale = clip._yscale;
			var sx = clickXscale/(r._xmouse/b.xmin);
			var sy = clickYscale/(r._ymouse/b.ymin);
			this.onMouseMove = function(){
				if (Key.isDown(Key.SHIFT)){
					var scale = Math.max(((r._xmouse*sx/clickXscale)/b.xmin), ((r._ymouse*sy/clickYscale)/b.ymin));
					clip._xscale = clickXscale * scale;
					clip._yscale = clickYscale * scale;
				}else{
					clip._xscale = clickXscale * ((r._xmouse*sx/clickXscale)/b.xmin);
					clip._yscale = clickYscale * ((r._ymouse*sy/clickYscale)/b.ymin);
				}
				updateAfterEvent();
			}
			break;
		case "rotate":
			var clickAngle = clip.getMouseAngle();
			var clickRotation = clip._rotation;
			this.onMouseMove = function(){
				var r = clickRotation - clickAngle + clip.getMouseAngle();
				clip._rotation = (Key.isDown(Key.SHIFT)) ? r.snap(45,clickRotation) : r;
				updateAfterEvent();
			}	
			break;
		default: 
			trace("invalid FreeTransform tool specified: " + this.tool);
	}
}
MovieClip.prototype.getMouseAngle = function(){
	return Math.atan2(this._parent._ymouse-this._y, this._parent._xmouse-this._x) * 180/Math.PI;
}
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]];
}
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;	
}
MovieClip.prototype.enableFreeTransform = function(tool){
	switch(tool){
		case "none":
		case null:
		case undefined:
		case false:
		case 0:
			this.disableFreeTransForm();
			break;
		default:
			if (!this.FreeTransformHandler){
				this.createEmptyMovieClip("FreeTransformHandler",60001).hitArea = this;
				ASSetPropFlags(this,"FreeTransformHandler",1,1);
			}
			this.FreeTransformHandler.tool = tool;
			this.FreeTransformHandler.onPress = SimpleFreeTransform.onPress;
			this.FreeTransformHandler.onRelease = this.FreeTransformHandler.onReleaseOutside = SimpleFreeTransform.onRelease;
	}
}

MovieClip.prototype.disableFreeTransform = function(){
	this.FreeTransformHandler.tool = 0;
	delete this.FreeTransformHandler.onPress;
	delete this.FreeTransformHandler.onRelease;
	delete this.FreeTransformHandler.onReleaseOutside;
}