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

反重力ポイント

反重力ポイント

@author tkinjo
/**
 * Copyright tkinjo ( http://wonderfl.net/user/tkinjo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/s132
 */

// forked from tkinjo's 反重力ポイント(四方の壁)フォースマップ
// forked from tkinjo's forked from: カラーグリッド
// forked from tkinjo's カラーグリッド
// forked from tkinjo's ストライプ
// forked from tkinjo's minimalcomps を使ってコンポーネントを作ってみた
package
{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import com.bit101.components.*;
    import flash.ui.Mouse;
    
    [SWF(width="465", height="465", backgroundColor="0xffffff", frameRate="60")] 
    /**
     * 反重力ポイント
     * 
     * @author tkinjo
     */
    public class Main extends Sprite
    {
        private const MAX_POWER:Number = 100;
        
        private var stageWidth:Number = stage.stageWidth;
        private var stageHeight:Number = stage.stageHeight;
        
        /** --------------------------------------------------
         * component
         */
        private var configPanel:SlidePanel;
        private var gridNumInputTextAndHSlider:InputTextAndHSlider;
        private var wallPowerInputTextAndHSlider:InputTextAndHSlider;
        private var wallDecreasingPowerInputTextAndHSlider:InputTextAndHSlider;
        private var gravityPointPowerInputTextAndHSlider:InputTextAndHSlider;
        private var gravityPointDecreasingPowerInputTextAndHSlider:InputTextAndHSlider;
        
        private var selectPushButton:PushButton;
        private var influencedPointPushButton:PushButton;
        private var gravityPointPushButton:PushButton;
        
        /** --------------------------------------------------
         * 
         */
        private var gravitySprites:Vector.<GravitySprite>;
        private var influencedPoints:Vector.<Particle>;
        
        private var viewBitmapData:BitmapData;
        private var viewBitmap:Bitmap;
        private var view:Sprite;
        
        private var movedSprite:Sprite;
        
        public function Main() 
        {
            setComponents();
            
            influencedPoints = new Vector.<Particle>();
            gravitySprites = new Vector.<GravitySprite>();
            influencedPointPushButton.selected = true;
            
            view.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler );
            stage.addEventListener(MouseEvent.MOUSE_UP,   mouseUpHandler );
            stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler );
            addEventListener(Event.ENTER_FRAME, enterframeHandler );
            
            draw();
        }
        
        private function setComponents():void {
            
            viewBitmapData = new BitmapData( stageWidth, stageHeight, true, 0x0 );
            viewBitmap = new Bitmap( viewBitmapData );
            view = new Sprite();
            view.addChild( viewBitmap );
            addChild( view );
            
            
            
            configPanel = new SlidePanel( 0, 0, stageWidth, 0, 1, 0xffffff, 0.9 );
            addChild( configPanel );
            
            
            
            // gridNumInputTextAndHSlider
            gridNumInputTextAndHSlider = createInputTextAndHSlider( "resolution" );
            gridNumInputTextAndHSlider.round = 0;
            gridNumInputTextAndHSlider.value = 32;
            gridNumInputTextAndHSlider.hSlider.maximum = 32;
            gridNumInputTextAndHSlider.addEventListener(Event.CHANGE, function( event:Event ):void {
                    
                    draw();
                } );
            
            // wall power
            wallPowerInputTextAndHSlider = createInputTextAndHSlider( "wall power", gridNumInputTextAndHSlider );
            wallPowerInputTextAndHSlider.round = 0;
            wallPowerInputTextAndHSlider.hSlider.maximum = 100;
            wallPowerInputTextAndHSlider.hSlider.minimum = -100;
            wallPowerInputTextAndHSlider.value = 10;
            wallPowerInputTextAndHSlider.addEventListener(Event.CHANGE, function( event:Event ):void {
                    draw();
                } );
            
            // wall dpower
            wallDecreasingPowerInputTextAndHSlider = createInputTextAndHSlider( "wall dpower", wallPowerInputTextAndHSlider );
            wallDecreasingPowerInputTextAndHSlider.round = 1;
            wallDecreasingPowerInputTextAndHSlider.hSlider.maximum = 10;
            wallDecreasingPowerInputTextAndHSlider.hSlider.minimum = -10;
            wallDecreasingPowerInputTextAndHSlider.value = 2;
            wallDecreasingPowerInputTextAndHSlider.addEventListener(Event.CHANGE, function( event:Event ):void {
                    draw();
                } );
            
            // gravityPoint power
            gravityPointPowerInputTextAndHSlider = createInputTextAndHSlider( "gpoint power", wallDecreasingPowerInputTextAndHSlider );
            gravityPointPowerInputTextAndHSlider.round = 0;
            gravityPointPowerInputTextAndHSlider.hSlider.maximum = 100;
            gravityPointPowerInputTextAndHSlider.hSlider.minimum = -100;
            gravityPointPowerInputTextAndHSlider.value = 10;
            gravityPointPowerInputTextAndHSlider.addEventListener(Event.CHANGE, function( event:Event ):void {
                    for ( var i:uint = 0; i < gravitySprites.length; i++ ) {
                        gravitySprites[i].gravityPoint.power = gravityPointPowerInputTextAndHSlider.value;
                    }
                    draw();
                } );
            
            // gravityPoint dpower
            gravityPointDecreasingPowerInputTextAndHSlider = createInputTextAndHSlider( "gpoint dpower", gravityPointPowerInputTextAndHSlider );
            gravityPointDecreasingPowerInputTextAndHSlider.round = 1;
            gravityPointDecreasingPowerInputTextAndHSlider.hSlider.maximum = 10;
            gravityPointDecreasingPowerInputTextAndHSlider.hSlider.minimum = -10;
            gravityPointDecreasingPowerInputTextAndHSlider.value = 2;
            gravityPointDecreasingPowerInputTextAndHSlider.addEventListener(Event.CHANGE, function( event:Event ):void {
                    for ( var i:uint = 0; i < gravitySprites.length; i++ ) {
                        gravitySprites[i].gravityPoint.decreasingPower = gravityPointDecreasingPowerInputTextAndHSlider.value;
                    }
                    draw();
                } );
            
            // select
            selectPushButton = createPushButton( "select", gravityPointDecreasingPowerInputTextAndHSlider, true );
            selectPushButton.toggle = true;
            selectPushButton.addEventListener(MouseEvent.CLICK, function( event:MouseEvent ):void {
                    if ( selectPushButton.selected ) {
                        unselectedPushButton();
                        selectPushButton.selected = true;
                    } else 
                        selectPushButton.selected = true;
                } );
            
            // influenced point
            influencedPointPushButton = createPushButton( "influenced point", selectPushButton );
            influencedPointPushButton.toggle = true;
            influencedPointPushButton.addEventListener(MouseEvent.CLICK, function( event:MouseEvent ):void {
                    if ( influencedPointPushButton.selected ) {
                        unselectedPushButton();
                        influencedPointPushButton.selected = true;
                    } else 
                        selectPushButton.selected = true;
                } );
            
            // gravity point
            gravityPointPushButton = createPushButton( "gravity point", influencedPointPushButton );
            gravityPointPushButton.toggle = true;
            gravityPointPushButton.addEventListener(MouseEvent.CLICK, function( event:MouseEvent ):void {
                    if ( gravityPointPushButton.selected ) {
                        unselectedPushButton();
                        gravityPointPushButton.selected = true;
                    } else 
                        selectPushButton.selected = true;
                } );
            
            configPanel.height = gravityPointPushButton.y + gravityPointPushButton.height + 15;
            
            
            // hueCircle
            var hueCircle:HueCircle = new HueCircle( 50, 30 );
            hueCircle.x = hueCircle.radius + stageWidth - hueCircle.width;
            hueCircle.y = hueCircle.radius + stageHeight - hueCircle.height;
            hueCircle.graphics.beginFill( 0xffffff );
            hueCircle.graphics.drawRect( -hueCircle.radius, -hueCircle.radius, hueCircle.width, hueCircle.height );
            hueCircle.graphics.endFill();
            addChild( hueCircle );
        }
        private function unselectedPushButton():void {
            
            selectPushButton.selected = false;
            influencedPointPushButton.selected = false;
            gravityPointPushButton.selected = false;
        }
        
        private function createInputTextAndHSlider( text:String = "", component:DisplayObject = null ):InputTextAndHSlider {
            
            var inputTextAndHSlider:InputTextAndHSlider = new InputTextAndHSlider( configPanel, 10, ( component != null ) ? component.y + component.height + 10 : 10, text );
            inputTextAndHSlider.label.width     = 70;
            inputTextAndHSlider.inputText.width = 30;
            inputTextAndHSlider.hSlider.width   = 300;
            
            return inputTextAndHSlider;
        }
        
        private function createPushButton( text:String = "", component:DisplayObject = null, newLine:Boolean = false ):PushButton {
            
            var pushButton:PushButton = new PushButton( configPanel, 
                    ( component != null && !newLine ) ? 
                        component.x + component.width + 10 : 
                        10, 
                    ( component != null ) ? 
                        ( ( newLine ) ? 
                            component.y + component.height + 10 : 
                            component.y 
                        ) : 
                        10,
                    text );
            
            return pushButton;
        }
        
        
        
        
        
        private function force( point:Point ):Point {
            
            var force:Point = new Point( 0, 0 );
            
            for ( var i:uint = 0; i < gravitySprites.length; i++ ) {
                
                var gravityPointForce:Point = gravitySprites[i].gravityPoint.force( point );
                force.x += gravityPointForce.x;
                force.y += gravityPointForce.y;
            }
            
            
            
            
            var wallPower:Number = wallPowerInputTextAndHSlider.value;
            var wallDecreasingPower:Number = wallDecreasingPowerInputTextAndHSlider.value;
            
            var topWallGravity:GravityPoint    = new GravityPoint( point.x,    0,           wallPower, wallDecreasingPower );
            var rightWallGravity:GravityPoint  = new GravityPoint( stageWidth, point.y,     wallPower, wallDecreasingPower );
            var bottomWallGravity:GravityPoint = new GravityPoint( point.x,    stageHeight, wallPower, wallDecreasingPower );
            var leftWallGravity:GravityPoint   = new GravityPoint( 0,          point.y,     wallPower, wallDecreasingPower );
            
            var topWallForce:Point    = topWallGravity.force(    point );
            var rightWallForce:Point  = rightWallGravity.force(  point );
            var bottomWallForce:Point = bottomWallGravity.force( point );
            var leftWallForce:Point   = leftWallGravity.force(   point );
            
            force.y += topWallForce.y;
            force.x += rightWallForce.x;
            force.y += bottomWallForce.y;
            force.x += leftWallForce.x;
            
            return force;
        }
        
        private function draw():void {
            
            graphics.clear();
            
            var i:int;
            var j:int;
            
            var gridNum:Number = gridNumInputTextAndHSlider.value;
            var gridNumPower:Number = Math.pow( gridNum, 2 );
            var gridWidth:Number = stageWidth / gridNum;
            var gridHeight:Number = stageHeight / gridNum;
            
            var forces:Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>( gridNum );
            var maxForceLength:Number = 0;
            
            for ( i = 0; i < gridNum; i++ ) {
                
                forces[i] = new Vector.<Point>( gridNum );
                
                for ( j = 0; j < gridNum; j++ ) {
                    
                    var point:Point = new Point( i * stageWidth / gridNum + gridWidth / 2, j * stageHeight / gridNum + gridHeight / 2 );
                    forces[i][j] = force( point );
                    
                    var length:Number = forces[i][j].length;
                    if ( maxForceLength < length )
                        maxForceLength = length;
                }
            }
            
            var centerPoint:Point = new Point();
            for ( i = 0; i < gridNum; i++ ) {
                
                for ( j = 0; j < gridNum; j++ ) {
                    
                    //var color:int = HSVtoRGB( getHueCircleAngle( centerPoint, forces[i][j] ), forces[i][j].length / maxForceLength, 1 );
                    var color:int = HSVtoRGB( getHueCircleAngle( centerPoint, forces[i][j] ), 0.5, 1 );
                    
                    graphics.beginFill( color, 1 );
                    graphics.drawRect( i * stageWidth / gridNum, j * stageHeight / gridNum, gridWidth, gridHeight );
                    graphics.endFill();
                }
            }
        }
        
        private function enterframeHandler( event:Event ):void {
            
            var influencedPointPosition:Point = new Point();
            for ( var i:uint = 0; i < influencedPoints.length; i++ ) {
                
                var influencedPoint:Particle = influencedPoints[i];
                influencedPointPosition.x = influencedPoint.x;
                influencedPointPosition.y = influencedPoint.y;
                
                influencedPoint.vx = influencedPoint.vx * 0.98 + force( influencedPointPosition ).x * 0.5;
                influencedPoint.vy = influencedPoint.vy * 0.98 + force( influencedPointPosition ).y * 0.5;
                
                influencedPoint.x += influencedPoint.vx;
                influencedPoint.y += influencedPoint.vy;
                
                
                
                if (influencedPoint.x < 1) 
                    influencedPoint.x = 1;
                    
                else if ( influencedPoint.x > stageWidth - 1 ) 
                    influencedPoint.x = stageWidth - 1;
                
                
                
                if ( influencedPoint.y < 1 ) 
                    influencedPoint.y = 1;
                    
                else if ( influencedPoint.y > stageHeight - 1 ) 
                    influencedPoint.y = stageHeight - 1;
            }
        }
        
        private function mouseDownHandler( event:MouseEvent ):void {
            
            if ( influencedPointPushButton.selected ) {
                
                var particle:Particle = new Particle( event.stageX, event.stageY );
                influencedPoints.push( particle );
                view.addChild( particle );
                particle.addEventListener(MouseEvent.MOUSE_DOWN, function( event:MouseEvent ):void {
                        if ( selectPushButton.selected && movedSprite == null )
                            movedSprite = event.currentTarget as Sprite;
                    } );
                
            } else if ( gravityPointPushButton.selected ) {
                
                var gravitySprite:GravitySprite = new GravitySprite( event.stageX, event.stageY, 
                        gravityPointPowerInputTextAndHSlider.value, gravityPointDecreasingPowerInputTextAndHSlider.value );
                gravitySprites.push( gravitySprite );
                view.addChild( gravitySprite );
                draw();
                gravitySprite.addEventListener(MouseEvent.MOUSE_DOWN, function( event:MouseEvent ):void {
                        if ( selectPushButton.selected && movedSprite == null )
                            movedSprite = event.currentTarget as Sprite;
                    } );
            }
        }
        
        private function mouseUpHandler( event:MouseEvent ):void {
            movedSprite = null;
        }
        
        private function mouseMoveHandler( event:MouseEvent ):void {
            
            if ( movedSprite == null )
                return;
            
            movedSprite.x = event.stageX;
            movedSprite.y = event.stageY;
            
            if( movedSprite is GravitySprite )
                draw();
        }
    }
}



