Home > 梅原 > ジンバルロックを体験してみよう!3(ビルトイン関数編)

ジンバルロックを体験してみよう!3(ビルトイン関数編)

20090731
Category:梅原 /Tags:,

ジンバルロックを体験してみよう!3(ビルトイン関数編)PV3Dでのジンバルロックを確認するのもよいけど、ビルトイン関数ではどうなんだろう、ということで作ってみた。

Get Adobe Flash player

★ジンバルロックを体験してみよう!3

0.左上のrotationXYZの立方体に注目
1.初期状態(又はReset後)に「Y+=30」を三回クリックして、
Y軸90度回転をする。
2.「Z+=30」をクリックしてみる。Z軸回転したことを確認。
3.「Z-=30」をクリックして戻す。
4.「X-=30」をクリックすると、、、アレレ!「Z+=30」と同じ
Z軸回転しちゃうぞ!
これがジンバルロックであります。
いろいろ回転させていろいろ試してくださいませ。

=============================

AS3.0(FP10)のビルトイン関数における、
rotationX,appendRotation,prependRotation
の使い分け。Pepervision3D(PV3D)との比較。

PV3D版★ジンバルロックを体験してみよう!
と見比べながら読むことを推奨。

まずそもそも、X,Zをクリックした時の回転方向が異なることに注目。
これは、PV3Dが左手系、ビルトイン関数では右手系であることによる違い。
正確にはX,Zが違うというより、Yが逆になっている。
PV3Dは既存のグラフィック系3Dソフトのセオリーに従った結果、
ビルトイン関数の方は、なによりこれまでのFlashの体系を優先させた結果だと思う。

■rotationXYZ
簡単なものなら、rotationXで足りるものもあるんだろうけど、
自在に回転させるとなると、どうしてもジンバルロックが問題になる。
値がわかりやすいってのが強み。
PV3DのrotationXYZに相当(名前も同じだから間違えないね!)。

■appendRotation
内部的にはQuaternionを使っているので、ジンバルロックが無い。
PV3DのQuaternionに相当。

■prependRotation
内部的にはQuaternionを使っているので、ジンバルロックが無い。
PV3DのlocalRotationXYZに相当。

参考
http://blog.r3c7.net/?p=193
http://www.kuma-de.com/blog/1-application/1-flash/2009-04-19/395

▼Wonderfl
http://wonderfl.net/code/35c2aac390baca65de536ca2d938336d691e758d

▼ActionScript AS3(FP9)

/*
 * ★ジンバルロックを体験してみよう!3
 *
 * 0.左上のrotationXYZの立方体に注目
 * 1.初期状態(又はReset後)に「Y+=30」を三回クリックして、
 * Y軸90度回転をする。
 * 2.「Z+=30」をクリックしてみる。Z軸回転したことを確認。
 * 3.「Z-=30」をクリックして戻す。
 * 4.「X-=30」をクリックすると、、、アレレ!「Z+=30」と同じ
 * Z軸回転しちゃうぞ!
 * これがジンバルロックであります。
 * いろいろ回転させていろいろ試してくださいませ。
 *
 * =============================
 *
 * AS3.0(FP10)のビルトイン関数における、
 * rotationX,appendRotation,prependRotation
 * の使い分け。Pepervision3D(PV3D)との比較。
 *
 * PV3D版★ジンバルロックを体験してみよう!
 * http://wonderfl.net/code/2d5664a811359bb65aeebb97422f4668250a74c9
 * と見比べながら読むことを推奨。
 *
 *
 * まずそもそも、X,Zをクリックした時の回転方向が異なることに注目。
 * これは、PV3Dが左手系、ビルトイン関数では右手系であることによる違い。
 * 正確にはX,Zが違うというより、Yが逆になっている。
 * PV3Dは既存のグラフィック系3Dソフトのセオリーに従った結果、
 * ビルトイン関数の方は、なによりこれまでのFlashの体系を優先させた結果だと思う。
 *
 *
 * ■rotationXYZ
 * 簡単なものなら、rotationXで足りるものもあるんだろうけど、
 * 自在に回転させるとなると、どうしてもジンバルロックが問題になる。
 * 値がわかりやすいってのが強み。
 * PV3DのrotationXYZに相当(名前も同じだから間違えないね!)。
 *
 * ■appendRotation
 * 内部的にはQuaternionを使っているので、ジンバルロックが無い。
 * PV3DのQuaternionに相当。
 *
 * ■prependRotation
 * 内部的にはQuaternionを使っているので、ジンバルロックが無い。
 * PV3DのlocalRotationXYZに相当。
 *
 *
 * 参考
 * http://blog.r3c7.net/?p=193
 * http://www.kuma-de.com/blog/1-application/1-flash/2009-04-19/395
 */

