Archiv der Kategorie ‘ActionScript‘

 
 

As2 Blox

Every laptop I’ve ever had has just simply died on me eventually – kind of odd. Anyway, as I’ve mentioned before, at least every month I do a dvd backup of everything I’ve been working on. Commercial projects and personal projects alike. Every time my laptops die I end up loosing a few weeks of stuff – now, I rarely loose client work because I have weird trick – when I upload a client project to the dev server, I upload EVERYTHING, so it becomes an actual backup of the project. I guess I must have learned that the hard way – I know there have been about 3 times when I had to decompile an .swf to work on a project, but I can’t remember exactly why that was. My girlfriend is taking 4 of my old laptop and desktop hardrives and geting them all put onto one drive for my birthday. Pretty excited to see what I’ll discover. I was thinking about this, so I started looking through all the old DVDs again and I found this little thing:

This movie requires Flash Player 9

Here is the fla – unedited: DOWNLOAD

This is the 3D engine it uses:

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
Stage.scaleMode = "noScale";
function localReset() {
	lxr = 0;
	lyr = 0;
	lx = 0;
	ly = 0;
	lz = 0;
}
gz = 0;
gx = 0;
gy = 0;
gxr = 0;
gyr = 0;
localReset();
centerX = 300;
centerY = 220;
rads = Math.PI/180;
sin = new Array();
cos = new Array();
for (var i = 0; i<720; i++) {
	sin[i] = Math.sin(i*(Math.PI/180));
}
for (var i = 0; i<720; i++) {
	cos[i] = Math.cos(i*(Math.PI/180));
}
lx = 0;
ly = 0;
lz;
// calculate 3d coards no 2d translation;
function l3d(_mx, my, mz) {
	zpos = ((lz+mz)*cos[lxr])-((lx+_mx)*sin[lxr]);
	xpos = ((lz+mz)*sin[lxr])+((lx+_mx)*cos[lxr]);
	ypos = ((ly+my)*cos[lyr])-(zpos*sin[lyr]);
	zpos = ((ly+my)*sin[lyr])+(zpos*cos[lyr]);
	//3rd one 
	apoint = [xpos, ypos, zpos];
	return apoint;
}
//////////////////////////////
// translate 3d coards to 2D 
//////////////////////////////
function p3d(_mx, my, mz) {
	zpos = ((gz+mz)*cos[gxr])-((gx+_mx)*sin[gxr]);
	xpos = ((gz+mz)*sin[gxr])+((gx+_mx)*cos[gxr]);
	ypos = ((gy+my)*cos[gyr])-(zpos*sin[gyr]);
	zpos = ((gy+my)*sin[gyr])+(zpos*cos[gyr]);
	dep = 1/((zpos/99390)+1);
	contrast = 1/((zpos/150)+1);
	//3rd one 
	apoint = [xpos*dep+centerX, ypos*dep+centerY, zpos];
	return apoint;
}
function skewObj(obj, mcW, mcH, pt0, ptH, ptW) {
	function distance(pt1, pt2) {
		var dy = pt2.y-pt1.y;
		var dx = pt2.x-pt1.x;
		var side = Math.sqrt(dy*dy+dx*dx);
		return side;
	}
	// 
	// pt0 = {x:p0._x, y:p0._y};
	// ptH = {x:pH._x, y:pH._y};
	// ptW = {x:pW._x, y:pW._y};
	// 
	obj._x = pt0.x;
	obj._y = pt0.y;
	obj._yscale = 100;
	var angleP2 = Math.atan2(ptW.y-pt0.y, ptW.x-pt0.x);
	var angleP1 = Math.atan2(ptH.y-pt0.y, ptH.x-pt0.x);
	var dAngle = (angleP1-angleP2)/2;
	var arm = Math.sqrt(2)/2/Math.cos(dAngle);
	// original a 100x100 model , now use 1x1 model
	obj._rotation = (180/Math.PI)*(angleP1-dAngle);
	obj.nest._rotation = -45;
	obj._yscale = 100*Math.tan(dAngle);
	obj.nest._xscale = distance(ptW, pt0)*100/arm/mcW;
	obj.nest._yscale = distance(ptH, pt0)*100/arm/mcH;
}

