Beautifl - Flash Gallery

Thumbnail : IKBone Ver2
IKBone Ver2
narutohyper 2010-08-15 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

package
{
    /* IKに角度制限をつけたVerです。
     * ちょっと動きがぬるっとしてますが、仕様ですw
     * ボーン選択後プロパティでボーンの長さや制限角度が修正できます。
     * 
     * また、フルスクリーンにすると、右に、IKボーンツリーが表示しますので、
     * キーボーン(IKの終点)のオン・オフが出来るようになります。
     * 
     * Ctrlキーを押しながら、ボーンを動かすと、FKになります。    
     * 
     * そのうちImage Mesh Generatorと結合させる予定。
     * http://wonderfl.net/c/voB0
     * 
     * 
     * 
     * @author narutohyper
     */
    
     
    import flash.display.Loader;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    import flash.system.ApplicationDomain;
    import flash.events.Event


    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.display.BitmapData;



    [SWF(width = 465, height = 465, frameRate = 60)]
    
    public class Main extends Sprite {
        
        private var ika:IKArmature2d;

        private var test:uint = 0;
        private var boneTree:IKBoneTree;
        private var property:propertyPanel;
        
        private var imgLoader:Loader
        
        public function Main() {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            //Sample画像の読み込み
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.HIGH;

    
            //---------------------------------
            //アーマチュア(枠組み)の作成
            //---------------------------------
            ika=new IKArmature2d()
            this.addChild(ika);
            //rootJointの作成
            //3つのJointを作成

            if (test) {
                ika.setBone(new IKBone2d('test1', 100, 0,-90,90));
                ika.setBone(new IKBone2d('test2', 50, 700, -120, 120));
                ika.setBone(new IKBone2d('test3', 50, 700,-120,120));
                ika.joint('root', 'test1');
                ika.joint('test1', 'test2');
                ika.joint('test2', 'test3');

            } else {
                //-------------------------------------------------
                //ボーンの作成
                //new IKBone2d('ID名':String,長さ:Number,初期角度:Number,稼動範囲角度(負):Number,稼動範囲角度(正):Number)
                //ボーンをアーマチュアに登録
                //IKArmature2d.set(IKBone2d);
                //初期角度、稼動範囲は、親ボーン角度からの相対
                //初期角度が、稼動範囲を超える場合は修正される
                //-------------------------------------------------
                var colors:Array=new Array(0xFFFF00,0x00FF00,0x0000FF,0xFF00FF,0x00FFFF);
            
                ika.setBone(new IKBone2d('body', 43, 0,-30,30));
                ika.setBone(new IKBone2d('breast', 48, 0,-30,30));
                
                ika.setBone(new IKBone2d('waistRight', 33, 134,134,134,true));
                ika.setBone(new IKBone2d('upperFootRight', 99, 46,-60,60));
                ika.setBone(new IKBone2d('lowerFootRight', 116, -1,-1,170));
                ika.setBone(new IKBone2d('ankleRight', 30, -10,-30,30));
                
                ika.setBone(new IKBone2d('shoulderRight',33,100,80,100,true));
                ika.setBone(new IKBone2d('upperArmRight',65,25));
                ika.setBone(new IKBone2d('lowerArmRight',58,-4));
                ika.setBone(new IKBone2d('handRight', 42, -8,-30,30));
                
                ika.setBone(new IKBone2d('waistLeft', 33, -134,-134,-134,true));
                ika.setBone(new IKBone2d('upperFootLeft', 99, -46,-60,60));
                ika.setBone(new IKBone2d('lowerFootLeft', 116, 1,-170,1));
                ika.setBone(new IKBone2d('ankleLeft', 30, 10,-30,30));
                    
                ika.setBone(new IKBone2d('shoulderLeft',33,-100,-100,-80,true));
                ika.setBone(new IKBone2d('upperArmLeft',65,-25));
                ika.setBone(new IKBone2d('lowerArmLeft',58,4));
                ika.setBone(new IKBone2d('handLeft', 42, 8,-30,30));
                
                ika.setBone(new IKBone2d('neck',30,0,-30,30,true));
                ika.setBone(new IKBone2d('head',50,0,-30,30));

                //-------------------------------------------------
                //ボーンをジョイント
                //IKArmature2d.joint('親Bone名 Or root','子Bone名'
                //-------------------------------------------------
                ika.joint('root', 'body');
                ika.joint('root', 'waistRight');
                ika.joint('root', 'waistLeft');
                ika.joint('body', 'breast');

                ika.joint('breast', 'neck');
                ika.joint('neck', 'head');
                
                ika.joint('breast', 'shoulderRight');
                ika.joint('breast', 'shoulderLeft');
                ika.joint('shoulderRight','upperArmRight');
                ika.joint('shoulderLeft', 'upperArmLeft');
                ika.joint('upperArmRight','lowerArmRight');
                ika.joint('upperArmLeft','lowerArmLeft');
                ika.joint('lowerArmRight','handRight');
                ika.joint('lowerArmLeft', 'handLeft');
                
                ika.joint('waistRight','upperFootRight');
                ika.joint('waistLeft','upperFootLeft');
                ika.joint('upperFootRight','lowerFootRight');
                ika.joint('upperFootLeft', 'lowerFootLeft');
                ika.joint('lowerFootRight','ankleRight');
                ika.joint('lowerFootLeft','ankleLeft');
            }
            ika.init()
            ika.x=250
            ika.y=184
            //ika.rotation=45
            boneTree = new IKBoneTree(ika);
            this.addChild(boneTree)
            boneTree.x = 500;
            boneTree.y = 10;

            property = new propertyPanel(ika);
            this.addChild(property)
            property.x = 10;
            property.y = this.stage.stageHeight - property.height - 10;
            

            
        }
        
    }

}







//---------------------------------------------------------
//IKTreeパネル
//---------------------------------------------------------

import flash.display.Sprite;
import flash.display.LineScaleMode;
import flash.events.Event;
import flash.text.*;

class IKBoneTree extends Sprite {
    private var _ika:IKArmature2d;
    
    public function IKBoneTree($ika:IKArmature2d) {
        _ika=$ika
        var rootObj:IKBone2d = _ika.bones['root'];
        var rootNode:IKBoneTreeNode = new IKBoneTreeNode(_ika,rootObj,false);
        this.addChild(rootNode);
    }

    public function changeKey(id:String,onFlag:Boolean):void {
        _ika.bones[id].keyBone = onFlag;
    }

}


class IKBoneTreeNode extends Sprite {
    public var _ika:IKArmature2d
    public function IKBoneTreeNode($ika:IKArmature2d,$tempBone:IKBone2d, $mode:Boolean = true) {
        _ika = $ika;
        var i:uint;
        var nextY:Number = 0;
        var checkLabel:myCheckBox = new myCheckBox($tempBone.id);

        checkLabel.addEventListener(myCheckBox.CHANGE,change)

        if($tempBone.keyBone) {
            checkLabel.onClick()
        }
        this.addChild(checkLabel);
        nextY += checkLabel.height;
        this.graphics.lineStyle(0, 0x666666);
        if ($mode) {
            this.graphics.moveTo(-12, 10);
            this.graphics.lineTo(0,10);
        }
        
        var nodes:Array=new Array()
        for (i=0;i<$tempBone.childs.length;i++) {
            nodes[i] = new IKBoneTreeNode(_ika,$tempBone.childs[i]);
            this.addChild(nodes[i]);
            nodes[i].x = 20;
            nodes[i].y = nextY;
            nextY += nodes[i].height + 1;
        }
        if (nodes[i-1]) {
            nextY -= nodes[i - 1].height
            this.graphics.moveTo(7, Math.floor(checkLabel.height / 2));
            this.graphics.lineTo(7, nextY+10);
        }
        if ($mode==false) {
            trace('------',i,nextY)
        }

    }

    private function change(e:Event):void {
        var _parentClass:IKBoneTree = e.target as IKBoneTree
        var tempMc:myCheckBox = e.target as myCheckBox
        _ika.bones[tempMc.str].keyBone = tempMc.onFlag;
    }

}