import com.bit101.components.*;
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.text.*;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.Cubic;


class GravityPoint extends Point {
    
    private var _power:Number;
    public function get power():Number {
        return _power;
    }
    public function set power(value:Number):void 
    {
        _power = value;
    }
    
    private var _decreasingPower:Number;
    public function get decreasingPower():Number {
        return _decreasingPower;
    }
    public function set decreasingPower(value:Number):void 
    {
        _decreasingPower = value;
    }
    
    
    public function force( point:Point ):Point {
        
        var positionFromPoint:Point = subtract( point );
        
        var forceLength:Number = power / Math.pow( positionFromPoint.length, decreasingPower );
        
        
        var angle:Number = Angle.normalizeRadianM180toP180(Math.PI/2 - Math.atan2(point.y - y, point.x - x)); 
        
        var forceX:Number = Math.sin(angle) * forceLength;
        var forceY:Number = Math.cos(angle) * forceLength;
        
        return new Point( forceX, forceY );
    }
    
    public function GravityPoint( x:Number, y:Number, power:Number = -1000, decreasingPower:Number = 2 ):void {
        
        super(x,y);
        
        _power = power;
        _decreasingPower = decreasingPower;
    }
}

class Angle {
    
    public static const RADIAN_0_DEGREE:Number   = 0;
    public static const RADIAN_90_DEGREE:Number  = Math.PI / 2;
    public static const RADIAN_180_DEGREE:Number = Math.PI;
    public static const RADIAN_270_DEGREE:Number = Math.PI / 2 * 3;
    public static const RADIAN_360_DEGREE:Number = 2 * Math.PI;
    