Despite the cluttered/messy style of the code and a few weird mistakes like the nesting of the distance function and a few other things. This code is actually kind of interesting, because it shows how we used to do 3D stuff and how we used to skew movieClips. The p3d function was based on code that I saw at http://wireframe.co.za/ I changed some stuff about it though, I cached the sin/cos function calls and added another function so that I could nest 3d transformations to give objects a local coordinate system. The skewing code was from Eric Lin. I may or may not have tweaked the skew code, I can’t remember.

The function for making a “blox”. Looks like this, you can see the thought process where I decided not to have top and bottom side for a cube:

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
pts = new Array();
pre = new Array();
function box(pX, pY, pZ) {
	// left
	lx = pX;
	lz = 10+pZ;
	ly = pY;
	pre[inc] = l3d(50, 50, 0);
	pre[inc+1] = l3d(-50, 50, 0);
	pre[inc+2] = l3d(50, -50, 0);
	inc += 3;
	// front
	lx = 10+pX;
	ly = pY;
	lz = pZ;
	pre[inc] = l3d(0, 50, 50);
	pre[inc+1] = l3d(0, 50, -50);
	pre[inc+2] = l3d(0, -50, 50);
	inc += 3;
	// right 
	lx = pX;
	lz = 50+pZ;
	ly = pY;
	pre[inc] = l3d(50, 50, 0);
	pre[inc+1] = l3d(-50, 50, 0);
	pre[inc+2] = l3d(50, -50, 0);
	inc += 3;
	// top
	/*lx = pX+1;
	lz = 60+pZ;
	ly = pY+62;
	pre[inc] = l3d(50, 0, -50);
	pre[inc+1] = l3d(-50, 0, -50);
	pre[inc+2] = l3d(50, 0, 50);
	inc += 3;*/
	//back
	lx = 50+pX;
	ly = pY;
	lz = pZ;
	pre[inc] = l3d(0, 50, 50);
	pre[inc+1] = l3d(0, 50, -50);
	pre[inc+2] = l3d(0, -50, 50);
	inc += 3;
}

Kind of interesting that I’m storing all the blox points in one array. Then when I draw, I alter the values in the array and end by looping through it and drawing each point:

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
this.onEnterFrame = function() {
 
	inc = 0;
	for (var i = 0; i<10; i++) {
		spindle[i] += rinc[i];
		mindle[i] += zinc[i];
		lxr = spindle[i]%360;
		lyr = mindle[i]%360
		box(rx[i], ry[i], 0);
	}
	tint = (inc/3)+2;
	//
	if (_xmouse>10 && _xmouse<500) {
		xdest = _xmouse;
	}
	if (_ymouse>10 && _ymouse<500) {
		ydest = _ymouse;
	}
	active = true;
	gxr += ((xdest)-gxr)/5;
	gyr += ((ydest)-gyr)/5;
	gxr = int(gxr);
	gyr = int(gyr);
	localReset();
	inc = 0;
	for (var i = 0; i<tint; i++) {
		pts[0] = p3d(pre[inc][0], pre[inc][1], pre[inc][2]);
		pts[1] = p3d(pre[inc+1][0], pre[inc+1][1], pre[inc+1][2]);
		pts[2] = p3d(pre[inc+2][0], pre[inc+2][1], pre[inc+2][2]);
		pt0 = {x:pts[0][0], y:pts[0][1]};
		ptH = {x:pts[1][0], y:pts[1][1]};
		ptW = {x:pts[2][0], y:pts[2][1]};
		dup = this["plane"+i];
		skewObj(dup, 100, 100, pt0, ptH, ptW);
 
		val = 4000+int(((pts[0][2]+pts[1][2]+pts[2][2])/3)*20);
		dup.swapDepths((val));
 
		dup._visible = true;
		inc += 3;
	}
};

