In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

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

★ジンバルロックを体験してみよう!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のlocalRot
/**
 * Copyright umhr ( http://wonderfl.net/user/umhr )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7FAn
 */

/*
 * ★ジンバルロックを体験してみよう!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();
        public function Main():void {
            
            //立方体を生成
            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;
            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;
            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;
            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);
                
                Math3D.sorter(e.target)
            }
        }
        
        private function near(num:Number):Number {
            return Math.round(num*1000000)/ 1000000;
        }
    }
}

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;

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;
    }
    public static function sorter(obj:*):void {
        if (obj is DisplayObjectContainer) {
            sort(obj);
        }
    }
    
    public static function sort(obj:DisplayObjectContainer):void {
        var leng:int = obj.numChildren;
        
        //子供が1個もないなら、ソートする必要いし、孫がいる可能性も無い。
        if (leng < 1) { return; };
        
        //カメラの座標を取得
        var pt:Point;
        var cameraCenter:Vector3D = new Vector3D();
        if (obj.transform.perspectiveProjection) {
            pt = obj.transform.perspectiveProjection.projectionCenter;
            cameraCenter.z = -obj.transform.perspectiveProjection.focalLength;
        }else {
            pt = obj.root.transform.perspectiveProjection.projectionCenter;
            cameraCenter.z = -obj.root.transform.perspectiveProjection.focalLength;
        }
        cameraCenter.x = pt.x;
        cameraCenter.y = pt.y;
        
        //カメラからobjまでの距離を取得し、sort_arrayに入れる。
        //zの値だけだとうまくいかないことがあるので、x,yの値もとり、距離を得る。
        var sort_array:Array = new Array();
        var objTemp_array:Array = [];
        for (var i:int = 0; i < leng; i++) {
            var poz:Vector3D;
            if (obj.getChildAt(i) is DisplayObjectContainer) {
                var objChild:* = obj.getChildAt(i);
                sort(objChild);
                if(!objChild.transform.getRelativeMatrix3D(objChild.root)){
                    continue;
                }
                var j:int = objTemp_array.length;
                objTemp_array[j] = objChild;
                poz = objTemp_array[j].transform.getRelativeMatrix3D(objTemp_array[j].root).position;
                sort_array[j] = Vector3D.distance(poz,cameraCenter);
            }
        }
        
        //子供が1個ならソートする必要なし。
        if (leng == 1) { return; };
        
        //ソートを実行する。
        //sortOn("z",)とかのやり方だと重い。
        sort_array = sort_array.sort(Array.RETURNINDEXEDARRAY | Array.NUMERIC);
        leng = sort_array.length;
        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 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;
    }
}