    public static function normalizeRadian0to360( value:Number ):Number {
        
        value %= Angle.RADIAN_360_DEGREE;

        if( value < RADIAN_0_DEGREE )
            value += Angle.RADIAN_360_DEGREE;
        
        return value;
    }
    
    public static function normalizeRadianM180toP180( value:Number ):Number {
        
        value = normalizeRadian0to360( value );
        
        if( value > RADIAN_180_DEGREE )
            value -= Angle.RADIAN_360_DEGREE;
        
        return value;
    }
}

class Particle extends Sprite {
    
    public var vx:Number;
    public var vy:Number;
    
    function Particle( x:Number = 0, y:Number = 0, vx:Number = 0, vy:Number = 0 ) {
        
        this.x = x;
        this.y = y;
        this.vx = vx;
        this.vy = vy;
        
        graphics.beginFill( 0x0 );
        graphics.drawCircle( 0, 0, 10 );
        graphics.endFill();
    }
}

class GravitySprite extends Sprite {
    
    public function get gravityPoint():GravityPoint { return _gravityPoint; }
    private var _gravityPoint:GravityPoint;
    
    public override function set x(value:Number):void {
        super.x = value;
        _gravityPoint.x = value;
    }
    
    public override function set y(value:Number):void 
    {
        super.y = value;
        _gravityPoint.y = value;
    }
    