It’s kind of like some of the OpenGL ES stuff I’ve been doing lately where I make heavy use of glDrawArrays() and array manipulation.

I used this basic 3D engine a bunch of times back in 2006-07. If you dig around you’ll find other instances of it here: old daily log.

Here is another one that uses the same engine:

This movie requires Flash Player 9

I also used this same 3D technique back in my director days 2002-04 – and java days too: Catch Env.

This link is also a great resource if your interested in simple 3D engines:

http://freespace.virgin.net/hugo.elias/routines/3d_to_2d.htm

Circle Intersections w/ Raphael

I was discussing an interesting problem with a friend of mine awhile back – it relates to simulating the intersection of two or more 2d bubbles. This turns out to be trickier than you might expect. The first sketch I created regarding this problem was this:

I used circle intersection logic from Paule Bourke. (That really is one of my favorite websites).

The above is interesting, but taking it further will be tricky – it looks like some kind of Voronoi variation might be the way to go.

Here is the main source:

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
 var r = new Raphael(0, 0, 500, 500);
 
var CIRCLE_NUM = 4;
var circles = [];
var lines = [];
 
// make some randomly positioned circles
for (var i = 0; i < CIRCLE_NUM; i++){
  circles.push(r.circle(Math.random() * 150 + 150, 
                        Math.random() * 150 + 150, 
                        60)
               .attr({fill: "rgba(81, 121, 200, 0.3)"}));
}
 
var line = r.path();
var path = "";
 
render();
dragAndDrop();
 
function render() {
  path = "";
  redPath = "";
  lines = [];
  var leng = circles.length;
  for (var i = 0; i<leng; i++){
    for (var j = i + 1; j<leng; j++){
      circleIntersection(circles[i], circles[j]);
    }
  }
}
 
// easy to understand explanation here:
// http://paulbourke.net/geometry/2circle/
function circleIntersection(a, b) {
  var a, h, cx, cy, px, py;
  var ax = a.attr("cx");
  var ay = a.attr("cy");
  var bx = b.attr("cx");
  var by = b.attr("cy");
  var ra = a.attr("r");
  var rb = b.attr("r");
 
  var dx = Math.abs(ax - bx);
  var dy = Math.abs(ay - by);
 
  var d = Math.sqrt(dx * dx + dy * dy);
 
  if (d > (ra + rb)) {
    // no solutions
  } else if (d < Math.abs(ra - rb)) {
    // no collisions, one inside other
  } else if (d == 0 && ra == rb) {
    // circles are coincident   
  } else {
    // there is a collision
    a = (ra * ra - rb * rb + d * d) / (2 * d);
    h = Math.sqrt(ra * ra - a * a);
    cx = ax + a * (bx - ax) / d;
    cy = ay + a * (by - ay) / d;
 
    // point c (draw here)
 
    var tx = h * (by - ay) / d;
    var ty = h * (bx - ax) / d;
    px = cx + tx;
    py = cy - ty;
 
    var ln = {a:{x:px, y:py}};
 
    path += "M " + px + " " + py + " ";
 
    px = cx - tx;
    py = cy + ty;
 
    ln.b = {x:px, y:py};
 
    path += "L " + px + " " + py + " ";
 
    line.attr({path: path});
 
    lines.push(ln);
  }
}
 
function dragAndDrop(){
  var circs = r.set();
  for (var i = 0; i < circles.length; i++) {
    circs.push(circles[i]);
  }
  circs.drag(function(dx, dy) {
    this.attr({cx: this.ox + dx, cy: this.oy + dy});
    render();
  }, function() {
    this.ox = this.attr("cx");
    this.oy = this.attr("cy");
  });
}

On a side note, you can use this old-school gradient circle technique to create something similar:

Lately I’ve been speed coding actionscript, so no variable typing and no holding back on weird/bad tricks. Sometimes the result is unreadable – other times it looks like elegant pseudo-code (which one is this?):