//---------------------------------------------------------
//簡易プロパティパネル
//---------------------------------------------------------

class propertyPanel extends Sprite {
    private var _ika:IKArmature2d;
    private var _setObject:IKBone2d;

    private var _uiA:Sprite
    private var _uiB:Sprite

    private var _sliderL:DraggableTextInput
    private var _sliderR:DraggableTextInput
    private var _sliderMin:DraggableTextInput
    private var _sliderMax:DraggableTextInput
    private var _sliderX:DraggableTextInput
    private var _sliderY:DraggableTextInput
    private var objNameA:TextField
    private var objNameB:TextField

    public function propertyPanel($ika:IKArmature2d) {
        graphics.lineStyle(0, 0x666666, 1, true, LineScaleMode.NONE);
        graphics.beginFill(0xFFFFFF, 1);
        graphics.drawRect(0, 0, 240, 100);
        _ika = $ika;
        _ika.addEventListener(IKArmature2d.MOUSE_DOWN,onMouseDown)


        _uiA=new Sprite()
        _uiB=new Sprite()

        this.addChild(_uiA);
        this.addChild(_uiB);

        //------------------------------------
        //ボーン情報の表示
        //------------------------------------
        //名前の表示
        _uiA.addChild(label('ボーン名:',60,0))
        objNameA = label('bone', 70, 0,'LEFT')
        _uiA.addChild(objNameA);
        //長さ
        _uiA.addChild(label('長さ:', 60, 30))
        _sliderL = new DraggableTextInput();
        _sliderL.x = 60;
        _sliderL.y = 27;
        _sliderL.minimum = 20;
        _sliderL.maximum = 300;
        _sliderL.snapInterval = 1;
        _uiA.addChild(_sliderL);

        //角度
        _uiA.addChild(label('角度:',160,30))
        _sliderR = new DraggableTextInput();
        _sliderR.x = 160;
        _sliderR.y = 27;
        _sliderR.minimum = -180;
        _sliderR.maximum = 180;
        _sliderR.value = 0;
        _sliderR.snapInterval = 1;
        _uiA.addChild(_sliderR);

        //min角度
        _uiA.addChild(label('最小角:',60,60))
        _sliderMin = new DraggableTextInput();
        _sliderMin.x = 60;
        _sliderMin.y = 57;
        _sliderMin.minimum = -180;
        _sliderMin.maximum = 180;
        _sliderMin.value = 0;
        _sliderMin.snapInterval = 1;
        _uiA.addChild(_sliderMin);
        _uiA.visible=false
        //max角度
        _uiA.addChild(label('最大角:',160,60))
        _sliderMax = new DraggableTextInput();
        _sliderMax.x = 160;
        _sliderMax.y = 57;
        _sliderMax.minimum = -180;
        _sliderMax.maximum = 180;
        _sliderMax.value = 0;
        _sliderMax.snapInterval = 1;
        _uiA.addChild(_sliderMax);
        

        //------------------------------------
        //アーマチュア情報の表示
        //------------------------------------
        _uiB.addChild(label('ボーン名:',60,0))
        objNameB = label('bone', 70, 0,'LEFT')
        _uiB.addChild(objNameB);
        //x
        _uiB.addChild(label('x:',60,30))
        _sliderX = new DraggableTextInput();
        _sliderX.x = 60;
        _sliderX.y = 27;
        _sliderX.minimum = -5760;
        _sliderX.maximum = 5760;
        _sliderX.value = 0;
        _uiB.addChild(_sliderX);

        //y
        _uiB.addChild(label('y:',160,30))
        _sliderY = new DraggableTextInput();
        _sliderY.x = 160;
        _sliderY.y = 27;
        _sliderY.minimum = -5760;
        _sliderY.maximum = 5760;
        _sliderY.value = 0;
        _uiB.addChild(_sliderY);
        _uiB.visible=false
            
        _uiA.y = 10;
        _uiB.y = 10;
        
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }
        
    private function init(e:Event = null):void {
      removeEventListener(Event.ADDED_TO_STAGE, init);
      stage.addEventListener(Event.RESIZE, onResize);
      onResize()
    }
    
        
    private function onResize(e:Event=null):void {
        y=stage.stageHeight-height-50;
        
    }
    

    public function label($str:String,$x:Number,$y:Number,$align:String='RIGHT'):TextField {
        var lb:TextField=new TextField();
        lb.autoSize=TextFieldAutoSize.LEFT;
        lb.selectable=false;
        lb.mouseEnabled=false;
        var format:TextFormat=new TextFormat();
        format.color=0x666666;
        format.size=12;
        format.font='_ゴシック';
        lb.defaultTextFormat=format;
        lb.text = $str;
        if ($align=='RIGHT') {
            lb.x = $x-lb.width;
        } else {
            lb.x = $x;
        }
        lb.y=$y;
        return lb;
    }


    private function onMouseDown(e:Event=null):void {
        if (_ika.startBone) {
            _uiA.visible=true
            _uiB.visible=false
            //ボーン情報
            _setObject = _ika.startBone;
            //名前の表示
            objNameA.text=_setObject.id
        } else {
            _uiA.visible=false
            _uiB.visible=true
            //無ければ、アーマチュア情報の表示
            _setObject = null;
            objNameB.text='root'
        }
        setProperty()
        _ika.removeEventListener(IKArmature2d.MOUSE_DOWN,onMouseDown)
        _ika.addEventListener(IKArmature2d.MOUSE_UP,onMouseUp)
        _ika.addEventListener(IKArmature2d.MOUSE_MOVE,setProperty)

        _sliderL.removeEventListener(Event.CHANGE, _onChangeA);
        _sliderR.removeEventListener(Event.CHANGE, _onChangeA);
        _sliderMin.removeEventListener(Event.CHANGE, _onChangeA);
        _sliderMax.removeEventListener(Event.CHANGE, _onChangeA);
        _sliderX.removeEventListener(Event.CHANGE, _onChangeB);
        _sliderY.removeEventListener(Event.CHANGE, _onChangeB);
    }

    private function onMouseUp(e:Event=null):void {
        _ika.addEventListener(IKArmature2d.MOUSE_DOWN,onMouseDown)
        _ika.removeEventListener(IKArmature2d.MOUSE_UP,onMouseUp)
        _ika.removeEventListener(IKArmature2d.MOUSE_MOVE,setProperty)

        _sliderL.addEventListener(Event.CHANGE, _onChangeA);
        _sliderR.addEventListener(Event.CHANGE, _onChangeA);
        _sliderMin.addEventListener(Event.CHANGE, _onChangeA);
        _sliderMax.addEventListener(Event.CHANGE, _onChangeA);
        _sliderX.addEventListener(Event.CHANGE, _onChangeB);
        _sliderY.addEventListener(Event.CHANGE, _onChangeB);
    }



    private function setProperty(e:Event=null):void {
        if (_ika.startBone) {
            _sliderL.value = _setObject.length;
            _sliderR.value = _setObject.rotation;
            _sliderMin.value = _setObject.minRotation;
            _sliderMax.value = _setObject.maxRotation;

        } else {
            _sliderX.value = _ika.x;
            _sliderY.value = _ika.y;

        }
    }


    private function _onChangeA(event:Event):void {
        _setObject.length=_sliderL.value;
        _setObject.setRotationRange(_sliderMin.value,_sliderMax.value)
        _setObject.boneRotation(_sliderR.value);
    }

    private function _onChangeB(event:Event):void {
        _ika.x =    _sliderX.value;
        _ika.y =    _sliderY.value;

    }

}