    public function GravitySprite( x:Number = 0, y:Number = 0, power:Number = -1000, decreasingPower:Number = 2 ) {
        
        super.x = x;
        super.y = y;
        
        _gravityPoint = new GravityPoint( x, y, power, decreasingPower );
        
        graphics.beginFill( 0x0 );
        graphics.drawCircle( 0, 0, 10 );
        graphics.drawCircle( 0, 0, 8 );
        graphics.drawCircle( 0, 0, 6 );
        graphics.endFill();
    }
}






/* -----
 * component
 */

class LabelEx extends Label {
    
    /**
     * Dispatched after a control value is modified, unlike the textInput event, which is dispatched before the value is modified.
     * @eventType flash.events.Event.CHANGE
     */
    [Event(name = "change", type = "flash.events.Event")] 
    
    /**
     * ...
     * @eventType com.bit101.components.Component.DRAW
     */
    [Event(name = "draw", type = "com.bit101.components.Component")] 
    
    
    
    private var textField:TextField;
    
    public function LabelEx(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, text:String = ""):void
    {
        super(parent, xpos, ypos, text);
    }
    
    /**
     * Initializes the component.
     */
    override protected function init():void
    {
        super.init();
        setSize(100, 16);
    }
    
    /**
     * Creates and adds the child display objects of this component.
     */
    override protected function addChildren():void
    {
        super.addChildren();
        
        for ( var i:uint = 0; i < numChildren; i++ ) {
            
            var child:DisplayObject = getChildAt( i );
            
            if ( child is TextField ) {
                
                textField = child as TextField;
                break;
            }
        }
    }
}