This is the code for the above image.

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
[SWF(width=400, height=400, frameRate=1, backgroundColor=0xFFFFFF)]
 
var m = new Matrix();
var BUB_NUM = 30;
 
for (var i = 0; i < BUB_NUM; i++)
  bubble(Math.random() * stage.stageWidth, 
         Math.random() * stage.stageHeight);
 
function bubble(xp, yp) {
	var bub = addChild(new Sprite());
	var rad = Math.random() * 20 + 50;
	var diam = rad * 2;
	m.createGradientBox(diam, diam, 0, -rad, -rad);
	with(bub.graphics) {
		beginGradientFill("radial", 
				  [0, 0xFFFFFF], 
				  [1,1], 
				  [0,255], m);
		drawCircle(0, 0, rad);
	}
	with(bub){
	  x = xp;
	  y = yp;
	  blendMode = "darken";
	  cacheAsBitmap = true;
	}
}

Not sure what my final solution will be… should be interesting.

describeType Reflection

The describeType utility function generates xml from a given class. It’s pretty straight forward:

trace(describeType(MovieClip));

Will give us this chunk of xml:

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
<type name="flash.display::MovieClip" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.display::MovieClip">
    <extendsClass type="flash.display::Sprite"/>
    <extendsClass type="flash.display::DisplayObjectContainer"/>
    <extendsClass type="flash.display::InteractiveObject"/>
    <extendsClass type="flash.display::DisplayObject"/>
    <extendsClass type="flash.events::EventDispatcher"/>
    <extendsClass type="Object"/>
    <implementsInterface type="flash.events::IEventDispatcher"/>
    <implementsInterface type="flash.display::IBitmapDrawable"/>
    <accessor name="root" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
    <accessor name="stage" access="readonly" type="flash.display::Stage" declaredBy="flash.display::DisplayObject"/>
    <accessor name="scenes" access="readonly" type="Array" declaredBy="flash.display::MovieClip"/>
    <accessor name="alpha" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="visible" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
    <accessor name="graphics" access="readonly" type="flash.display::Graphics" declaredBy="flash.display::Sprite"/>
    <accessor name="mask" access="readwrite" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
    <accessor name="currentLabel" access="readonly" type="String" declaredBy="flash.display::MovieClip"/>
    <accessor name="mouseX" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="currentFrameLabel" access="readonly" type="String" declaredBy="flash.display::MovieClip"/>
    <accessor name="mouseY" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="scaleZ" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="currentLabels" access="readonly" type="Array" declaredBy="flash.display::MovieClip"/>
    <accessor name="rotationX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="rotationY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="rotationZ" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="cacheAsBitmap" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
    <accessor name="tabIndex" access="readwrite" type="int" declaredBy="flash.display::InteractiveObject"/>
    <accessor name="opaqueBackground" access="readwrite" type="Object" declaredBy="flash.display::DisplayObject"/>
    <accessor name="scrollRect" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
    <accessor name="filters" access="readwrite" type="Array" declaredBy="flash.display::DisplayObject"/>
    <accessor name="width" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="blendMode" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
    <accessor name="transform" access="readwrite" type="flash.geom::Transform" declaredBy="flash.display::DisplayObject"/>
    <accessor name="name" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
    <accessor name="scale9Grid" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
    <accessor name="mouseChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
    <accessor name="tabChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
    <accessor name="height" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="useHandCursor" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
    <accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
      <metadata name="Inspectable">
        <arg key="environment" value="none"/>
      </metadata>
    </accessor>
    <accessor name="focusRect" access="readwrite" type="Object" declaredBy="flash.display::InteractiveObject"/>
    <accessor name="loaderInfo" access="readonly" type="flash.display::LoaderInfo" declaredBy="flash.display::DisplayObject"/>
    <accessor name="accessibilityProperties" access="readwrite" type="flash.accessibility::AccessibilityProperties" declaredBy="flash.display::DisplayObject"/>
    <accessor name="scaleX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="buttonMode" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
    <accessor name="scaleY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="dropTarget" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::Sprite"/>
    <accessor name="blendShader" access="writeonly" type="flash.display::Shader" declaredBy="flash.display::DisplayObject"/>
    <accessor name="trackAsMenu" access="readwrite" type="Boolean" declaredBy="flash.display::MovieClip"/>
    <accessor name="parent" access="readonly" type="flash.display::DisplayObjectContainer" declaredBy="flash.display::DisplayObject"/>
    <accessor name="hitArea" access="readwrite" type="flash.display::Sprite" declaredBy="flash.display::Sprite"/>
    <accessor name="soundTransform" access="readwrite" type="flash.media::SoundTransform" declaredBy="flash.display::Sprite"/>
    <accessor name="mouseEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
    <accessor name="rotation" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="numChildren" access="readonly" type="int" declaredBy="flash.display::DisplayObjectContainer"/>
    <accessor name="x" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="y" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="z" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
    <accessor name="doubleClickEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
    <accessor name="textSnapshot" access="readonly" type="flash.text::TextSnapshot" declaredBy="flash.display::DisplayObjectContainer"/>
    <accessor name="contextMenu" access="readwrite" type="flash.ui::ContextMenu" declaredBy="flash.display::InteractiveObject"/>
    <accessor name="tabEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
    <accessor name="currentScene" access="readonly" type="flash.display::Scene" declaredBy="flash.display::MovieClip"/>
    <accessor name="currentFrame" access="readonly" type="int" declaredBy="flash.display::MovieClip"/>
    <accessor name="framesLoaded" access="readonly" type="int" declaredBy="flash.display::MovieClip"/>
    <accessor name="totalFrames" access="readonly" type="int" declaredBy="flash.display::MovieClip"/>
    <accessor name="enabled" access="readwrite" type="Boolean" declaredBy="flash.display::MovieClip"/>
    <method name="getChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
      <parameter index="1" type="int" optional="false"/>
    </method>
    <method name="addEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Function" optional="false"/>
      <parameter index="3" type="Boolean" optional="true"/>
      <parameter index="4" type="int" optional="true"/>
      <parameter index="5" type="Boolean" optional="true"/>
    </method>
    <method name="dispatchEvent" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
      <parameter index="1" type="flash.events::Event" optional="false"/>
    </method>
    <method name="hasEventListener" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
      <parameter index="1" type="String" optional="false"/>
    </method>
    <method name="toString" declaredBy="flash.events::EventDispatcher" returnType="String"/>
    <method name="willTrigger" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
      <parameter index="1" type="String" optional="false"/>
    </method>
    <method name="removeEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Function" optional="false"/>
      <parameter index="3" type="Boolean" optional="true"/>
    </method>
    <method name="areInaccessibleObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
      <parameter index="1" type="flash.geom::Point" optional="false"/>
    </method>
    <method name="globalToLocal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
      <parameter index="1" type="flash.geom::Point" optional="false"/>
    </method>
    <method name="localToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
      <parameter index="1" type="flash.geom::Point" optional="false"/>
    </method>
    <method name="getBounds" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="getRect" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="prevScene" declaredBy="flash.display::MovieClip" returnType="void"/>
    <method name="nextScene" declaredBy="flash.display::MovieClip" returnType="void"/>
    <method name="hitTestObject" declaredBy="flash.display::DisplayObject" returnType="Boolean">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="setChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
      <parameter index="2" type="int" optional="false"/>
    </method>
    <method name="hitTestPoint" declaredBy="flash.display::DisplayObject" returnType="Boolean">
      <parameter index="1" type="Number" optional="false"/>
      <parameter index="2" type="Number" optional="false"/>
      <parameter index="3" type="Boolean" optional="true"/>
    </method>
    <method name="globalToLocal3D" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Vector3D">
      <parameter index="1" type="flash.geom::Point" optional="false"/>
    </method>
    <method name="contains" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="startDrag" declaredBy="flash.display::Sprite" returnType="void">
      <parameter index="1" type="Boolean" optional="true"/>
      <parameter index="2" type="flash.geom::Rectangle" optional="true"/>
    </method>
    <method name="removeChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
      <parameter index="1" type="int" optional="false"/>
    </method>
    <method name="local3DToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
      <parameter index="1" type="flash.geom::Vector3D" optional="false"/>
    </method>
    <method name="getChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="int">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="stopTouchDrag" declaredBy="flash.display::Sprite" returnType="void">
      <parameter index="1" type="int" optional="false"/>
      <metadata name="API">
        <arg key="" value="667"/>
      </metadata>
    </method>
    <method name="stop" declaredBy="flash.display::MovieClip" returnType="void"/>
    <method name="stopDrag" declaredBy="flash.display::Sprite" returnType="void"/>
    <method name="getChildByName" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
      <parameter index="1" type="String" optional="false"/>
    </method>
    <method name="startTouchDrag" declaredBy="flash.display::Sprite" returnType="void">
      <parameter index="1" type="int" optional="false"/>
      <parameter index="2" type="Boolean" optional="true"/>
      <parameter index="3" type="flash.geom::Rectangle" optional="true"/>
      <metadata name="API">
        <arg key="" value="667"/>
      </metadata>
    </method>
    <method name="swapChildren" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
      <parameter index="2" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="swapChildrenAt" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
      <parameter index="1" type="int" optional="false"/>
      <parameter index="2" type="int" optional="false"/>
    </method>
    <method name="getObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Array">
      <parameter index="1" type="flash.geom::Point" optional="false"/>
    </method>
    <method name="play" declaredBy="flash.display::MovieClip" returnType="void"/>
    <method name="addChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="nextFrame" declaredBy="flash.display::MovieClip" returnType="void"/>
    <method name="prevFrame" declaredBy="flash.display::MovieClip" returnType="void"/>
    <method name="addChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
      <parameter index="2" type="int" optional="false"/>
    </method>
    <method name="gotoAndPlay" declaredBy="flash.display::MovieClip" returnType="void">
      <parameter index="1" type="Object" optional="false"/>
      <parameter index="2" type="String" optional="true"/>
    </method>
    <method name="removeChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
      <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    </method>
    <method name="gotoAndStop" declaredBy="flash.display::MovieClip" returnType="void">
      <parameter index="1" type="Object" optional="false"/>
      <parameter index="2" type="String" optional="true"/>
    </method>
    <method name="addFrameScript" declaredBy="flash.display::MovieClip" returnType="void">
      <metadata name="Inspectable">
        <arg key="environment" value="none"/>
      </metadata>
    </method>
  </factory>