package{
	import flash.display.Sprite;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.geom.Matrix3D;
	import flash.geom.PerspectiveProjection;
	import flash.geom.Point;
	import flash.geom.Vector3D;
	import flash.display.SimpleButton;
	import flash.text.TextField;
	import flash.events.MouseEvent;

	[SWF(width="465", height="465", frameRate="30", backgroundColor="0")]
	public class Main extends Sprite {
		private var pp:PerspectiveProjection = new PerspectiveProjection();
		private var viewStage:Sprite = new Sprite();
		public function Main():void {

			addChild(viewStage);

			//立方体を生成
			var c0:Sprite = Primitives.colorCube(75,75,75);
			c0.x = 465/2-110;
			c0.y = 465/2-110;
			c0.z = 0;
			pp.projectionCenter = new Point(c0.x,c0.y);
			c0.transform.perspectiveProjection = pp;
			viewStage.addChild(c0);
			var c1:Sprite = Primitives.colorCube(75,75,75);
			c1.x = 465/2+110;
			c1.y = 465/2-110;
			c1.z = 0;
			pp.projectionCenter = new Point(c1.x,c1.y);
			c1.transform.perspectiveProjection = pp;
			viewStage.addChild(c1);
			var c2:Sprite = Primitives.colorCube(75,75,75);
			c2.x = 465/2;
			c2.y = 465/2+65;
			c2.z = 0;
			pp.projectionCenter = new Point(c2.x,c2.y);
			c2.transform.perspectiveProjection = pp;
			viewStage.addChild(c2);

			//Button
			var btnX1:SimpleButton = Create.newSimpleButton([5,396,60,20,"X+=30"]);
			var btnX0:SimpleButton = Create.newSimpleButton([70, 396, 60, 20, "X-=30"]);
			var btnY1:SimpleButton = Create.newSimpleButton([5,418,60,20,"Y+=30"]);
			var btnY0:SimpleButton = Create.newSimpleButton([70, 418, 60, 20, "Y-=30"]);
			var btnZ1:SimpleButton = Create.newSimpleButton([5,440,60,20,"Z+=30"]);
			var btnZ0:SimpleButton = Create.newSimpleButton([70, 440, 60, 20, "Z-=30"]);
			var reset:SimpleButton = Create.newSimpleButton([400, 440, 60, 20, "Reset"]);
			btnX1.name = "X1";
			btnX0.name = "X0";
			btnY1.name = "Y1";
			btnY0.name = "Y0";
			btnZ1.name = "Z1";
			btnZ0.name = "Z0";
			btnX1.addEventListener(MouseEvent.CLICK, CLICK);
			btnX0.addEventListener(MouseEvent.CLICK, CLICK);
			btnY1.addEventListener(MouseEvent.CLICK, CLICK);
			btnY0.addEventListener(MouseEvent.CLICK, CLICK);
			btnZ1.addEventListener(MouseEvent.CLICK, CLICK);
			btnZ0.addEventListener(MouseEvent.CLICK, CLICK);
			reset.addEventListener(MouseEvent.CLICK, resetCLICK);
			addChild(btnX1);
			addChild(btnX0);
			addChild(btnY1);
			addChild(btnY0);
			addChild(btnZ1);
			addChild(btnZ0);
			addChild(reset);

			//TextField
			var tfc0:TextField = Create.newTextField( { x:c0.x-50, y:c0.y-10,width:100,height:20,text:"rotationXYZ",textColor:0xFFFFFF ,selectable:false,setTextFormat:[{align:"center"}]} )
			var tfc1:TextField = Create.newTextField( { x:c1.x-50, y:c1.y-10,width:100,height:20,text:"appendRotation",textColor:0xFFFFFF ,selectable:false,setTextFormat:[{align:"center"}]} )
			var tfc2:TextField = Create.newTextField( { x:c2.x-50, y:c2.y-10,width:100,height:20,text:"prependRotation",textColor:0xFFFFFF ,selectable:false,setTextFormat:[{align:"center"}]} )
			addChild(tfc0);
			addChild(tfc1);
			addChild(tfc2);

			//rotationXYZ
			var tf0x:TextField = Create.newTextField({x:5,y:5,width:120,height:20,text:"rotationX",textColor:0xFFFFFF,selectable:false});
			var tf0y:TextField = Create.newTextField({x:5,y:25,width:120,height:20,text:"rotationY",textColor:0xFFFFFF,selectable:false});
			var tf0z:TextField = Create.newTextField({x:5,y:45,width:120,height:20,text:"rotationZ",textColor:0xFFFFFF,selectable:false});
			addChild(tf0x);
			addChild(tf0y);
			addChild(tf0z);

			//appendRotation
			var tf1x:TextField = Create.newTextField({x:340,y:5,width:120,height:20,text:"rotationX",textColor:0xFFFFFF,selectable:false});
			var tf1y:TextField = Create.newTextField({x:340,y:25,width:120,height:20,text:"rotationY",textColor:0xFFFFFF,selectable:false});
			var tf1z:TextField = Create.newTextField({x:340,y:45,width:120,height:20,text:"rotationZ",textColor:0xFFFFFF,selectable:false});
			addChild(tf1x);
			addChild(tf1y);
			addChild(tf1z);

			//prependRotation
			var tf2x:TextField = Create.newTextField({x:300,y:315,width:120,height:20,text:"rotationX",textColor:0xFFFFFF,selectable:false});
			var tf2y:TextField = Create.newTextField({x:300,y:335,width:120,height:20,text:"rotationY",textColor:0xFFFFFF,selectable:false});
			var tf2z:TextField = Create.newTextField({x:300,y:355,width:120,height:20,text:"rotationZ",textColor:0xFFFFFF,selectable:false});
			addChild(tf2x);
			addChild(tf2y);
			addChild(tf2z);

			function CLICK(e:MouseEvent = null):void {
				if (count > 0) { return };
				var axis:String = e.currentTarget.name.substr(0,1);
				var d:Number = Number(e.currentTarget.name.substr(1, 1))*60-30;
				if ("X" == axis) {
					toRotationXYZ[0] = d;
				}else if ("Y" == axis) {
					toRotationXYZ[1] = d;
				}else if ("Z" == axis) {
					toRotationXYZ[2] = d;
				}
				count = 10;
			}
			function resetCLICK(e:MouseEvent):void {
				c0.rotationX = c0.rotationY = c0.rotationZ = 0;
				c1.rotationX = c1.rotationY = c1.rotationZ = 0;
				c2.rotationX = c2.rotationY = c2.rotationZ = 0;
				rotationXYZ = [0, 0, 0];
				toRotationXYZ = [0, 0, 0];
				count = 1;
			}
			var toRotationXYZ:Array = [0,0,0];
			var rotationXYZ:Array = [0, 0, 0];
			var count:int = 1;

			addEventListener(Event.ENTER_FRAME, onEnterFrame);

			function onEnterFrame(e:Event):void {
				if (count <= 0) { return };
				count --;
				var _x:Number = toRotationXYZ[0] * 0.1;
				var _y:Number = toRotationXYZ[1] * 0.1;
				var _z:Number = toRotationXYZ[2] * 0.1;
				if (count == 0) {
					toRotationXYZ[0] = toRotationXYZ[1] = toRotationXYZ[2] = 0;
				}

				//左上の立方体に対してはrotationX,Y,Zの値を変更
				c0.rotationX += _x;
				c0.rotationY += _y;
				c0.rotationZ += _z;

				var poz:Vector3D;
				var degrees:Number;
				var vec:Vector3D;
				//右上の立方体に対してはappendRotationでX,Y,Zの値を変更
				poz = c1.transform.matrix3D.position;
				c1.transform.matrix3D.position = new Vector3D();
				degrees = Math.sqrt(_x * _x + _y * _y + _z * _z);
				vec = new Vector3D(_x, _y, _z);
				vec.normalize();
				c1.transform.matrix3D.appendRotation(degrees, vec);
				c1.transform.matrix3D.position = poz;
				/*上の記述は以下と同じ
				poz = c1.transform.matrix3D.position;
				c1.transform.matrix3D.appendTranslation(-poz.x,-poz.y,-poz.z);
				c1.transform.matrix3D.appendRotation(_x, Vector3D.X_AXIS);
				c1.transform.matrix3D.appendRotation(_y, Vector3D.Y_AXIS);
				c1.transform.matrix3D.appendRotation(_z, Vector3D.Z_AXIS);
				c1.transform.matrix3D.appendTranslation(poz.x,poz.y,poz.z);
				*/

				//中央下の立方体に対してはprependRotationでX,Y,Zの値を変更
				poz = c2.transform.matrix3D.position;
				c2.transform.matrix3D.position = new Vector3D();
				degrees = Math.sqrt(_x * _x + _y * _y + _z * _z);
				vec = new Vector3D(_x, _y, _z);
				vec.normalize();
				c2.transform.matrix3D.prependRotation(degrees, vec);
				c2.transform.matrix3D.position = poz;

				tf0x.text = "rX:" + near(c0.rotationX);
				tf0y.text = "rY:" + near(c0.rotationY);
				tf0z.text = "rZ:" + near(c0.rotationZ);
				tf1x.text = "rX:" + near(c1.rotationX);
				tf1y.text = "rY:" + near(c1.rotationY);
				tf1z.text = "rZ:" + near(c1.rotationZ);
				tf2x.text = "rX:" + near(c2.rotationX);
				tf2y.text = "rY:" + near(c2.rotationY);
				tf2z.text = "rZ:" + near(c2.rotationZ);

				sorter0(viewStage)
			}
		}
		private function near(num:Number):Number {
			return Math.round(num*1000000)/ 1000000;
		}
		private function sorter0(obj:*):void {
			var leng:int = obj.numChildren;
			for (var i:int = 0; i < leng; i++) {
				if (obj.getChildAt(i) is DisplayObjectContainer) {
					sorter(obj.getChildAt(i));
				}
			}

		}

		private function sorter(obj:DisplayObjectContainer):void {
			/*
			 * 現状はz-sortになってるけど、これだけじゃだめなこともあるので
			 * 視点からの距離を測ったほうがいい。そのための準備
			var pt:Point;
			var ptZ:Number;
			if (obj.transform.perspectiveProjection) {
				pt = obj.transform.perspectiveProjection.projectionCenter;
				ptZ = obj.transform.perspectiveProjection.focalLength;
			}else {
				pt = this.root.transform.perspectiveProjection.projectionCenter;
				ptZ = this.root.transform.perspectiveProjection.focalLength;
			}
			//trace(pt)
			*/
			var leng:int = obj.numChildren;
			if (leng <= 1) {
				return;
			}
			var sort_array:Array = new Array();
			var objTemp_array:Array = [];
			for (var i:int = 0; i < leng; i++) {
				sort_array[i] = obj.transform.matrix3D.transformVector(new Vector3D(obj.getChildAt(i).x, obj.getChildAt(i).y, obj.getChildAt(i).z)).z;
				objTemp_array[i] = obj.getChildAt(i);

			}
			sort_array = sort_array.sort(Array.RETURNINDEXEDARRAY | Array.NUMERIC);
			var isSwap:Boolean;
			for (i = 0; i < leng; i++) {
				if (leng - i - 1 != sort_array[i]) {
					isSwap = true;
				}
			}
			if (isSwap) {
				for (i = 0; i < leng; i++) {
					obj.setChildIndex(objTemp_array[sort_array[i]],0)
				}
			}
		}
		private function sorter2(obj:DisplayObjectContainer):void {
			trace(obj.transform.matrix3D.rawData)
			if (obj.rotationY % 10 != 0) { return };
			var leng:int = obj.numChildren;
			var sort_array:Array = new Array();
			var objTemp_array:Array = [];
			for (var i:int = 0; i < leng; i++) {
				sort_array[i] = Math3D.affine([obj.x, obj.y, obj.z, obj.rotationX * Math3D.DEGTORAD, obj.rotationY * Math3D.DEGTORAD, obj.rotationZ * Math3D.DEGTORAD], obj.getChildAt(i).x, obj.getChildAt(i).y, obj.getChildAt(i).z)[2];
				objTemp_array[i] = obj.getChildAt(i);
			}

			sort_array = sort_array.sort(Array.RETURNINDEXEDARRAY | Array.NUMERIC);
			var isSwap:Boolean;
			for (i = 0; i < leng; i++) {
				if (leng - i - 1 != sort_array[i]) {
					isSwap = true;
				}
			}
			if (isSwap) {
				for (i = 0; i < leng; i++) {
					obj.setChildIndex(objTemp_array[sort_array[i]],0)
				}
			}
		}
	}
}