class InputTextEx extends InputText {
    
    /**
     * Dispatched after a control value is modified, unlike the textInput event, which is dispatched before the value is modified.
     * @eventType flash.events.Event.CHANGE
     */
    [Event(name = "change", type = "flash.events.Event")] 
    
    /**
     * ...
     * @eventType com.bit101.components.Component.DRAW
     */
    [Event(name = "draw", type = "com.bit101.components.Component")] 
    
    private var textField:TextField;
    
    public function InputTextEx(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, text:String = "", defaultHandler:Function = null)
    {
        super( parent, xpos, ypos, text, defaultHandler );
    }
    
    /**
     * Creates and adds child display objects.
     */
    override protected function addChildren():void
    {
        super.addChildren();
        
        for ( var i:uint = 0; i < numChildren; i++ ) {
            
            var child:DisplayObject = getChildAt( i );
            
            if ( child is TextField ) {
                
                textField = child as TextField;
                break;
            }
        }
        
        textField.autoSize = TextFieldAutoSize.LEFT;
    }
    
    protected override function onChange(event:Event):void
    {
        super.onChange( event );
        dispatchEvent( event );
    }
}

class HSliderEx extends HSlider {
    
    /**
     * Dispatched after a control value is modified, unlike the textInput event, which is dispatched before the value is modified.
     * @eventType flash.events.Event.CHANGE
     */
    [Event(name = "change", type = "flash.events.Event")] 
    