//=======================================================================================
//IKアーマチュア(枠組み)
//=======================================================================================
    import flash.display.Sprite;

    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.text.*
    import flash.geom.Point;
    import flash.geom.Matrix;
    import flash.ui.Keyboard;
    
    
    class IKArmature2d extends Sprite    {
        public static const MOUSE_DOWN:String = 'mouse_down';
        public static const MOUSE_UP:String = 'mouse_up';
        public static const MOUSE_MOVE:String = 'mouse_move';
        
        private var _rootJoint:IKJoint2d;
        private var _bones:Object;

        private var target:Sprite;
        private var IKBones:Array;
        private var oldPoint:Point;
        private var newPoint:Point;
        
        private var tempVector:Array
        private var tempArray:Array

        public var startBone:IKBone2d;
        

        
        public function IKArmature2d () {

            //目標点

            bones = new Object();
            bones['root'] = new IKBone2d('root',0);
            bones['root'].superRotation = -90;
            bones['root'].setDegree(0);
            bones['root'].addEventListener(IKBone2d.ROOT_DOWN,IKDrag)
            this.addChild(bones['root']);
        }

        public function init():void {
            bones['root'].move();

            var i:int;
            //配置の順番を変える
            //rootから順番に
            tempArray=new Array()
            node(bones['root'])
            for (i = tempArray.length - 1; i >= 0; i--) {
                this.addChild(tempArray[i]);
            }
        }


        public function node(bone:IKBone2d):void {
            var i:uint;
            tempArray.push(bone);
            for (i=0;i<bone.childs.length;i++) {
                node(bone.childs[i]);
            }
        }


        
        
        public function setBone(value:IKBone2d):void {
            bones[value.id]=value;
            bones[value.id].addEventListener(IKBone2d.MOUSE_DOWN,IKStart)
        }
        
        public function joint($boneA:String = null, $boneB:String = null):void {
            if (bones[$boneA] && bones[$boneB]) {
                bones[$boneA].setChild(bones[$boneB]);
            } else {
                trace('Error:boneが存在しません。', $boneA + '=', bones[$boneA], $boneB + '=', bones[$boneB]);
            }
        }
        
        
        
        
        public function set bones(value:Object):void {
                _bones = value;
        }
        
        public function get bones():Object {
            return _bones;
        }
        
        //-----------------------------------------------------
        //IKBoneのドラッグでアーマチュアを動かす系
        //-----------------------------------------------------
        private function IKDrag(e:MouseEvent):void {
            if (startBone) {
                startBone.selectOff()
                startBone = null;
            }
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onIKDragMove);
            stage.addEventListener(MouseEvent.MOUSE_UP, onIKDragUp);
            dispatchEvent(new Event(MOUSE_DOWN));
        }
        
        private function onIKDragMove(e:MouseEvent):void {
            x = stage.mouseX;
            y = stage.mouseY;
            dispatchEvent(new Event(MOUSE_MOVE));
        }
        
        private function onIKDragUp(e:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, onIKDragMove);
            stage.removeEventListener(MouseEvent.MOUSE_UP, onIKDragUp);
            dispatchEvent(new Event(MOUSE_UP));
        }
        
        //-----------------------------------------------------
        //IKBoneのドラッグでターゲットを動かすMouseEvent系
        //-----------------------------------------------------

        private function IKStart(e:MouseEvent):void {
            //MouseDownしたObject
            if (startBone) {
                startBone.selectOff()
            }
            startBone = e.target as IKBone2d
            startBone.selectOn()

            //startBoneからkeyBone(無い場合はroot)までのIKbonesを作成する
            if (tempVector) {
                for (i = 0; i < tempVector.length; i++ ) {
                    this.removeChild(tempVector[i])
                }
            }
            
            IKBones=new Array()
            tempVector=new Array()
            var tempBone:IKBone2d = startBone

            if(e.ctrlKey) {
                IKBones.push(tempBone)
            } else {

                while (true) {
                    if (tempBone) {
                        IKBones.push(tempBone)
                        if (tempBone.keyBone) {
                            break;
                        } else {
                            tempBone = tempBone.parentBone
                        }
                    } else {
                        break;
                    }
                }
            }
            
            var i:uint
            IKBones.reverse();
            for (i = 0; i < IKBones.length; i++ ) {
                IKBones[i].arrowVisible = true;
                tempVector[i] = new Arrow(false)
                this.addChild(tempVector[i])
            }

            oldPoint = newPoint;
            newPoint=new Point(mouseX,mouseY);
            
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
            dispatchEvent(new Event(MOUSE_DOWN));
        }


        private function onMouseUp(e:MouseEvent):void {
            stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            var i:uint
            startBone.setDefaultLength()
            for (i=0; i < IKBones.length;i++ ) {
                IKBones[i].arrowVisible = false;
            }
            dispatchEvent(new Event(MOUSE_UP));
        }
    
        private function onMouseMove(e:MouseEvent):void {
            oldPoint = newPoint;
            newPoint=new Point(mouseX,mouseY);
            var startVector:Point=new Point((mouseX-startBone.boneTailPoint.x),(mouseY-startBone.boneTailPoint.y));
            var targetPoint:Point

            for (var i:int = IKBones.length - 1; i >= 0; i-- ) {
                if (IKBones[i].id!='root') {
                //------------------------------------------
                //新しいポイントにボーンを向ける
                //------------------------------------------
                    setVector(tempVector[i], IKBones[i].boneTailPoint, newPoint)
                    tension(tempVector[i],IKBones[i]);
                    targetPoint = tempVector[i].vector.add(IKBones[i].boneTailPoint)
                    
                    lookAt(IKBones[i], targetPoint)

                //------------------------------------------
                //向けた方向でtailpointを取得、張力を再調査
                //------------------------------------------
                    setVector(tempVector[i], IKBones[i].boneTailPoint, newPoint)
                    //本来戻るはずの位置(張力MAXの状態)で次のターゲットの位置を決めておく
                    newPoint = tempVector[i].vector.add(IKBones[i].point)
                    //張力を再調査
                    tension(tempVector[i],IKBones[i]);
                    //ボーンを一旦移動
                    if(i>0) {
                        IKBones[i].point = tempVector[i].vector.add(IKBones[i].point)
                    }
                }
            }

            //------------------------------------------
            //ボーンの位置を修正する
            //------------------------------------------
            if (IKBones[0].id!='root') {
                IKBones[0].move()
            } else {
                IKBones[1].move()
            }
            dispatchEvent(new Event(MOUSE_MOVE));
        }

        private function tension($temp:Arrow,$bone:IKBone2d):void {
            //張力:Max:boneの長さ
            var t:Number = ($temp.length > $bone.length) ? $bone.length : $temp.length;
            $temp.length = t*0.1
        }

        private function setVector($v:Arrow, $active:Point,$target:Point=null ):void {
            var tempPoint:Point;
            if (!$target) {
                $target = new Point($active.x+$v.length,$active.y);
            }

            tempPoint = $target.subtract($active);
            $v.length = Point.distance($active, $target);
            $v.rotation = Math.atan2(tempPoint.y, tempPoint.x) * 180 / Math.PI;
            $v.x=$active.x
            $v.y=$active.y

        }

        private function lookAt($active:IKJoint2d,$target:Point):Boolean {
            //$active(ジョイント)を$targetへ向ける
            var nowPoint:Point;
            var targetPoint:Point;
            var tempPoint:Point;
            nowPoint = $active.point;
            targetPoint = new Point($target.x, $target.y);
            tempPoint = targetPoint.subtract(nowPoint);
            
            return $active.setAngle(Math.atan2(tempPoint.y, tempPoint.x) * 180 / Math.PI);
        }
        
        private function lookAtBone($active:IKBone2d,$target:Point):Boolean {
            //$active(ジョイント)を$targetへ向ける
            var nowPoint:Point;
            var targetPoint:Point;
            var tempPoint:Point;
            nowPoint = $active.point;
            targetPoint = new Point($target.x, $target.y);
            tempPoint = targetPoint.subtract(nowPoint);
            
            return $active.setAngle(Math.atan2(tempPoint.y, tempPoint.x) * 180 / Math.PI);
        }

        private function angle360(value:Number):Number {
            return (value + 360) % 360
        }
        
        private function degree(value:Number):Number {
            value += 180;
            value %= 360;
            value += 360;
            value %= 360;
            value -= 180;
            return value;
        }

        public function Trace(... arguments):void {
                //bg.appendText(arguments.toString()+"\n");
                //trace(arguments);
        }



    }



    
    import flash.display.Shape;
    import flash.geom.Point;
    import flash.geom.Matrix;
    
    class Arrow extends Shape {
        private var _length:Number;
        private var _defColor:Number
        private var _color:Number;
        private var _test:Boolean;
        public var _vector:Point
        
        public function Arrow($test:Boolean=true,$color:uint = 0x666666, $length:Number = 100) {
            _test=$test;
            _color = $color;
            _defColor = _color;
            length = $length;
        }

        public function changeColor():void {
            _color = 0xFF0000;
        }

        public function defColor():void {
            _color = _defColor;
        }


        public function set length(value:Number):void {
            _length = value;
            if (_test) {
                graphics.clear();
                graphics.beginFill(_color);
                graphics.moveTo(_length, 0);
                graphics.lineTo(_length - 10,-6);
                graphics.lineTo(_length - 10,6);
                graphics.lineTo(_length, 0);
                graphics.endFill();
                graphics.lineStyle(0, _color);
                graphics.lineTo(0, 0);
            }
        }
        
        public function get length():Number {
            return _length;
        }

        public function get vector():Point {
            var result:Point = new Point(_length,0);
            var mtx:Matrix = new Matrix();
            mtx.rotate(rotation*Math.PI/180);
            return mtx.transformPoint(result);
        }

        public function set point(value:Point):void {
            x=value.x
            y=value.y
        }

        public function get point():Point {
            return new Point(x,y);
        }

        
    }
    