</type>

When dealing with regular objects we can iterate over their properties like this:

var o:Object = {a:1, b:2, c:3};
 
for (var i:String in o){
	trace(i, "=", o[i]);
}

Which results in:

a = 1
b = 2
c = 3

Trying to do the same over a MovieClip only works for dynamic properties:

var clip:MovieClip = new MovieClip();
clip.dynamicProp = 1;
for (var i:String in clip){
	trace(i, "=", clip[i]);
}

Resulting in:

dynamicProp = 1

If we want to see all the other properties we need to use describeType:

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
var clip:MovieClip = new MovieClip();
 
getProps(clip);
 
function getProps(target:*):void{
	var description:XML = describeType(target);
	var i:XML,name:String,access:String;
 
	for each (i in description.accessor){
		access = i.@access;
		name = i.@name;
		if (access == "readonly"){
			traceProp(target, name);
		}else if (access == "readwrite"){
			traceProp(target, name);
		}else{
			// writeonly
			trace(name);
		}
	}
}
 
function traceProp(target:*, key:*):void{
	trace(key, "=", target[key]);
}

Which will give us:

root = null
stage = null
scenes = [object Scene]
alpha = 1
visible = true
graphics = [object Graphics]
mask = null
currentLabel = null
mouseX = 800
currentFrameLabel = null
mouseY = 445
scaleZ = 1
currentLabels = 
rotationX = 0
rotationY = 0
rotationZ = 0
cacheAsBitmap = false
tabIndex = -1
opaqueBackground = null
scrollRect = null
filters = 
width = 0
blendMode = normal
transform = [object Transform]
name = instance1
scale9Grid = null
mouseChildren = true
tabChildren = true
height = 0
useHandCursor = true
accessibilityImplementation = null
focusRect = null
loaderInfo = null
accessibilityProperties = null
scaleX = 1
buttonMode = false
scaleY = 1
dropTarget = null
blendShader
trackAsMenu = false
parent = null
hitArea = null
soundTransform = [object SoundTransform]
mouseEnabled = true
rotation = 0
numChildren = 0
x = 0
y = 0
z = 0
doubleClickEnabled = false
textSnapshot = [object TextSnapshot]
contextMenu = null
tabEnabled = false
currentScene = [object Scene]
currentFrame = 0
framesLoaded = 1
totalFrames = 1
enabled = true