    /**
     * ...
     * @eventType com.bit101.components.Component.DRAW
     */
    [Event(name = "draw", type = "com.bit101.components.Component")] 
    
    public function HSliderEx(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0, defaultHandler:Function = null):void
    {
        super(parent, xpos, ypos, defaultHandler);
    }
}

class InputTextAndHSlider extends Sprite {
    
    /**
     * Dispatched after a control value is modified, unlike the textInput event, which is dispatched before the value is modified.
     * @eventType flash.events.Event.CHANGE
     */
    [Event(name = "change", type = "flash.events.Event")]
    
    
    
    /**
     * label
     */
    public function get label():Label {
        
        return _label;
    }
    private var _label:Label;
    
    
    
    /**
     * inputText
     */
    public function get inputText():InputTextEx {
        
        return _inputText;
    }
    private var _inputText:InputTextEx;
    
    
    
    /**
     * hSlider
     */
    public function get hSlider():HSliderEx {
        
        return _hSlider;
    }
    private var _hSlider:HSliderEx;
    
    
    
    /**
     * round
     */
    public var round:int = 2;
    
    
    
    /**
     * value
     */
    public function get value():Number {
        
        return _value;
    }
    public function set value( tempValue:Number ):void {
        
        hSlider.value = tempValue;
        
        _value = Math.round( hSlider.value * Math.pow( 10, round ) ) / Math.pow( 10, round );
        
        if ( !isNaN( value ) )
            inputText.text = value.toString();
        
        dispatchEvent( new Event( Event.CHANGE ) );
    }
    private var _value:Number;
    
    
    
    /**
     * 
     * @param    parent
     * @param    xpos
     * @param    ypos
     * @param    text
     */
    public function InputTextAndHSlider(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0, text:String = ""):void
    {
        parent.addChild( this );
        x = xpos;
        y = ypos;
        
        // label
        _label = new LabelEx( this, 0, 0, text );
        
        // inputText
        _inputText = new InputTextEx( this );
        inputText.restrict = "-0-9.";
        updateInputTextPosition( label );
        
        // hSlider
        _hSlider = new HSliderEx( this );
        hSlider.backClick = true;
        updateHSliderPosition( inputText );
        
        
        
        // hSlider eventlistener
        label.addEventListener(Component.DRAW, function( event:Event ):void {
                updateInputTextPosition( label );
            } );
        
        // inputText eventlistener
        inputText.addEventListener(Event.CHANGE, function( event:Event ):void {
                value = parseFloat( inputText.text );
            } );
        inputText.addEventListener(Component.DRAW, function( event:Event ):void {
                updateHSliderPosition( inputText );
            } );
        inputText.addEventListener(FocusEvent.FOCUS_OUT, function( event:FocusEvent ):void {
                if ( isNaN( value ) )
                    inputText.text = "0";
            } );
        
        // hSlider eventlistener
        hSlider.addEventListener(Event.CHANGE, function( event:Event ):void {
                value = hSlider.value;
            } );
    }
    
    
    
    /**
     * 
     * @param    component
     */
    private function updateInputTextPosition( component:DisplayObject ):void {
        
        inputText.y = component.y + ( component.height - inputText.height ) / 2;
        inputText.x = ( component.x + component.width ) + ( inputText.y - component.y );
    }
    
    
    
