classes

ColorCircle.as

Stiahnuť ColorCircle.as

package sk.yoz.graphics
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    
    import sk.yoz.events.ColorCircleEvent;
    
    public class ColorCircle extends Sprite
    {
        protected var _radius:Number = 0;
        protected var _color:uint = 0;
        protected var bitmap:Bitmap = new Bitmap();
        
        protected var currentColor:Sprite;
        protected var currentColorInnerRadius:Number;
        protected var currentColorOuterRadius:Number;
        
        public function ColorCircle(radius:Number, color:uint=0):void
        {
            super();
            
            _radius = radius;
            this.color = color;
            
            bitmap.bitmapData = new BitmapData(radius * 2, radius * 2, true, 0);
            addChild(bitmap);
            
            var mask:Shape = new Shape();
            mask.graphics.beginFill(0, 1);
            mask.graphics.drawCircle(radius, radius, radius);
            addChild(mask);
            this.mask = mask;
            
            addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
            addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            addEventListener(MouseEvent.ROLL_OUT, onRollOut);
        }
        
        public function get radius():Number
        {
            return _radius;
        }
        
        public function set color(value:uint):void
        {
            _color = value;
            updateCurrentColor(value);
        }
        
        public function get color():uint
        {
            return _color;
        }
        
        protected function updateCurrentColor(color:uint):void
        {
            if(!currentColor)
                return;
            drawCurrentColor(
                currentColorOuterRadius, currentColorInnerRadius, color);
        }
        
        protected function onMouseMove(event:MouseEvent):void
        {
            event.updateAfterEvent();
            var color:uint = event.target == currentColor 
                ? this.color : bitmap.bitmapData.getPixel(mouseX, mouseY);
            updateCurrentColor(color);
            
            var type:String = ColorCircleEvent.COLOR_OVER;
            dispatchEvent(new ColorCircleEvent(type, false, false, color));
        }
        
        protected function onMouseDown(event:MouseEvent):void
        {
            var color:uint = event.target == currentColor 
                ? this.color : bitmap.bitmapData.getPixel(mouseX, mouseY);
            this.color = color;
            
            var type:String = ColorCircleEvent.COLOR_SELECTED;
            dispatchEvent(new ColorCircleEvent(type, false, false, color));
        }
        
        protected function onRollOut(event:MouseEvent):void
        {
            updateCurrentColor(color);
        }
        
        protected function drawDonut(innerRadius:Number, outerRadius:Number, 
            bitmapData:BitmapData):void
        {
            var donut:Shape = new Shape();
            donut.graphics.lineStyle(outerRadius - innerRadius, 0, 1);
            donut.graphics.drawCircle(outerRadius, outerRadius, 
                (outerRadius + innerRadius) / 2);
            donut.cacheAsBitmap = true;
            bitmapData.draw(donut, null, null, BlendMode.ALPHA);
            
            var matrix:Matrix = new Matrix();
            matrix.translate(radius - outerRadius, radius - outerRadius);
            
            bitmap.bitmapData.draw(bitmapData, matrix);
        }
        
        public function drawRGBPalette(outerRadius:Number, innerRadius:Number):void
        {
            var color:uint, distance:Number, dx:Number, dy:Number;
            var r2:Number = outerRadius * 2;
            var radiusDif2:Number = (outerRadius - innerRadius) / 2;
            var middleRadius:Number = innerRadius + radiusDif2;
            var bitmapData:BitmapData = new BitmapData(r2, r2, true, 0);
            var light:Number, dark:Number;
            bitmapData.lock();
            for(var x:uint = 0; x < r2; x++)
            for(var y:uint = 0; y < r2; y++)
            {
                dx = outerRadius - x;
                dy = outerRadius - y;
                distance = Math.sqrt(dx * dx + dy * dy);
                if(distance > outerRadius + 2 || distance < innerRadius - 2)
                    continue;
                
                light = dark = 0;
                if(distance > middleRadius)
                    light = (distance - middleRadius) / radiusDif2;
                else
                    dark = (middleRadius - distance) / radiusDif2;
                light = light > 1 ? 1 : light;
                dark = dark > 1 ? 1 : dark;
                color = paletteColor(Math.atan2(dy, dx) / Math.PI / 2 + .5,
                    light, dark * dark * dark * dark);
                
                bitmapData.setPixel32(x, y, color + 0xff000000);
            }
            
            bitmapData.unlock();
            drawDonut(innerRadius, outerRadius, bitmapData);
            bitmapData.dispose();
        }
        
        public function drawBWPalette(outerRadius:Number, innerRadius:Number):void
        {
            var color:uint, amount:Number, distance:Number, dx:Number, dy:Number;
            var r2:Number = outerRadius * 2;
            var bitmapData:BitmapData = new BitmapData(r2, r2, true, 0);
            bitmapData.lock();
            for(var x:uint = 0; x < r2; x++)
            for(var y:uint = 0; y < r2; y++)
            {
                dx = outerRadius - x;
                dy = outerRadius - y;
                distance = Math.sqrt(dx * dx + dy * dy);
                if(distance > outerRadius + 2 || distance < innerRadius - 2)
                    continue;
                
                amount = (Math.atan2(dy, dx) / Math.PI / 2 + .5) * 0xff;
                color = amount << 16 | amount << 8 | amount;
                
                bitmapData.setPixel32(x, y, color + 0xff000000);
            }
            bitmapData.unlock();
            drawDonut(innerRadius, outerRadius, bitmapData);
            bitmapData.dispose();
        }
        
        public function drawSolid(outerRadius:Number, innerRadius:Number, 
            color:uint):void
        {
            var r2:Number = outerRadius * 2;
            var bitmapData:BitmapData = new BitmapData(r2, r2, true, 0);
            var shape:Shape = new Shape();
            shape.graphics.beginFill(color, 1);
            shape.graphics.drawCircle(outerRadius, outerRadius, outerRadius);
            shape.graphics.endFill();
            
            bitmapData.draw(shape);
            drawDonut(innerRadius, outerRadius, bitmapData);
            bitmapData.dispose();
        }
        
        public function drawCurrentColor(outerRadius:Number, innerRadius:Number,
            color:int = -1):void
        {
            if(!outerRadius)
                return;
            currentColorOuterRadius = outerRadius;
            currentColorInnerRadius = innerRadius;
            
            if(!currentColor)
            {
                currentColor = new Sprite();
                addChild(currentColor);
            }
            
            color = color == -1 ? this.color : color;
            var radius:Number = (outerRadius + innerRadius) / 2;
            
            currentColor.graphics.clear();
            currentColor.graphics.lineStyle(outerRadius - innerRadius, color, 1);
            currentColor.graphics.drawCircle(this.radius, this.radius, radius);
            currentColor.graphics.endFill();
        }
        
        public static function paletteColor(position:Number, light:Number=0, 
            dark:Number=0):uint
        {
            var r:Number = Math.abs(.5 - position) * 6 - 1;
            r = r > 1 ? 1 : r < 0 ? 0 : r;
            r = (r + (1 - r) * light) * (1 - dark);
            
            var g:Number = (1 - Math.abs(1/3 - position)) * 6 - 4;
            g = g > 1 ? 1 : g < 0 ? 0 : g;
            g = (g + (1 - g) * light) * (1 - dark);
            
            var b:Number = (1 - Math.abs(2/3 - position)) * 6 - 4;
            b = b > 1 ? 1 : b < 0 ? 0 : b;
            b = (b + (1 - b) * light) * (1 - dark);
            
            return (r * 0xff) << 16 | (g * 0xff) << 8 | (b * 0xff);
        }
    }
}