Getting at the method signatures doesn’t require too much additional work:

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
var clip:MovieClip = new MovieClip();
 
getInfo(clip);
 
function getInfo(target:*):void{
	var description:XML = describeType(target);
	var i:XML,name:String,access:String;
 
	for each (i in description.accessor){
		access = i.@access;
		name = i.@name;
		if (access == "readonly"){
			traceProp(target, name);
		}else if (access == "readwrite"){
			traceProp(target, name);
		}else{
			// writeonly
			trace(name);
		}
	}
	for each (i in description.method){
		traceMethod(i);
	}
}
function traceMethod(node:XML):void{
	var signature:String = node.@name + "(";
	var optional:Boolean = false;
	var type:String;
	if (node.parameter.length()){
		for each (var i in node.parameter){
			if (i.@optional == "true" && ! optional){
				optional = true;
				signature +=  "[";
			}
			// remove package name;
			type = i.@type;
			type = type.replace(/(.*?)::/,"");
 
			signature +=  type + ",";
		}
		signature = signature.substr(0,signature.length - 1);
		if (optional){
			signature +=  "]";
		}
	}
	signature +=  ")";
	trace(signature);
}
 
function traceProp(target:*, key:*):void{
	//trace(key, "=", target[key]);
}

I’ve commented out the implementation of traceProp() to avoid clutter, so the result is:

blendShader
getChildAt(int)
addEventListener(String,Function,[Boolean,int,Boolean])
dispatchEvent(Event)
hasEventListener(String)
toString()
willTrigger(String)
removeEventListener(String,Function,[Boolean])
areInaccessibleObjectsUnderPoint(Point)
globalToLocal(Point)
localToGlobal(Point)
getBounds(DisplayObject)
getRect(DisplayObject)
prevScene()
nextScene()
hitTestObject(DisplayObject)
setChildIndex(DisplayObject,int)
hitTestPoint(Number,Number,[Boolean])
globalToLocal3D(Point)
contains(DisplayObject)
startDrag([Boolean,Rectangle])
removeChildAt(int)
local3DToGlobal(Vector3D)
getChildIndex(DisplayObject)
stopTouchDrag(int)
stop()
stopDrag()
getChildByName(String)
startTouchDrag(int,[Boolean,Rectangle])
swapChildren(DisplayObject,DisplayObject)
swapChildrenAt(int,int)
getObjectsUnderPoint(Point)
play()
addChild(DisplayObject)
nextFrame()
prevFrame()
addChildAt(DisplayObject,int)
gotoAndPlay(Object,[String])
removeChild(DisplayObject)
gotoAndStop(Object,[String])
addFrameScript()

I like this approach for reflection. It’s very flexible. There are lots of applications for this type of thing. I assume that things like MonsterDebugger make heavy use of this.

Awhile back I started working on something that would automatically generate UI for a given class. I didn’t take it very far…. have a look: http://actionsnippet.com/?p=1425