class Math3D {
	public static const DEGTORAD:Number = 0.017453292519943295;
	public static const RADTODEG:Number = 57.29577951308232;
	public static function affine(matrix_array:Array,x:Number, y:Number, z:Number):Array {
		var n_cx:Number = Math.cos(matrix_array[3]);
		var n_sx:Number = Math.sin(matrix_array[3]);
		var n_cy:Number = Math.cos(matrix_array[4]);
		var n_sy:Number = Math.sin(matrix_array[4]);
		var n_cz:Number = Math.cos(matrix_array[5]);
		var n_sz:Number = Math.sin(matrix_array[5]);
		var _array:Array = new Array(3);
		_array[0] = x*(n_cz*n_cy+n_sy*n_sx*n_sz)+y*(-n_sz*n_cy+n_sy*n_sx*n_cz)+z*(n_sy*n_cx)+matrix_array[0];
		_array[1] = x*(n_cx*n_sz)+y*n_cx*n_cz-z*(n_sx)+matrix_array[1];
		_array[2] = x*(-n_sy*n_cz+n_cy*n_sx*n_sz)+y*(n_sy*n_sz+n_cy*n_sx*n_cz)+z*(n_cy*n_cx)+matrix_array[2];
		return _array;
	}
}

class Primitives {
	public static function colorCube(width:Number = 100, depth:Number = 100, height:Number = 100):Sprite {
		var colors_array:Array = [  0x00FF00, 0xFF0000, 0x00FFFF, 0xFF00FF,0x0000FF, 0xFFFF00 ];
		var result:Sprite = new Sprite;
		var sp:Sprite = Create.newSprite( { z:depth/2}, { graphics:[ { beginFill:[colors_array[0], 0.9] }, { drawRect:[ -width/2, -height/2, width, height] } ] } );
		result.addChild(sp);
		var spsub:Sprite = colorCube2([colors_array[0]], 3, 50, 3);
		spsub.z = 65;
		result.addChild(spsub);

		sp = Create.newSprite( { z:-depth/2 }, { graphics:[ { beginFill:[colors_array[1], 0.9] }, { drawRect:[ -width/2, -height/2, width, height] } ] } );
		result.addChild(sp);
		spsub = colorCube2([colors_array[1]], 3, 50, 3);
		spsub.z = -65;
		result.addChild(spsub);

		sp = Create.newSprite( { x:width/2,rotationY:90 }, { graphics:[ { beginFill:[colors_array[2], 0.9] }, { drawRect:[ -depth/2, -height/2, depth, height] } ] } );
		result.addChild(sp);
		spsub = colorCube2([colors_array[2]], 50, 3, 3);
		spsub.x = 65;
		result.addChild(spsub);

		sp = Create.newSprite( { x:-width/2,rotationY:90 }, { graphics:[ { beginFill:[colors_array[3], 0.9] }, { drawRect:[ -depth/2, -height/2, depth, height] } ] } );
		result.addChild(sp);
		spsub = colorCube2([colors_array[3]], 50, 3, 3);
		spsub.x = -65;
		result.addChild(spsub);

		sp = Create.newSprite( { y:-height/2,rotationX:90 }, { graphics:[ { beginFill:[colors_array[4], 0.9] }, { drawRect:[ -width/2, -depth/2, width, depth] } ] } );
		result.addChild(sp);
		spsub = colorCube2([colors_array[4]], 3, 3,50);
		spsub.y = -65;
		result.addChild(spsub);

		sp = Create.newSprite( { y:height/2,rotationX:90 }, { graphics:[ { beginFill:[colors_array[5], 0.9] }, { drawRect:[ -width/2, -depth/2, width, depth] } ] } );
		result.addChild(sp);
		spsub = colorCube2([colors_array[5]], 3, 3,50);
		spsub.y = 65;
		result.addChild(spsub);

		return result;
	}
	public static function colorCube2(colors_array:Array = null ,width:Number = 100, depth:Number = 100, height:Number = 100):Sprite {

		if (!colors_array) {
			colors_array = [  0x00FF00, 0xFF0000, 0x00FFFF, 0xFF00FF, 0x0000FF, 0xFFFF00 ];
		}else {
			colors_array = colors_array.concat(colors_array, colors_array, colors_array, colors_array, colors_array);
		}

		var result:Sprite = new Sprite;
		var sp:Sprite = Create.newSprite( { z:depth/2}, { graphics:[ { beginFill:[colors_array[0], 0.9] }, { drawRect:[ -width/2, -height/2, width, height] } ] } );
		result.addChild(sp);
		sp = Create.newSprite( { z:-depth/2 }, { graphics:[ { beginFill:[colors_array[1], 0.9] }, { drawRect:[ -width/2, -height/2, width, height] } ] } );
		result.addChild(sp);

		sp = Create.newSprite( { x:width/2,rotationY:90 }, { graphics:[ { beginFill:[colors_array[2], 0.9] }, { drawRect:[ -depth/2, -height/2, depth, height] } ] } );
		result.addChild(sp);
		sp = Create.newSprite( { x:-width/2,rotationY:90 }, { graphics:[ { beginFill:[colors_array[3], 0.9] }, { drawRect:[ -depth/2, -height/2, depth, height] } ] } );
		result.addChild(sp);

		sp = Create.newSprite( { y:-height/2,rotationX:90 }, { graphics:[ { beginFill:[colors_array[4], 0.9] }, { drawRect:[ -width/2, -depth/2, width, depth] } ] } );
		result.addChild(sp);
		sp = Create.newSprite( { y:height/2,rotationX:90 }, { graphics:[ { beginFill:[colors_array[5], 0.9] }, { drawRect:[ -width/2, -depth/2, width, depth] } ] } );
		result.addChild(sp);

		return result;
	}
}