    /**
     * 
     * @param    component
     */
    private function updateHSliderPosition( component:Component ):void {
        
        hSlider.y = component.y + ( component.height - hSlider.height ) / 2;
        hSlider.x = ( component.x + component.width ) + ( hSlider.y - component.y );
    }
}



class ClearColorPanel extends Sprite {
    
    private var _backgroundColor:Number;
    public function get backgroundColor():Number { return _backgroundColor; }
    public function set backgroundColor(value:Number):void 
    {
        _backgroundColor = value;
        draw();
    }
    
    
    
    private var _backgroundAlpha:Number;
    public function get backgroundAlpha():Number { return _backgroundAlpha; }
    public function set backgroundAlpha(value:Number):void 
    {
        _backgroundAlpha = value;
        draw();
    }
    
    private var _width:Number;
    public override function get width():Number { return _width; }
    public override function set width(value:Number):void 
    {
        _width = value;
        draw();
    }
    
    private var _height:Number;
    public override function get height():Number { return _height; }
    public override function set height(value:Number):void 
    {
        _height = value;
        draw();
    }
    
    
    
    
    
    public function ClearColorPanel( x:Number = 0, y:Number = 0, width:Number = 0, height:Number = 0, alpha:Number = 1, backgroundColor:int = 0, backgroundAlpha:Number = 0.1 ) {
        
        this.x = x;
        this.y = y;
        _width = width;
        _height = height;
        this.alpha = alpha;
        _backgroundColor = backgroundColor;
        _backgroundAlpha = backgroundAlpha;
        
        draw();
    }
    
    public function draw():void {
        
        graphics.clear();
        graphics.beginFill( backgroundColor, backgroundAlpha );
        graphics.drawRect( 0, 0, width, height );
        graphics.endFill();
    }
}

class SlidePanel extends Sprite {
    
    private var panel:ClearColorPanel;
    private var openCloseSwitchButton:PushButton;
    private var open:Boolean;
    
    
    public override function set width(value:Number):void 
    {
        super.width = value;
        panel.width = value;
        openCloseSwitchButton.x = width - 20;
    }
    
    public override function set height(value:Number):void 
    {
        super.height = height;
        panel.height = value;
    }
    
    
    public function SlidePanel( x:Number = 0, y:Number = 0, width:Number = 0, height:Number = 0, alpha:Number = 1, backgroundColor:int = 0, backgroundAlpha:Number = 0.1 ) {
        
        this.x = x;
        this.y = y;
        
        panel = new ClearColorPanel( 0, 0, width, height, alpha, backgroundColor, backgroundAlpha );
        super.addChild( panel );
        
        openCloseSwitchButton = new PushButton(super, width - 20, 0);
        super.addChild( openCloseSwitchButton );
        openCloseSwitchButton.width = 20;
        openCloseSwitchButton.addEventListener(MouseEvent.CLICK, openCloseSwitchButtonClickHandler );
        
        openCloseSwitchButton.label = "-";
        open = true;
    }
    
    private function openCloseSwitchButtonClickHandler( event:MouseEvent ):void {
        
        // hide
        if ( open )
            show();
            
        // show
        else
            hide();
    }
    
    private function show():void {
        
        open = false;
        openCloseSwitchButton.label = "+";
        BetweenAS3.tween(panel, {y: -panel.height}, null, 0.5, Cubic.easeInOut ).play();
    }
    
    private function hide():void {
        
        open = true;
        openCloseSwitchButton.label = "-";
        BetweenAS3.tween(panel, { y: 0 }, null, 0.5, Cubic.easeInOut ).play();
    }
    
    
    override public function addChild(child:DisplayObject):DisplayObject 
    {
        return panel.addChild(child);
    }
    
    override public function addChildAt(child:DisplayObject, index:int):DisplayObject 
    {
        return panel.addChildAt(child, index);
    }
}





















class HueCircle extends Sprite {
    
    public function get radius():Number { return _radius; }
    public function set radius(value:Number):void 
    {
        _radius = value;
        draw();
    }
    private var _radius:Number;
    
    
    