//=======================================================================================
//IKJoint
//=======================================================================================
    //計算に必要な位置x,y、長さlength、ベクトルvectorPointと「制限角度」を持ったJoint
    //テスト用では、制限角度、ベクトルが描画される

    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.geom.Point;
    import flash.geom.Matrix;

    class IKJoint2d extends Sprite {
        
        private var _id:String;

        private var _length:Number;
        private var _arrow:Arrow;
        private var _test:Boolean;
        private var _visible:Boolean;
        private var _x:Number;
        private var _y:Number;

        //ジョイント(Sprite)自体は回転させない。
        //その為、回転は以下の変数で保持
        private var _rotation:Number;
        private var _rotationRange:Shape;
        
        private var _minRotation:Number;
        private var _maxRotation:Number;
        private var _lockPoint:int=-1;
        private var _lockRotation:String;

        public var _circle:Shape;

        public function IKJoint2d($visible:Boolean=false,$test:Boolean=true,$color:uint=0x6666666) {
            arrow = new Arrow(true, $color);
            arrow.name = 'arrow';
            arrowVisible = $visible
            
            if (id == 'root') {
                _circle = new Shape();
                _circle.graphics.beginFill(0x333399,0.5);
                _circle.graphics.drawCircle(0, 0, 10);
                addChild(_circle);
            } else {
                _circle = new Shape();
                _circle.graphics.beginFill(0xFFFFFF,1);
                _circle.graphics.drawCircle(0, 0, 2);
                addChild(_circle);
            }
            
            length = 0;
            _test = $test;
            _rotationRange = new Shape();
            _rotationRange.name = 'rotationRange';
            x=0
            y=0

        }
        

        //------------------------------------------------------------------------------
        //Setter Getter
        //------------------------------------------------------------------------------
            //-------------------------------------------------------
            //id
            //-------------------------------------------------------
                public function get id():String {
                    return _id;
                }
    
            
                public function set id(value:String):void {
                    _id = value;
                }


                override public function get y():Number {
                    return _y;
                }
                
                override public function set y(value:Number):void {
                    _y = value;
                    if (arrowVisible) {
                        super.y = _y;
                    }
                }

                override public function get x():Number {
                    return _x;
                }
                
                override public function set x(value:Number):void {
                    _x = value;
                    if (arrowVisible) {
                        super.x = _x;
                    }
                }

                public function get superX():Number {
                    return super.x;
                }
                
                public function set superX(value:Number):void {
                    super.x = value;
                }
                
                public function get superY():Number {
                    return super.y;
                }
                
                public function set superY(value:Number):void {
                    super.y = value;
                }

            //-----------------------------------------------------
            //テスト用Arrowの表示
            //-----------------------------------------------------
                public function set arrowVisible(value:Boolean):void {
                    _visible = value;
                    if (_visible) {
                        addChild(_rotationRange);
                        addChild(arrow);
                    } else {
                        if (this.getChildByName('arrow')) {
                            removeChild(_rotationRange);
                            removeChild(arrow);
                        }
                    }

                }

                public function get arrowVisible():Boolean {
                    return _visible;
                }


            //-------------------------------------------------------
            //clone
            //-------------------------------------------------------
                public function get clone():Object {
                    var result:Object = new Object();
                    result.vector2d=this.vector2d
                    result.minRotation = this.minRotation;
                    result.maxRotation = this.maxRotation;
                    result.superRotation = this.superRotation
                    result.id = this.id;
                    return result;
                }
                
                public function set clone(value:Object):void {
                    this.id = value.id;
                    this.vector2d = value.vector2d
                    this.superRotation=value.superRotation
                    this.setRotationRange(value.minRotation, value.maxRotation)
                }


            //-------------------------------------------------------
            //Point
            //-------------------------------------------------------
                public function get point():Point {
                    return new Point(x, y);
                }
                
                public function set point(value:Point):void {
                    x = value.x;
                    y = value.y;
                    
                }
        
            //-------------------------------------------------------
            //長さ
            //-------------------------------------------------------
                public function get length():Number {
                    return _length;
                }
                
                public function set length(value:Number):void {
                    _length = value;
                    if(arrow) {
                        arrow.length = value;
                    }
                }


            //-------------------------------------------------------
            //回転
            //rotationでは、Joint自体は回転しない
            //自身の回転は、親ボーンに依存する
            //強制的に回転させる場合は、superRotationを使用
            //-------------------------------------------------------
                override public function set rotation(value:Number):void {
                    _rotation = value
                }

                override public function get rotation():Number {
                    return _rotation
                }

                public function set superRotation(value:Number):void {
                    super.rotation = value
                }
                
                public function get superRotation():Number {
                    return super.rotation
                }
            

            //-------------------------------------------------
            //superRotationに依存しない角度の指定
            //依存する設定はvectorRotation
            //-------------------------------------------------
                public function setAngle(value:Number):Boolean {
                    return vectorRotation(value-superRotation)
                }


            //------------------------------------------------
            //ベクトル(Boneの終端)を返す
            //------------------------------------------------
                public function get tailPoint():Point {
                    //trace(id,'length=',length,'x=',int(x),'y=',int(y),'sR=',superRotation,'R=',rotation)
                    var result:Point = new Point(length,0);
                    var mtx:Matrix = new Matrix();
                    mtx.rotate(superRotation*Math.PI/180);
                    mtx.rotate(rotation*Math.PI/180);
                    mtx.translate(x, y);
                    result = mtx.transformPoint(result);
                    return result;
                }
                


            //------------------------------------------------
            //vector2d
            //------------------------------------------------
                public function get vector2d():Vector2d {
                    return new Vector2d(x, y, length, rotation);
                }

                public function set vector2d(value:Vector2d):void {
                    x = value.x;
                    y = value.y;
                    length = value.length;
                    rotation = value.rotation;
                }
            
            //------------------------------------------------
            //回転制限
            //------------------------------------------------
                public function get minRotation():Number {
                    return _minRotation;
                }
                
                public function set minRotation(value:Number):void {
                    _minRotation = value;
                }
                
                public function get maxRotation():Number {
                    return _maxRotation;
                }
                
                public function set maxRotation(value:Number):void {
                    _maxRotation = value;
                }


            //------------------------------------------------
            //矢印
            //------------------------------------------------
                public function get arrow():Arrow {
                    return _arrow;
                }
                
                public function set arrow(value:Arrow):void {
                    _arrow = value;
                }
                



        //------------------------------------------------------------------------------
        //publicメソッド
        //------------------------------------------------------------------------------
            //---------------------------------------------------
            //テスト用
            //---------------------------------------------------
                public function active():void {
                    _circle.graphics.clear()
                    if (id == 'root') {
                        _circle.graphics.beginFill(0xFF0000,0.5);
                        _circle.graphics.drawCircle(0, 0, 10);
                    } else {
                        _circle.graphics.beginFill(0xFF0000,1);
                        _circle.graphics.drawCircle(0, 0, 4);
                    }
                }
                
                public function normal():void {
                    _circle.graphics.clear()
                    if (id == 'root') {
                        _circle.graphics.beginFill(0x339933,0.5);
                        _circle.graphics.drawCircle(0, 0, 10);
                    } else {
                        _circle.graphics.beginFill(0x339933,1);
                        _circle.graphics.drawCircle(0, 0, 4);
                    }
                    
                }
            //-------------------------------------------------
            //操作
            //-------------------------------------------------
                //-------------------------------------------------
                //可動範囲を設定する
                //-------------------------------------------------
                public function setRotationRange($min:Number = -180, $max:Number = 180):void {
                    _minRotation = $min;
                    _maxRotation = $max;
                    if (_rotationRange) {
                        _rotationRange.graphics.clear();
                        _rotationRange.graphics.lineStyle(0, 0xFF0000);
                        _rotationRange.graphics.lineTo(Math.cos($min*Math.PI/180) * 20, Math.sin($min*Math.PI/180) * 20);
                        _rotationRange.graphics.lineStyle(0, 0x0000FF);
                        _rotationRange.graphics.moveTo(0, 0);
                        _rotationRange.graphics.lineTo(Math.cos($max * Math.PI / 180) * 20, Math.sin($max * Math.PI / 180) * 20);
                    }
                }
            

                //-------------------------------------------------
                //矢印を回転させる。
                //可動範囲を超えた場合は、可動範囲内でとどめ、falseを返す
                //-------------------------------------------------
                public function vectorRotation(value:Number):Boolean {
                    var result:Boolean = true;
                    //可動範囲の比較
                    if (degree(value) < _minRotation) {
                        arrow.rotation = _minRotation;
                        rotation=_minRotation
                        result = false;

                    } else if (degree(value) > _maxRotation) {
                        arrow.rotation = _maxRotation;
                        rotation=_maxRotation
                        result = false;

                    } else {
                        rotation = value
                        arrow.rotation = rotation;
                    }
                    
                    
                    
                    
                    
                    
                    return result
                }

            //-------------------------------------------------
            //角度を常に-180~180で返す
            //-------------------------------------------------
            public function degree(value:Number):Number {
                value += 180;
                value %= 360;
                value += 360;
                value %= 360;
                value -= 180;
                return value;
            }

        //------------------------------------------------------------------------------
        //privateメソッド
        //------------------------------------------------------------------------------
        
    }