import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.SimpleButton;

class Create{
	public static var defaultTextFormat:TextFormat = new TextFormat();

	public static function newSimpleButton(x_y_w_h_txt:Array = null,property:Array=null,graphics:Array=null):SimpleButton{

		var _x:Number = x_y_w_h_txt[0];
		var _y:Number = x_y_w_h_txt[1];
		var _width:Number = x_y_w_h_txt[2];
		var _height:Number = x_y_w_h_txt[3];
		var _text:String = x_y_w_h_txt[4];

		var upState:Sprite = newSprite({x:_x,y:_y},{graphics:toDrawRect({color:0xCCCCCC,width:_width,height:_height,round:8})});
		upState.addChild(newShape({x:2,y:2},{graphics:toDrawRect({color:0xE5E5E5,width:_width-4,height:_height-4,round:6})}));
		var overState:Sprite = newSprite({x:_x,y:_y},{graphics:toDrawRect({color:0xBBBBBB,width:_width,height:_height,round:8})});
		overState.addChild(newShape({x:2,y:2},{graphics:toDrawRect({color:0xEEEEEE,width:_width-4,height:_height-4,round:6})}));
		var downState:Sprite = newSprite({x:_x,y:_y},{graphics:toDrawRect({color:0xAAAAAA,width:_width,height:_height,round:8})});
		downState.addChild(newShape({x:2,y:2},{graphics:toDrawRect({color:0xDDDDDD,width:_width-4,height:_height-4,round:6})}));
		var hitTestState:Shape = newShape({x:_x,y:_y},{graphics:toDrawRect({width:_width,height:_height,round:8})});

		if(x_y_w_h_txt[4]){
			upState.addChild(newTextField({x:0,y:2,width:x_y_w_h_txt[2],height:x_y_w_h_txt[3]-2,text:x_y_w_h_txt[4],setTextFormat:[{font:"_sans",align:"center"}]}));
			overState.addChild(newTextField({x:0,y:2,width:x_y_w_h_txt[2],height:x_y_w_h_txt[3]-2,text:x_y_w_h_txt[4],setTextFormat:[{font:"_sans",align:"center"}]}));
			downState.addChild(newTextField({x:0,y:3,width:x_y_w_h_txt[2],height:x_y_w_h_txt[3]-3,text:x_y_w_h_txt[4],setTextFormat:[{font:"_sans",align:"center"}]}));
		}
		var sb:SimpleButton = new SimpleButton(upState,overState,downState,hitTestState);

		return sb;
	}
	public static function toDrawRect(... args):Array{
		var _x:Number = args[0]["x"]?args[0]["x"]:0;
		var _y:Number = args[0]["y"]?args[0]["y"]:0;
		var _width:Number = args[0]["width"]?args[0]["width"]:100;
		var _height:Number = args[0]["height"]?args[0]["height"]:100;
		var _color:Number = args[0]["color"]?args[0]["color"]:0xFF0000;
		var _alpha:Number = args[0]["alpha"]?args[0]["alpha"]:1;
		var _round:Number = args[0]["round"]?args[0]["round"]:0;
		var _lineSize:Number = args[0]["lineSize"]?args[0]["lineSize"]:0;
		var _lineColor:Number = args[0]["lineColor"]?args[0]["lineColor"]:0;
		var _lineAlpha:Number = args[0]["lineAlpha"]?args[0]["lineAlpha"]:0;
		var _ellipseWidth:Number = args[0]["ellipseWidth"]?args[0]["ellipseWidth"]:_round;
		var _ellipseHeight:Number = args[0]["ellipseHeight"]?args[0]["ellipseHeight"]:_ellipseWidth;
		return [{beginFill:[_color,_alpha]},{drawRoundRect:[_x,_y,_width,_height,_ellipseWidth,_ellipseHeight]}];
	}
	public static function newShapeRect(... args):Shape{
		if (args.length == 0) {
			args = [new Object()];
		}
		var _dX:Number = args[0]["dx"]?args[0]["dx"]:0;
		var _dY:Number = args[0]["dy"]?args[0]["dy"]:0;
		var _x:Number = args[0]["x"]?args[0]["x"]:0;
		var _y:Number = args[0]["y"]?args[0]["y"]:0;
		var _width:Number = args[0]["width"]?args[0]["width"]:100;
		var _height:Number = args[0]["height"]?args[0]["height"]:100;
		var _rotation:Number = args[0]["rotation"]?args[0]["rotation"]:0;
		var _color:Number = args[0]["color"]?args[0]["color"]:0xFF0000;
		var _alpha:Number = args[0]["alpha"]?args[0]["alpha"]:1;
		var _round:Number = args[0]["round"]?args[0]["round"]:0;
		var _lineSize:Number = args[0]["lineSize"]?args[0]["lineSize"]:0;
		var _lineColor:Number = args[0]["lineColor"]?args[0]["lineColor"]:0;
		var _lineAlpha:Number = args[0]["lineAlpha"]?args[0]["lineAlpha"]:0;
		var _ellipseWidth:Number = args[0]["ellipseWidth"]?args[0]["ellipseWidth"]:_round;
		var _ellipseHeight:Number = args[0]["ellipseHeight"]?args[0]["ellipseHeight"]:_ellipseWidth;
		var sh:Shape = newShape({x:_x,y:_y,rotation:_rotation},{graphics:[{beginFill:[_color,_alpha]},{drawRoundRect:[_dX,_dY,_width,_height,_ellipseWidth,_ellipseHeight]}]});
		return sh;
	}
	public static function newSpriteRect(... args):Sprite {
		if (args.length == 0) {
			args = [new Object()];
		}
		var _dX:Number = args[0]["dx"]?args[0]["dx"]:0;
		var _dY:Number = args[0]["dy"]?args[0]["dy"]:0;
		var _x:Number = args[0]["x"]?args[0]["x"]:0;
		var _y:Number = args[0]["y"]?args[0]["y"]:0;
		var _width:Number = args[0]["width"]?args[0]["width"]:100;
		var _height:Number = args[0]["height"]?args[0]["height"]:100;
		var _color:Number = args[0]["color"]?args[0]["color"]:0xFF0000;
		var _alpha:Number = args[0]["alpha"]?args[0]["alpha"]:1;
		var _round:Number = args[0]["round"]?args[0]["round"]:0;
		var _lineSize:Number = args[0]["lineSize"]?args[0]["lineSize"]:0;
		var _lineColor:Number = args[0]["lineColor"]?args[0]["lineColor"]:0;
		var _lineAlpha:Number = args[0]["lineAlpha"]?args[0]["lineAlpha"]:0;
		var _ellipseWidth:Number = args[0]["ellipseWidth"]?args[0]["ellipseWidth"]:_round;
		var _ellipseHeight:Number = args[0]["ellipseHeight"]?args[0]["ellipseHeight"]:_ellipseWidth;
		var sp:Sprite = newSprite({x:_x,y:_y},{graphics:[{beginFill:[_color,_alpha]},{drawRoundRect:[_dX,_dY,_width,_height,_ellipseWidth,_ellipseHeight]}]});
		return sp;
	}
	//,{drawRect:[0,0,_width,_height]}
	public static function newShape(... args):Shape{
		var sp:Shape;
		var _str:String;
		var _length:int = args.length;
		for (var i:int = 0; i < _length; i++) {
			var _obj:Object = args[i];
			if(i == 0){
				if(_obj.Shape){
					sp = _obj.Shape;
				}else{
					sp = new Shape();
				}
			}
			if(_obj.graphics){
				for (var j:int = 0; j < _obj.graphics.length; j++) {
					if(_obj.graphics[j]){
						for (_str in _obj.graphics[j]) {
							//trace(_str,_obj.graphics[j][_str])
							sp.graphics[_str].apply(null, _obj.graphics[j][_str]);
						}
					}
				}
			}
			for (_str in _obj) {
				if(_str != "Shape" && _str != "graphics"){
					sp[_str] = _obj[_str];
				}
			}
		}
		return sp;
	}
	public static function newSprite(... args):Sprite{
		var sp:Sprite;
		var _str:String;
		var _length:int = args.length;
		for (var i:int = 0; i < _length; i++) {
			var _obj:Object = args[i];
			if(i == 0){
				if(_obj.Sprite){
					sp = _obj.Sprite;
				}else{
					sp = new Sprite();
				}
			}
			if(_obj.graphics){
				for (var j:int = 0; j < _obj.graphics.length; j++) {
					if(_obj.graphics[j]){
						for (_str in _obj.graphics[j]) {
							sp.graphics[_str].apply(null, _obj.graphics[j][_str]);
						}
					}
				}
			}
			for (_str in _obj) {
				if(_str != "Sprite" && _str != "graphics" && _str != "addChild"){
					sp[_str] = _obj[_str];
				}
			}
			if(_obj.addChild){
				sp.addChild(_obj.addChild);
			}
		}
		return sp;
	}
	public static function newTextField(... args):TextField{
		var ta:TextField = new TextField();
		ta.defaultTextFormat = defaultTextFormat;
		var _length:int = args.length;
		for (var i:int = 0; i < _length; i++) {
			var _obj:Object = args[i];
			for (var _str:String in _obj) {
				if(_str != "setTextFormat"){
					ta[_str] = _obj[_str];
				}
			}
			if(_obj.setTextFormat){
				var format:TextFormat = new TextFormat();
				if(_obj.setTextFormat[0] is TextFormat){
					format = _obj.setTextFormat[0];
				}else{
					for (var tf_str:String in _obj.setTextFormat[0]) {
						format[tf_str] = _obj.setTextFormat[0][tf_str];
					}
				}
				ta.setTextFormat(format,isNaN(_obj.setTextFormat[1])?-1:_obj.setTextFormat[1],isNaN(_obj.setTextFormat[2])?-1:_obj.setTextFormat[2]);
			}
		}
		return ta;
	}
}

関連記事:

Comments are closed.