    public function get innerRadius():Number { return _innerRadius; }
    public function set innerRadius(value:Number):void 
    {
        _innerRadius = value;
        draw();
    }
    private var _innerRadius:Number;
    
    
    
    private var bitmap:Bitmap;
    private var circleMask:Sprite;
    
    
    
    public function HueCircle( radius:Number, innerRadius:Number = 0 ) {
        
        _radius = radius;
        _innerRadius = innerRadius;
        
        var diameter:Number = radius * 2;
        
        
        
        if ( hueCircleBitmapData == null )
            resizeHueCircleBitmapData( diameter );
        
        
        
        bitmap = new Bitmap( hueCircleBitmapData );
        bitmap.cacheAsBitmap = true;
        addChild( bitmap );
        
        
        
        circleMask = new Sprite();
        circleMask.cacheAsBitmap = true;
        addChild( circleMask );
        
        
        
        bitmap.mask = circleMask;
        
        draw();
    }
    
    private function draw():void {
        
        circleMask.graphics.clear();
        circleMask.graphics.beginFill( 0xffffff );
        circleMask.graphics.drawCircle( radius, radius, radius);
        if( innerRadius != 0 ) circleMask.graphics.drawCircle( radius, radius, innerRadius );
        circleMask.graphics.endFill();
        
        
        var largeRadius:Number = ( ( radius > innerRadius ) ? radius : innerRadius );
        bitmap.x = -largeRadius;
        bitmap.y = -largeRadius;
        bitmap.scaleX = largeRadius / ( hueCircleBitmapData.width / 2 );
        bitmap.scaleY = largeRadius / ( hueCircleBitmapData.width / 2 );
        
        circleMask.x = -radius;
        circleMask.y = -radius;
    }
    
    
    
    
    
    
    private static var hueCircleBitmapData:BitmapData;
    
    public static function resizeHueCircleBitmapData( width:Number ):void {
        
        var centerPoint:Point = new Point( width / 2, width / 2 );
        var tempPoint:Point = new Point();
        
        hueCircleBitmapData = new BitmapData( width, width, false );
        
        hueCircleBitmapData.lock();
        
        for ( var i:int = 0; i < width; i++ ) {
            
            for ( var j:int = 0; j < width; j++ ) {
                
                tempPoint.x = i;
                tempPoint.y = j;
                hueCircleBitmapData.setPixel( i, j, getHueCircleColor( centerPoint, tempPoint ) );
            }
        }
        
        hueCircleBitmapData.unlock();
    }
}


function getHueCircleColor( centerPoint:Point, point:Point ):uint {
    
    return HSVtoRGB( getHueCircleAngle( centerPoint, point ), 1, 1 );
}


function getHueCircleAngle( centerPoint:Point, point:Point ):uint {
    
    var pointFromCenterPoint:Point = point.subtract( centerPoint );
    var pointBearingFromCenterPoint:Number = Math.atan2( pointFromCenterPoint.y, pointFromCenterPoint.x ) * 180 / Math.PI;
    
    if ( pointBearingFromCenterPoint < 0 )
    pointBearingFromCenterPoint = pointBearingFromCenterPoint + 360;
    
    return pointBearingFromCenterPoint;
}


function HSVtoRGB( h:Number, s:Number, v:Number ):uint {
    
    var Hi:uint = ( h / 60 ) % 6;
    
    var f:Number = h / 60 - Hi;
    
    var p:Number = v * ( 1 - s );
    
    var q:Number = v * ( 1 - f * s );
    
    var t:Number = v * ( 1 - ( 1 - f ) * s );
    
    switch( Hi ) {
        
        case 0:
            return toRGB255( v, t, p );
        
        case 1:
            return toRGB255( q, v, p );
        
        case 2:
            return toRGB255( p, v, t );
        
        case 3:
            return toRGB255( p, q, v );
        
        case 4:
            return toRGB255( t, p, v );
        
        case 5:
            return toRGB255( v, p, q );
    }
    
    return 0;
}


function toRGB255( r:Number, g:Number, b:Number ):uint {
    
    return ( r * 255 << 16 ) + ( g * 255 << 8 ) + b * 255;
}