//=======================================================================================
//IKBone
//=======================================================================================
    import flash.display.Shape;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.*
    import flash.geom.Point;
    import flash.geom.Matrix;

    class IKBone2d extends IKJoint2d {
        public static const MOUSE_DOWN:String = 'mouse_down';
        public static const ROOT_DOWN:String = 'root_down';
        
    
        //new IKBone2d('ID名':String,長さ:Number,初期角度:Number,稼動範囲角度(負):Number,稼動範囲角度(正):Number,色)
        public function IKBone2d($id:String,$length:Number=100,$angle:Number=0,$minAngle:Number=-180,$maxAngle:Number=180,$key:Boolean=false,$color:uint=0x66FF66) {
            id = $id;
            childs = new Array();

            super(false,true,$color);

            _sAngle=$angle
            _sMinAngle=$minAngle
            _sMaxAngle=$maxAngle

            if (id != 'root') {
                bone=new Bone(true,$color);
                addChild(bone);
                length = $length;
                addEventListener(MouseEvent.MOUSE_DOWN, clickBone);
                keyBone = $key;

                var format:TextFormat=new TextFormat();
                format.color=0x666666
                format.size=14;
                format.font='_ゴシック';
                
                _Label = new TextField();
                _Label.autoSize=TextFieldAutoSize.LEFT
                _Label.selectable = false;
                _Label.mouseEnabled = false;
                _Label.multiline = false;
                _Label.x=-5
                _Label.y=10

                _Label.defaultTextFormat=format
                //addChild(Label);
                _Label.text = id;
            } else {
                keyBone = true;
                addEventListener(MouseEvent.MOUSE_DOWN, clickRoot);
            }
            

            this.addChild(_circle)


            //trace(superRotation,rotation)
        }

        
        //------------------------------------------------------------------------------
        //publicメソッド
        //------------------------------------------------------------------------------
            //---------------------------------------------------
            //操作
            //---------------------------------------------------
                //------------------------------------------
                //BoneをMouseDownした時のArrowの長さを元に戻す
                //------------------------------------------
                public function setDefaultLength():void {
                    _clickLength=0
                    arrow.length=length;
                }

                //------------------------------------------
                //見た目を選択状態を元に戻す
                //------------------------------------------
                public function selectOff():void {
                    bone.selectOff()
                }
                
                //------------------------------------------
                //見た目を選択状態にする
                //------------------------------------------
                public function selectOn():void {
                    bone.selectOn()
                }
                

                //-------------------------------------------------
                //角度設定はrotationやrotationXを使わずにこちらを使う
                //ただし、相対的な角度での設定になるため、見た目上での角度設定を行う場合は、
                //setDegreeSpecialやsetAngle使用
                //-------------------------------------------------
                public function setDegree(value:Number):Boolean {
                    return boneRotation(degree(value))
                }
                
                //-----------------------------------------------------------------------
                //設定の時など、y軸を中心に、左右対称に-180~180で角度を設定したい場合
                //-----------------------------------------------------------------------
                public function setDegreeSpecial(value:Number):Boolean {
                    return boneRotation(degree(value-90)-superRotation)
                }
                
                //-------------------------------------------------
                //superRotationに依存しない角度の指定
                //-------------------------------------------------
                override public function setAngle(value:Number):Boolean {
                    return boneRotation(value-superRotation)
                }
                
                //-------------------------------------------------
                //子のジョイントを登録する
                //-------------------------------------------------
                public function setChild(value:IKBone2d):void {
                    value.parentBone=this;
                    childs.push(value);
                }

                //-------------------------------------------------
                //矢印(ボーン)を回転させる。
                //可動範囲を超えた場合は、可動範囲内でとどめ、falseを返す
                //-------------------------------------------------
                public function boneRotation(value:Number):Boolean {
                    var result:Boolean
                    result = vectorRotation(value);

                    if (bone) {
                        bone.rotation=arrow.rotation
                    }
                    for (var i:uint = 0; i < childs.length; i++) {
                        childs[i].move()
                    }

                    return result;
                }
            

                //-------------------------------------------------
                //親が動いた時に、親から呼ばれる
                //-------------------------------------------------
                public function move():void {
                    if (parentBone) {
                        x = parentBone.tailPoint.x
                        y = parentBone.tailPoint.y
                        super.superX=x
                        super.superY=y
                        superRotation = parentBone.rotation + parentBone.superRotation;
                        _Label.rotation = -superRotation
                        if (!rotation) {
                            setRotationRange(_sMinAngle,_sMaxAngle)
                            setDegree(_sAngle);
                        }
                        bone.rotation = arrow.rotation


                    }
                    for (var i:uint = 0; i < childs.length; i++) {
                        childs[i].move()
                    }
                }
        
        
        //------------------------------------------------------------------------------
        //Setter Getter
        //------------------------------------------------------------------------------
            //-------------------------------------------------------
            //
            //-------------------------------------------------------
                public function set parentBone(value:IKBone2d):void {
                    _parentBone = value;
                }

                public function get parentBone():IKBone2d {
                    return _parentBone;
                }

                public function get childs():Array {
                    return _childs;
                }
                
                public function set childs(value:Array):void {
                    _childs = value;
                }

                public function set bone(value:Bone):void {
                    _bone = value;
                }

                public function get bone():Bone {
                    return _bone;
                }

            //------------------------------------------------
            //ベクトル(Boneの終端)を返す
            //------------------------------------------------
                public function get boneTailPoint():Point {
                    var result:Point
                    if (_clickLength) {
                        result = new Point(_clickLength,0);
                    } else {
                        result = new Point(length,0);
                    }
                    var mtx:Matrix = new Matrix();
                    mtx.rotate(superRotation*Math.PI/180);
                    mtx.rotate(rotation*Math.PI/180);
                    mtx.translate(x, y);
                    result = mtx.transformPoint(result);
                    return result;
                }



            //-------------------------------------------------------
            //長さ
            //-------------------------------------------------------
                override public function set length(value:Number):void {
                    super.length = value;
                    if (bone) {
                        bone.length = value;
                    }
                    for (var i:uint = 0; i < childs.length; i++) {
                        childs[i].move()
                    }
                }




            //-------------------------------------------------------
            //clone
            //-------------------------------------------------------
                override public function get clone():Object {
                    var result:Object = super.clone
                    result.parentBone = parentBone;
                    result.childs = childs;

                    return result;
                }
                
                override public function set clone(value:Object):void {
                    super.clone = value;
                    this.parentBone = value.parentBone;
                    this.childs = value.childs;

                }

                
                
                public function get keyBone():Boolean {
                    return _keyBone;
                }
                
                public function set keyBone(value:Boolean):void {
                    _keyBone = value;
                    if (bone) {
                        if (_keyBone) {
                            active()
                        } else {
                            normal()
                        }
                    }

                }
    
        
        //------------------------------------------------------------------------------
        //privateメソッド
        //------------------------------------------------------------------------------
            private var _sAngle:Number
            private var _sMinAngle:Number
            private var _sMaxAngle:Number
            private var _parentBone:IKBone2d;
            private var _childs:Array;
            private var _clickLength:Number;
            private var _bone:Bone;
            private var _Label:TextField;
            private var _keyBone:Boolean=false
        
        
            private function clickBone(e:MouseEvent):void {
                _clickLength=bone.mouseX
                if (_clickLength < 20) {
                    _clickLength = 20;
                    if (_clickLength > length) {
                        _clickLength = length;
                    }
                }
                
                arrow.length=_clickLength;
                dispatchEvent(new MouseEvent(MOUSE_DOWN,true,false,NaN,NaN,null,e.ctrlKey));

            }

            private function clickRoot(e:MouseEvent):void {
                dispatchEvent(new MouseEvent(ROOT_DOWN));

            }




    }


//=======================================================================================
//Bone
//=======================================================================================
import flash.display.Sprite;

class Bone extends Sprite {
    private const SELECT_COLOR:uint = 0x0000FF;
    
    private var _length:Number;
    private var _color:uint;
    private var _nowColor:uint;
    private var _test:Boolean;

    public function Bone($test:Boolean=true,$color:uint = 0x66FF66, $length:Number = 100) {

        _test=$test;
        _color = $color;
        length = $length;
        _nowColor = _color;
    }


    public function set length(value:Number):void {
        _length = value;
        makeBone()
    }

    public function selectOn():void {
        _nowColor = SELECT_COLOR;
        makeBone();
    }
    
    public function selectOff():void {
        _nowColor = _color;
        makeBone();
    }

    
    private function makeBone():void {
        if (_test) {
            //bone画像の生成
            graphics.clear();
            graphics.beginFill(_nowColor, 0.3);
            graphics.moveTo(0, 0);
            if (_length > 10) {
                graphics.lineTo(5,-7);
                graphics.lineTo(_length - 5,-2);
                graphics.lineTo(_length,0);
                graphics.lineTo(_length - 5,2);
                graphics.lineTo(5,7);
            } else {
                graphics.lineTo(_length / 2, -7);
                graphics.lineTo(_length - 5,-2);
                graphics.lineTo(_length - 5,2);
                graphics.lineTo(_length / 2, 7);
            }
            graphics.endFill();
            graphics.beginFill(0xFFFFFF, 0);
            graphics.drawCircle(_length, 0, 4);
        }
    }




    public function get length():Number {
        return _length;
    }
    
}





//=======================================================================================
//Vector2d
//=======================================================================================

    import flash.geom.Point;

    class Vector2d extends Object {
        private var _x:Number;
        private var _y:Number;
        private var _rotation:Number;
        private var _length:Number;

        public function Vector2d ($x:Number = 0, $y:Number = 0, $length:Number = 0, $rotation:Number = 0) {
            x = $x;
            y = $y;
            length = $length;
            rotation = $rotation;
            
        }

        public function get x():Number {
            return _x;
        }
        
        public function set x(value:Number):void {
            _x = value;
        }
        
        public function get y():Number {
            return _y;
        }
        
        public function set y(value:Number):void {
            _y = value;
        }
        
        public function get rotation():Number {
            return _rotation;
        }
        
        public function set rotation(value:Number):void {
            _rotation = value;
        }
        
        public function get length():Number {
            return _length;
        }
        
        public function set length(value:Number):void {
            _length = value;
        }
        
        public function get point():Point {
            return new Point(x,y)
        }

        public function set point(value:Point):void {
            x = value.x;
            y = value.y;
            
        }

    }




//----------------------------------------------------------------------
//簡易Component
//----------------------------------------------------------------------
    class myConstant extends Object{
        public var cursorLock:Boolean=false;
        public var scrollId:uint=0;
        public var scrollNum:uint=0;
        public var scrollDefaultId:uint=0;

        public function myConstant() {
        }

    }
    
//----------------------------------------------------------------------
//簡易Component
//----------------------------------------------------------------------

    import flash.display.Sprite;
    import flash.text.*;
    import flash.events.Event;
    class myComponent extends Sprite {
        public static const fontSize:Number=13
        public var format:TextFormat
        public var _rootObj:*
        public var myConst:myConstant

        public function myComponent() {
            format=new TextFormat();
            format.color = 0x333333
            format.leading = 2
            format.size=fontSize;
            //format.font='_等幅';
            format.font='_ゴシック';

            this.addEventListener(Event.ADDED_TO_STAGE,onAddedToStage);
        }

        private function onAddedToStage(e:Event):void {
            this.removeEventListener(Event.ADDED_TO_STAGE,onAddedToStage);
            _rootObj = parent.root
            if(_rootObj) {
                if(_rootObj.hasOwnProperty('myConst')) {
                    myConst = _rootObj.myConst
                }
            }
        }

    }
    
    
//----------------------------------------------------------------------
//簡易チェックボックス
//----------------------------------------------------------------------
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.display.GradientType;
    import flash.display.LineScaleMode
    import flash.text.*;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.geom.Matrix;

    class myCheckBox extends myComponent {
        public static const CHANGE:String = "check_change";

        private var states:Sprite
        private var back:Shape

        private var onState:Shape
        private var onStateOver:Shape
        private var offState:Shape
        private var offStateOver:Shape
        private var onStateDisable:Shape
        private var offStateDisable:Shape

        private var label:TextField

        public var onFlag:Boolean=false;

        public var str:String
        public var value:String


        public function myCheckBox($str:String,$x:Number=0,$y:Number=0,$w:Number=100,$h:Number=20) {
            back = new Shape()
            back.graphics.beginFill(0xFFFFFF,0)
            back.graphics.drawRect(0,0,20,$h)
            this.addChild(back);
            str=$str
            states=new Sprite();
            this.addChild(states);

            onState=makeState('onState')
            onStateOver=makeState('onStateOver')
            offState=makeState('offState')
            offStateOver=makeState('offStateOver')

            onStateDisable=makeState('onStateDisable')
            offStateDisable=makeState('offStateDisable')

            states.addChild(onState)
            states.addChild(onStateOver)
            states.addChild(offState)
            states.addChild(offStateOver)
            states.addChild(onStateDisable)
            states.addChild(offStateDisable)
            states.y=4

            offState.visible=true;
            onState.visible=false;
            onStateOver.visible=false;
            offStateOver.visible=false;
            onStateDisable.visible=false;
            offStateDisable.visible=false;

            label=new TextField()
            label.defaultTextFormat = format
            label.autoSize=TextFieldAutoSize.LEFT
            label.selectable=false;
            label.mouseEnabled=false;
            label.htmlText=$str;
            this.addChild(label)
            label.x=20
            label.y=3

            back.width=this.width

            this.x=$x
            this.y=$y

            this.addEventListener(MouseEvent.MOUSE_OVER,onMouseOver)
            this.addEventListener(MouseEvent.MOUSE_OUT,onMouseOut)
            this.addEventListener(MouseEvent.CLICK,onClick)

        }

        public function tabSet(value:uint):Boolean {
            states.tabEnabled=true;
            states.tabChildren=false;
            states.tabIndex=value
            return true
        }


        private function onMouseOver(e:MouseEvent):void {
            if (onFlag) {
                onState.visible=false
                onStateOver.visible=true
            } else {
                offState.visible=false
                offStateOver.visible=true
            }
        }

        private function onMouseOut(e:MouseEvent):void {
            if (onFlag) {
                onState.visible=true
                onStateOver.visible=false
            } else {
                offState.visible=true
                offStateOver.visible=false
            }
        }

        public function onClick(e:MouseEvent=null):void {
            if (onFlag) {
                onFlag=false
                onStateOver.visible=false
                offStateOver.visible=true
                value='';

            } else {
                onFlag=true
                if (e) {
                    offStateOver.visible=false
                    onStateOver.visible=true
                } else {
                    offState.visible=false
                    onState.visible=true
                }
                value=str

            }
            if (e) {
                dispatchEvent(new Event(CHANGE));
            }
        }


        private function checkMark(mc:Shape):void {
            mc.graphics.beginFill(0x666666,1)
            mc.graphics.moveTo(2,6)
            mc.graphics.lineTo(5,8)
            mc.graphics.lineTo(11,2)
            mc.graphics.lineTo(12,2)
            mc.graphics.lineTo(6,12)
            mc.graphics.lineTo(5,12)
            mc.graphics.lineTo(2,7)
            mc.graphics.endFill()
        }

        private function makeState(mode:String):Shape {
            var result:Shape = new Shape()
            var colors:Array=new Array(0xFFFFFF,0x999999)
            var alphas:Array=new Array(1,1)
            var ratios:Array=new Array(100,255)
            var matrix:Matrix=new Matrix()
                    matrix.createGradientBox(18,18,0,-1,0)

            result.graphics.beginFill(0x666666,1)
            result.graphics.drawRect(0,0,14,14)
            switch (mode) {
                case 'onState':
                    result.graphics.beginFill(0xFFFFFF,1)
                    result.graphics.drawRect(1,1,12,12)
                    result.graphics.beginGradientFill(GradientType.RADIAL    ,colors, alphas, ratios, matrix)
                    result.graphics.drawRect(2,2,10,10)
                    checkMark(result)

                break
                case 'onStateOver':
                    result.graphics.beginFill(0xFFFFFF,1)
                    result.graphics.drawRect(1,1,12,12)
                    result.graphics.beginGradientFill(GradientType.RADIAL    ,colors, alphas, ratios, matrix)
                    result.graphics.drawRect(2,2,10,10)
                    result.graphics.beginFill(0x3399FF,0.2)
                    result.graphics.drawRect(1,1,12,12)

                    checkMark(result)

                break
                case 'offState':
                    result.graphics.beginFill(0xFFFFFF,1)
                    result.graphics.drawRect(1,1,12,12)
                    result.graphics.beginGradientFill(GradientType.RADIAL    ,colors, alphas, ratios, matrix)
                    result.graphics.drawRect(2,2,10,10)
                break
                case 'offStateOver':
                    result.graphics.beginFill(0xFFFFFF,1)
                    result.graphics.drawRect(1,1,12,12)
                    result.graphics.beginGradientFill(GradientType.RADIAL    ,colors, alphas, ratios, matrix)
                    result.graphics.drawRect(2,2,10,10)
                    result.graphics.beginFill(0x3399FF,0.2)
                    result.graphics.drawRect(1,1,12,12)
                break
                case 'onStateDisable':
                    result.graphics.beginFill(0xCCCCCC,1)
                    result.graphics.drawRect(1,1,12,12)
                    colors=new Array(0xCCCCCC,0x999999)
                    result.graphics.beginGradientFill(GradientType.RADIAL    ,colors, alphas, ratios, matrix)
                    result.graphics.drawRect(2,2,10,10)
                    checkMark(result)

                break
                case 'offStateDisable':
                    result.graphics.beginFill(0xCCCCCC,1)
                    result.graphics.drawRect(1,1,12,12)
                    colors=new Array(0xCCCCCC,0x999999)
                    result.graphics.beginGradientFill(GradientType.RADIAL    ,colors, alphas, ratios, matrix)
                    result.graphics.drawRect(2,2,10,10)
                break

            }

            return result
        }



    }



    
    
    



import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.Capabilities;
import flash.system.IME;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.ui.Mouse;

/**
 * 値が変更された直後に送出されます。
 * @eventType flash.events.Event.CHANGE
 */
[Event(name="change", type="flash.events.Event")]
/**
 * DraggableTextInput クラスはスライダーと直接入力の両方をサポートする数値入力インターフェースです。
 * @author yasu
 * @see http://clockmaker.jp/
 *
 */
internal class DraggableTextInput extends Sprite
{
        protected static const TEXTFORMAT_DEFAUT:TextFormat = new TextFormat("Arial", 11, 0x157bbe, null, null, true);
        protected static const TEXTFORMAT_SLIDING:TextFormat = new TextFormat("Arial", 11, 0xFFFFFF, null, null, true);
        protected static const TEXTFORMAT_INPUT:TextFormat = new TextFormat("Arial", 11, 0x000000, null, null, false);
        protected static const TEXTFIELD_HEIGHT:Number = 21;
        protected static const TEXTFIELD_WIDTH:Number = 50;

        /**
         * 新しい DraggableTextInput インスタンスを作成します。
         */
        public function DraggableTextInput()
        {
                initialize();
        }

        /**
         * ゼロ以外の場合、有効値は、このプロパティの整数倍と minimum の合計および maximum 以下になります。
         * @return
         *
         */
        public function get snapInterval():Number
        {
                return _snapInterval;
        }

        public function set snapInterval(value:Number):void
        {
                if (value == 0)
                        throw new Error();

                _snapInterval = value;
        }

        /**
         * value の有効な最大値です。
         */
        public function get maximum():Number
        {
                return _maximum;
        }

        public function set maximum(value:Number):void
        {
                _maximum = value;
                _value = Math.min(_maximum, _value);
        }

        /**
         * value の有効な最少値です。
         */
        public function get minimum():Number
        {
                return _minimum;
        }

        public function set minimum(value:Number):void
        {
                _minimum = value;
                _value = Math.max(_minimum, _value);
        }

        /**
         * この範囲の現在の値です。
         */
        public function get value():Number
        {
                return Number(_label.text);
        }

        public function set value(value:Number):void
        {
                _value = Math.max(_minimum, Math.min(_maximum, value));

                _label.text = _format(_value);
        }

        /**
         * 桁揃えの桁の数値です。
         */
        public var formatRatio:int = -2;

        protected var _value:Number;
        protected var _label:TextField;
        protected var _bg:Shape;
        protected var _pointDown:Point;
        protected var _focusShape:Shape;
        protected var _valueOld:Number;
        protected var _minimum:Number = int.MIN_VALUE;
        protected var _maximum:Number = int.MAX_VALUE;
        protected var _snapInterval:Number = 1;
        protected var _isMouseDown:Boolean;
        protected var _isMouseMove:Boolean;
        private var _arrow:Bitmap;

        /**
         * インスタンスが保持しているデータを破棄します。
         */
        public function finalize():void
        {
                _label.removeEventListener(Event.CHANGE, _onLabelChange);
                removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
                removeEventListener(MouseEvent.CLICK, _onClick);
        }

        protected function initialize():void
        {
                _bg = new Shape();
                addChild(_bg);

                _focusShape = new Shape();
                _focusShape.graphics.beginFill(0x53b6f9);
                _focusShape.graphics.drawRect(0, 0, 5, 5);
                _focusShape.graphics.endFill();
                _focusShape.graphics.beginFill(0x737373);
                _focusShape.graphics.drawRect(1, 1, 3, 3);
                _focusShape.graphics.endFill();
                _focusShape.graphics.beginFill(0xFFFFFF);
                _focusShape.graphics.drawRect(2, 2, 1, 1);
                _focusShape.graphics.endFill();
                _focusShape.scale9Grid = new Rectangle(2, 2, 1, 1);
                addChild(_focusShape);

                _focusShape.width = TEXTFIELD_WIDTH;
                _focusShape.height = TEXTFIELD_HEIGHT;
                _focusShape.visible = false;

                _label = new TextField();
                _label.type = TextFieldType.DYNAMIC;
                _label.selectable = false;
                _label.x = 2;
                _label.y = 2;
                _label.width = TEXTFIELD_WIDTH - 4;
                _label.height = TEXTFIELD_HEIGHT - 4;
                _label.restrict = "0-9.\\-";
                _label.addEventListener(Event.CHANGE, _onLabelChange);
                addChild(_label);

                // use http://wonderfl.net/c/8TK2
                var arr:Array = [
                        [0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0],
                        [0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0],
                        [0, 2, 1, 1, 2, 2, 2, 0, 2, 2, 2, 1, 1, 2, 0],
                        [2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 2],
                        [0, 2, 1, 1, 2, 2, 2, 0, 2, 2, 2, 1, 1, 2, 0],
                        [0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0],
                        [0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0]
                        ];
                var bmd:BitmapData = new BitmapData(15, 7, true, 0x0);
                bmd.lock();
                for (var i:int = 0; i < arr.length; i++)
                {
                        for (var j:int = 0; j < arr[i].length; j++)
                        {
                                bmd.setPixel32(j, i, arr[i][j] == 0 ? 0x0 : arr[i][j] == 1 ? 0xFF000000 : 0xFFFFFFFF);
                        }
                }
                bmd.unlock();

                _arrow = new Bitmap(bmd);

                _label.defaultTextFormat = TEXTFORMAT_DEFAUT;

                addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDown);
                addEventListener(MouseEvent.CLICK, _onClick);
        }

        protected function _onClick(event:MouseEvent):void
        {
                if (_isMouseDown)
                        return;

                if (_focusShape.visible == true)
                        return;

                if (Capabilities.hasIME)
                {
                        try
                        {
                                IME.enabled = false;
                        }
                        catch (error:Error)
                        {
                        }
                }

                _valueOld = Number(_label.text);
                _label.type = TextFieldType.INPUT;
                _label.selectable = true;
                _label.setSelection(0, _label.length);
                _label.defaultTextFormat = TEXTFORMAT_INPUT;
                _label.text = _label.text;

                _focusShape.visible = true;

                stage.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseDownForCommit);
                stage.addEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
        }

        protected function _onKeyDown(event:KeyboardEvent):void
        {
                switch (event.keyCode)
                {
                        case Keyboard.ENTER:
                                _commitProperties();
                                break;
                        case Keyboard.ESCAPE:
                                _label.text = _valueOld.toString(10);
                                _commitProperties();
                                break;
                        case Keyboard.UP:
                                _updateValue(Number(_label.text) + _snapInterval);
                                _label.setSelection(0, _label.length);
                                break;
                        case Keyboard.DOWN:
                                _updateValue(Number(_label.text) - _snapInterval);
                                _label.setSelection(0, _label.length);
                                break;
                }
        }

        protected function _onMouseDownForCommit(event:MouseEvent):void
        {
                if (event.target == _label)
                        return;

                _commitProperties();
        }

        protected function _commitProperties():void
        {
                var valueNew:Number = Number(_label.text);
                if (valueNew < _minimum || valueNew > _maximum)
                {
                        valueNew = _valueOld;
                }

                stage.removeEventListener(KeyboardEvent.KEY_DOWN, _onKeyDown);
                stage.removeEventListener(MouseEvent.MOUSE_DOWN, _onMouseDownForCommit);

                _label.defaultTextFormat = TEXTFORMAT_DEFAUT;
                _label.selectable = false;
                _label.type = TextFieldType.DYNAMIC;
                _label.text = _format(valueNew)

                _focusShape.visible = false;

                _dispatchChangeEvent();
        }

        protected function _onMouseDown(event:MouseEvent):void
        {
                if (_label.type == TextFieldType.INPUT)
                        return;

                stage.addEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);

                _label.defaultTextFormat = TEXTFORMAT_SLIDING;

                _label.text = _label.text;
                _pointDown = new Point(mouseX, mouseY);

                _valueOld = Number(_label.text);

                _bg.graphics.clear();
                _bg.graphics.beginFill(0x157bbe);
                _bg.graphics.drawRect(0, 0, _label.textWidth + 8, TEXTFIELD_HEIGHT);

                Mouse.hide();
                stage.addChild(_arrow);
                _arrow.x = stage.mouseX - int( _arrow.width / 2 );
                _arrow.y = stage.mouseY - int( _arrow.height / 2);

                _isMouseDown = false;
                _isMouseMove = false;
        }

        protected function _onMouseMove(event:MouseEvent):void
        {
                _isMouseMove = true;

                var vx:Number = +1 * (mouseX - _pointDown.x);
                var vy:Number = -1 * (mouseY - _pointDown.y);

                var d:Number = (vx + vy) * _snapInterval;

                _updateValue(_valueOld + d);

                _bg.graphics.clear();
                _bg.graphics.beginFill(0x157bbe);
                _bg.graphics.drawRect(0, 0, _label.textWidth + 8, TEXTFIELD_HEIGHT);

                _dispatchChangeEvent();

                _arrow.x = stage.mouseX - int( _arrow.width / 2 );
                _arrow.y = stage.mouseY - int( _arrow.height / 2);
        }

        protected function _updateValue(valueNew:Number):void
        {
                valueNew = Math.max(_minimum, Math.min(_maximum, valueNew));
                _label.text = _format(valueNew);
        }

        protected function _onMouseUp(event:MouseEvent):void
        {
                _bg.graphics.clear();
                stage.removeEventListener(MouseEvent.MOUSE_UP, _onMouseUp);
                stage.removeEventListener(MouseEvent.MOUSE_MOVE, _onMouseMove);

                _label.defaultTextFormat = TEXTFORMAT_DEFAUT;
                _label.text = _label.text;

                if (event.target == _label && _isMouseMove)
                        _isMouseDown = true;

                Mouse.show();
                stage.removeChild(_arrow);
        }

        /**
         * 値をフォーマットします。
         * @param val フォーマットしたい値。
         * @return フォーマットされた文字列。
         */
        protected function _format(val:Number):String
        {
                var nn:Number = Math.pow(10, formatRatio);
                var valueNew:Number = Math.round(val / nn) * nn;

                var str:String = valueNew.toString(10);
                var arr:Array = str.split(".");

                var decimal:String = arr[1] || "00";
                var ratio:Number = Math.abs(formatRatio);
                if (decimal.length < ratio)
                {
                        while (decimal.length < ratio)
                        {
                                decimal = decimal + "0";
                        }
                }
                else
                {
                        decimal = decimal.substr(0, ratio);
                }
                if (ratio == 0)
                        decimal = "0";
                return arr[0] + "." + decimal;
        }

        protected function _dispatchChangeEvent():void
        {
                dispatchEvent(new Event(Event.CHANGE));
        }

        private function _onLabelChange(event:Event):void
        {
                event.stopPropagation();
        }
}