/**
* Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ks6Q
*/
package {
//import aquioux.display.colorUtil.CycleRGB;
import com.bit101.components.HSlider;
import com.bit101.components.PushButton;
import com.bit101.components.VSlider;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
[SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#000000")]
/**
* Magnet Fractal Type I (Julia) の描画
* @see http://aquioux.net/blog/?p=2226
* @author Aquioux(Yoshida, Akio)
*/
public class Main extends Sprite {
// ステージサイズ
private const WIDTH:int = 450;
private const HEIGHT:int = 450;
// スライダー関連
private const SLIDER_LONG:int = WIDTH;
private const SLIDER_SHORT:int = stage.stageWidth - WIDTH;
private var sliderValueMin:Number;
private var sliderValueMax:Number;
// 初期値
private const REAL_NUMBER:Number = 0; // c の実数部
private const IMAGINARY_NUMBER:Number = 0; // c の虚数部
// 各連携クラス
private var fractal_:Magnet1; // フラクタル計算クラス
private var engine_:Engine; // フラクタル描画エンジンクラス
private var mouseBehavior_:MouseBehavior; // マウス操作クラス
private var viewer_:Viewer; // ビューアクラス
private var buttons_:Buttons; // プリセットパラメータボタン
private var hslider_:HSlider; // 水平スライダー
private var vslider_:VSlider; // 垂直スライダー
private var textFieldReal_:TextField; // 水平スライダーの値表示
private var textFieldImag_:TextField; // 水平スライダーの値表示
// マウスダウンフラグ
private var isDown_:Boolean = false;
// コンストラクタ
public function Main() {
// フラクタルカラーマップ
var colors:Vector.<uint> = new Vector.<uint>();
var degree:int = 24;
var step:Number = 360 / (degree + 1);
for (var i:int = 0; i < degree; ++i) colors[i] = CycleRGB.getColor(i * step);
colors.reverse();
colors.fixed = true;
// フラクタル計算クラス
fractal_ = new Magnet1();
fractal_.colors = colors;
// ビューアクラス
viewer_ = new Viewer(WIDTH, HEIGHT);
addChild(viewer_);
// マウス操作クラス
mouseBehavior_ = new MouseBehavior(WIDTH, HEIGHT);
addChild(mouseBehavior_);
// フラクタル描画エンジンクラス
engine_ = new Engine();
engine_.viewer = viewer_;
engine_.controller = mouseBehavior_;
engine_.calculator = fractal_;
engine_.reset();
// プリセットパラメータボタン
buttons_ = new Buttons();
buttons_.action = buttonHandler;
addChild(buttons_);
// リセットボタン
var resetButton:PushButton = new PushButton(this, 0, buttons_.y + buttons_.height, "Reset", resetButtonHandler);
resetButton.width = 50;
resetButton.height = 20;
// スライダー
sliderValueMin = fractal_.rect.x;
sliderValueMax = fractal_.rect.width + fractal_.rect.x;
// 横スライダー(複素数 c の実数部)
hslider_ = new HSlider(this, 0, HEIGHT);
hslider_.width = SLIDER_LONG;
hslider_.height = SLIDER_SHORT;
hslider_.setSliderParams(sliderValueMin, sliderValueMax, REAL_NUMBER);
hslider_.tick = 0.001;
// 縦スライダー(複素数 c の虚数部)
vslider_ = new VSlider(this, WIDTH, 0);
vslider_.width = SLIDER_SHORT;
vslider_.height = SLIDER_LONG;
vslider_.setSliderParams(sliderValueMin, sliderValueMax, IMAGINARY_NUMBER);
vslider_.tick = 0.001;
// スライダーの値表示
var textFormat:TextFormat = new TextFormat("_typewriter", 12, 0x0);
textFieldReal_ = new TextField();
textFieldReal_.defaultTextFormat = textFormat;
textFieldReal_.autoSize = TextFieldAutoSize.LEFT;
textFieldReal_.selectable = false;
textFieldReal_.blendMode = BlendMode.INVERT;
textFieldReal_.y = HEIGHT - 15 * 2.5;
addChild(textFieldReal_);
textFieldImag_ = new TextField();
textFieldImag_.defaultTextFormat = textFormat;
textFieldImag_.autoSize = TextFieldAutoSize.LEFT;
textFieldImag_.selectable = false;
textFieldImag_.blendMode = BlendMode.INVERT;
textFieldImag_.y = HEIGHT - 15 * 1.5;
addChild(textFieldImag_);
// マウスハンドラの設定
// スライダーに直接ハンドラを設定すると ENTER_FRAME のタイミングで更新がかかり、
// 処理負荷が大きくなるため、マウスアップ時にスライダハンドラを実行させる
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
// 初回の描画
fractal_.c.real = hslider_.value;
fractal_.c.imag = vslider_.value;
draw();
textFieldReal_.text = "real : " + String(hslider_.value);
textFieldImag_.text = "imag : " + String(vslider_.value);
}
// 描画
private function draw():void {
viewer_.start();
}
// マウスハンドラ
// マウスダウン
private function mouseDownHandler(e:MouseEvent):void {
isDown_ = ((mouseX > WIDTH) || (mouseY > HEIGHT)) ? true : false;
}
// マウスアップ
private function mouseUpHandler(e:MouseEvent):void {
if (isDown_) {
hsliderHandler();
vsliderHandler();
isDown_ = false;
}
}
// ボタンハンドラ
// プリセットパラメータボタン
private function buttonHandler(values:Vector.<Number>):void {
hslider_.value = fractal_.c.real = values[0];
vslider_.value = fractal_.c.imag = values[1];
draw();
textFieldReal_.text = "real : " + String(hslider_.value);
textFieldImag_.text = "imag : " + String(vslider_.value);
}
// リセットボタン
private function resetButtonHandler(e:Event):void {
hslider_.value = fractal_.c.real = REAL_NUMBER;
vslider_.value = fractal_.c.imag = IMAGINARY_NUMBER;
engine_.reset();
textFieldReal_.text = "real : " + String(hslider_.value);
textFieldImag_.text = "imag : " + String(vslider_.value);
buttons_.reset();
}
// スライダーハンドラ
// 横スライダー
private function hsliderHandler():void {
fractal_.c.real = hslider_.value;
draw();
textFieldReal_.text = "real : " + String(hslider_.value);
buttons_.reset();
}
// 縦スライダー
private function vsliderHandler():void {
fractal_.c.imag = vslider_.value;
draw();
textFieldImag_.text = "imag : " + String(vslider_.value);
buttons_.reset();
}
}
}
//package {
//import aquioux.math.Complex;
import flash.geom.Rectangle;
/**
* Magnet Fractal Type I (Julia) 描画クラス
* @author Aquioux(Yoshida, Akio)
*/
/*public*/ class Magnet1 implements ICalculator {
/**
* 描画範囲
*/
public function get rect():Rectangle { return RECTANGLE; }
private const RECTANGLE:Rectangle = new Rectangle(MIN_X, MIN_Y, (MAX_X - MIN_X), (MAX_Y - MIN_Y));
// 個別の開始座標、終了座標
private const MIN_X:Number = -9; // X軸最小値
private const MIN_Y:Number = -9; // Y軸最小値
private const MAX_X:Number = 9; // X軸最大値
private const MAX_Y:Number = 9; // Y軸最大値
/**
* 集合に該当する部分の色(一般的には色なし=黒)
*/
public function set color(value:uint):void { _color = value; }
private var _color:uint = 0x000000;
/**
* 発散部分の色階調
*/
public function set colors(value:Vector.<uint>):void {
_colors = value;
degree_ = value.length;
}
private var _colors:Vector.<uint>;
/**
* 漸化式の c
*/
public function get c():Complex { return _c; }
private var _c:Complex = new Complex(0, 0);
// 発散チェックループ回数(_colors.length の値)
private var degree_:int;
/**
* Scan クラスからの走査データを受け、計算をおこなう
* @param x X座標値
* @param y Y座標値
* @return 計算結果
*/
public function calculate(x:Number, y:Number):uint {
var r:int = formula(x, y, _c.real, _c.imag); // julia
return (r >= 0) ? _colors[r] : _color;
}
/**
* 漸化式 z ← ((z^2 + c - 1) / (2 * z + c - 2))^2
* @param zRl 複素数 z の実数部
* @param zIm 複素数 z の虚数部
* @param cRl 複素数 c の実数部
* @param cIm 複素数 c の虚数部
* @return 発散評価値
* @private
*/
private function formula(zRl:Number, zIm:Number, cRl:Number, cIm:Number):int {
var i:int = degree_;
while (i--) {
// 発散の評価
var zRlSqr:Number = zRl * zRl;
var zImSqr:Number = zIm * zIm;
if (zRlSqr + zImSqr > 1024) break;
var zTRl:Number = zRl - 1;
if (zTRl * zTRl + zImSqr < 0.001) break;
// 漸化式の実行
// 分子
var z1Rl:Number = zRlSqr - zImSqr + cRl - 1;
var z1Im:Number = 2 * zRl * zIm + cIm;
// 分母
var z2Rl:Number = 2 * zRl + cRl - 2;
var z2Im:Number = 2 * zIm + cIm;
// 除算
var z3Norm:Number = z2Rl * z2Rl + z2Im * z2Im;
var z3Rl:Number = (z1Rl * z2Rl + z1Im * z2Im) / z3Norm;
var z3Im:Number = (z1Im * z2Rl - z1Rl * z2Im) / z3Norm;
// 2乗
zRl = z3Rl * z3Rl - z3Im * z3Im;
zIm = 2 * z3Rl * z3Im;
}
return i;
// break で脱しなかった(発散しなかった)場合、while を回りきるので -1 になる
}
}
//}
//package {
import flash.geom.Rectangle;
/**
* フラクタル計算クラスの interface
* @author YOSHIDA, Akio (Aquioux)
*/
/*public*/ interface ICalculator {
function get rect():Rectangle;
function set color(value:uint):void;
function set colors(value:Vector.<uint>):void;
function calculate(x:Number, y:Number):uint;
}
//}
//package {
import flash.events.Event;
import flash.geom.Rectangle;
/**
* フラクタル描画エンジンクラス
* @author Aquioux(Yoshida, Akio)
*/
/*public*/ class Engine {
/**
* フラクタル計算クラス
*/
public function set calculator(value:ICalculator):void { _calculator = value; }
private var _calculator:ICalculator;
/**
* マウス操作クラス
*/
public function set controller(value:MouseBehavior):void {
_controller = value;
_controller.addEventListener(MouseBehavior.MOUSE_MOVE, mouseMoving);
_controller.addEventListener(Event.CHANGE, update);
}
private var _controller:MouseBehavior;
/**
* ビューアクラス
*/
public function set viewer(value:Viewer):void {
_viewer = value;
_viewer.addEventListener(Event.CHANGE, draw);
displayWidth_ = _viewer.width;
displayHeight_ = _viewer.height;
}
private var _viewer:Viewer;
/**
* 描画計算領域を示す Rectangle
*/
public function set rect(value:Rectangle):void {
// 今後使用するので引数を保持する
_rect = value;
// 複素平面の走査開始座標を計算する
startX_ = _rect.x;
startY_ = _rect.y;
// 複素平面の中心座標を計算する
centerX_ = startX_ + _rect.width * 0.5;
centerY_ = startY_ + _rect.height * 0.5;
// 複素平面の走査加算値を計算する
stepX_ = _rect.width / (displayWidth_ - 1);
stepY_ = _rect.height / (displayHeight_ - 1);
}
private var _rect:Rectangle;
// ビューアに描画するデータ
private var data_:Vector.<uint> = new Vector.<uint>();
// 表示領域サイズ
private var displayWidth_:int; // 幅
private var displayHeight_:int; // 高
// 複素平面の走査開始座標
private var startX_:Number; // 実数座標
private var startY_:Number; // 虚数座標
// 複素平面の中心座標
private var centerX_:Number; // 実数座標
private var centerY_:Number; // 虚数座標
// 複素平面の走査加算値
private var stepX_:Number; // 実数軸
private var stepY_:Number; // 虚数軸
/**
* 描画計算領域のリセット、再描画
*/
public function reset():void {
rect = _calculator.rect; // 領域のリセット
_viewer.start(); // 再描画
}
/**
* 描画開始
* _controller からの通知、および外部からの呼び出しで起動する処理
*/
public function update(e:Event):void {
if (e) {
// MouseBehavior からの rectangle を受ける
var t:Rectangle = _controller.rect.clone();
t.x = t.x * stepX_ + _rect.x;
t.y = t.y * stepY_ + _rect.y;
t.width *= stepX_;
t.height *= stepY_;
rect = t; // 内部に保持している _rect を更新
}
// _viewer への描画開始指示
_viewer.start();
}
// _viewer の求めに応じて、指定範囲の描画 Vector を渡す
// _viewer からの通知で起動する処理
private function draw(e:Event):void {
var startX:int = _viewer.drawRect.x;
var startY:int = _viewer.drawRect.y;
var limitX:int = _viewer.drawRect.width + startX;
var limitY:int = _viewer.drawRect.height + startY;
var idx:int = 0;
data_.fixed = false;
data_.length = 0;
for (var y:int = startY; y < limitY; ++y) {
for (var x:int = startX; x < limitX; ++x) {
data_[idx++] = _calculator.calculate(x * stepX_ + startX_, y * stepY_ + startY_);
}
}
data_.fixed = true;
_viewer.draw(data_);
}
// cntl + マウスムーブ時
private function mouseMoving(e:Event):void {
_viewer.mouseMoving(_controller.rect.x, _controller.rect.y);
}
}
//}
//package {
import flash.display.BlendMode;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
/**
* 描画領域選択クラス
* @author Aquioux(Yoshida, Akio)
*/
/*public*/ class MouseBehavior extends Sprite {
/**
* カスタムイベント(cntl + マウスムーブ)
*/
public static const MOUSE_MOVE:String = "mouseMoving";
/**
* ドラッグで決定された領域を示す Rectangle
*/
public function get rect():Rectangle { return selectedRect_; }
private var selectedRect_:Rectangle;
// 選択領域描画用
private var g_:Graphics;
// 矩形描画、移動に係る変数
private var dragStartX_:Number; // ドラッグ開始X座標
private var dragStartY_:Number; // ドラッグ開始Y座標
private var dragWidth_:Number; // ドラッグ幅
private var dragHeight_:Number; // ドラッグ高
private var isCtrlDown_:Boolean = false; // cntl キーダウン
private var enableWidth_:int;
private var enableHeight_:int;
/**
* コンストラクタ
* @param target 描画エンジン
*/
public function MouseBehavior(w:int, h:int) {
enableWidth_ = w;
enableHeight_ = h;
// 初期化
g_ = this.graphics;
blendMode = BlendMode.INVERT;
// Rectangle 生成
selectedRect_ = new Rectangle();
// stage に登録されたときの処理
addEventListener(Event.ADDED_TO_STAGE, addedHandler);
}
// stage に登録されたときの処理
private function addedHandler(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, addedHandler);
// マウスイベント有効領域を指定する
var base:Shape = new Shape();
var g:Graphics = base.graphics;
g.beginFill(0x0, 0);
g.drawRect(0, 0, enableWidth_, enableHeight_);
g.endFill();
addChild(base);
// キーボードイベントハンドラ登録
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
// マウスイベントハンドラ登録
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
}
// マウスイベントハンドラ
// マウスダウン
private function mouseDownHandler(e:MouseEvent):void {
// 起点待避
dragStartX_ = mouseX;
dragStartY_ = mouseY;
// マウスイベントハンドラ登録
if (isCtrlDown_) {
// 移動
selectedRect_.width = enableWidth_;
selectedRect_.height = enableHeight_;
stage.addEventListener(MouseEvent.MOUSE_MOVE, movingRectangle);
stage.addEventListener(MouseEvent.MOUSE_UP, moveupRectangle);
} else {
// 拡大
stage.addEventListener(MouseEvent.MOUSE_MOVE, zoomingRectangle);
stage.addEventListener(MouseEvent.MOUSE_UP, zoomupRectangle);
}
}
// 移動
// マウスムーブ
private function movingRectangle(e:MouseEvent):void {
dragWidth_ = dragStartX_ - mouseX;
dragHeight_ = dragStartY_ - mouseY;
// selectedRect_ 調整
selectedRect_.x = dragWidth_;
selectedRect_.y = dragHeight_;
// イベント送出
mouseMoving();
}
// マウスアップ
private function moveupRectangle(e:MouseEvent):void {
// マウスイベントハンドラ解除
stage.removeEventListener(MouseEvent.MOUSE_MOVE, movingRectangle);
stage.removeEventListener(MouseEvent.MOUSE_UP, moveupRectangle);
// イベント送出
update();
}
// 拡大
// マウスムーブ
private function zoomingRectangle(e:MouseEvent):void {
// 選択領域のサイズ計算
dragWidth_ = mouseX - dragStartX_;
dragHeight_ = mouseY - dragStartY_;
// 選択領域を正方形にする
// 絶対値を求める
var isMinusWidth:Boolean = dragWidth_ < 0 ? true : false;
var isMinusHeight:Boolean = dragHeight_ < 0 ? true : false;
if (isMinusWidth) dragWidth_ *= -1;
if (isMinusHeight) dragHeight_ *= -1;
// 幅・高のうち大きい方を正方形の辺とする
var edge:Number = dragWidth_ > dragHeight_ ? dragWidth_ : dragHeight_;
// 元の値がマイナスだったものはマイナスにする
dragWidth_ = isMinusWidth ? -edge : edge;
dragHeight_ = isMinusHeight ? -edge : edge;
// 選択領域の表示
g_.clear();
g_.lineStyle(0, 0x0);
g_.drawRect(dragStartX_, dragStartY_, dragWidth_, dragHeight_);
}
// マウスアップ
private function zoomupRectangle(e:MouseEvent):void {
// マウスイベントハンドラ解除
stage.removeEventListener(MouseEvent.MOUSE_MOVE, zoomingRectangle);
stage.removeEventListener(MouseEvent.MOUSE_UP, zoomupRectangle);
// selectedRect_ 調整
selectedRect_.x = dragStartX_;
selectedRect_.y = dragStartY_;
selectedRect_.width = dragWidth_;
selectedRect_.height = dragHeight_
// サイズをプラスの値に調整
if (dragWidth_ < 0) {
selectedRect_.x += selectedRect_.width;
selectedRect_.width *= -1;
}
if (dragHeight_ < 0) {
selectedRect_.y += selectedRect_.height;
selectedRect_.height *= -1;
}
// 選択領域消去
g_.clear();
// イベント送出
update();
}
// マウスホイール
private function mouseWheelHandler(e:MouseEvent):void {
// マウスホイールの移動量をスケールに変換
var delta:Number = e.delta * 0.5;
delta = (delta < 0) ? -delta : 1 / delta;
// selectedRect_ を計算
var nowWidth:Number = enableWidth_ * delta;
var nowHeight:Number = enableHeight_ * delta;
selectedRect_.x = mouseX - nowWidth / 2;
selectedRect_.y = mouseY - nowHeight / 2;
selectedRect_.width = nowWidth;
selectedRect_.height = nowHeight;
// イベント送出
update();
}
// キーボードイベントハンドラ
// キーダウン
private function keyDownHandler(e:KeyboardEvent):void {
if (e.ctrlKey) isCtrlDown_ = true;
}
// キーアップ
private function keyUpHandler(e:KeyboardEvent):void {
if (isCtrlDown_) isCtrlDown_ = false;
}
// イベント送出
// マウスムーブ時
private function mouseMoving():void {
dispatchEvent(new Event(MOUSE_MOVE));
}
// マウスアップ時
private function update():void {
dispatchEvent(new Event(Event.CHANGE));
}
}
//}
//package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
* ビューア
* @author YOSHIDA, Akio (Aquioux)
*/
/*public*/ class Viewer extends Sprite {
/**
* BitmapData 描画のための Rectangle
*/
public function get drawRect():Rectangle { return _drawRect; }
private var _drawRect:Rectangle;
// キャンバスとしての BitmapData
private var bitmapData_:BitmapData;
// cntl + マウスムーブ時のガイド表示物
private var mouseMovingGuideBm_:Bitmap;
private var mouseMovingGuideBmd_:BitmapData;
private var isMouseMoving_:Boolean = false; // cntl + マウスムーブ中フラグ
// start() 時、画面を暗くする
private const FADE:ColorTransform = new ColorTransform(0.5, 0.5, 0.5);
// 1度の draw() で描画する高さ
private const DRAW_HEIGHT:int = 15;
private const ZERO_POINT:Point = new Point(0, 0);
private var point_:Point = new Point();
private var rect_:Rectangle;
/**
* コンストラクタ
* @param w 描画幅
* @param h 描画高
*/
public function Viewer(w:int, h:int) {
// キャンバス部生成
bitmapData_ = new BitmapData(w, h, false, 0x0);
addChild(new Bitmap(bitmapData_));
rect_ = bitmapData_.rect;
// cntl + マウスムーブ時のガイド表示物
mouseMovingGuideBmd_ = bitmapData_.clone();
mouseMovingGuideBm_ = new Bitmap(mouseMovingGuideBmd_);
mouseMovingGuideBm_.alpha = 0;
addChild(mouseMovingGuideBm_);
// BitmapData 描画のための Rectangle 生成
_drawRect = new Rectangle(0, 0, w, DRAW_HEIGHT);
}
/**
* cntl + マウスムーブ時の挙動
* @param posX X軸移動量
* @param posY Y軸移動量
*/
public function mouseMoving(moveX:int, moveY:int):void {
// cntl + マウスムーブ開始時の処理
if (!isMouseMoving_) {
// キャンバス bitmapData_
bitmapData_.colorTransform(rect_, FADE);
// cntl + マウスムーブ時のガイド表示物
mouseMovingGuideBmd_.copyPixels(bitmapData_, rect_, ZERO_POINT);
mouseMovingGuideBm_.alpha = 0.5;
isMouseMoving_ = true;
}
// cntl + マウスムーブ中の処理
mouseMovingGuideBm_.x = -moveX;
mouseMovingGuideBm_.y = -moveY;
}
/**
* 描画開始
*/
public function start():void {
// cntl + マウスムーブからのアップデートだったとき
if (isMouseMoving_) {
// キャンバス bitmapData_
point_.x = mouseMovingGuideBm_.x;
point_.y = mouseMovingGuideBm_.y;
bitmapData_.lock();
bitmapData_.copyPixels(mouseMovingGuideBmd_, rect_, point_);
bitmapData_.unlock();
// cntl + マウスムーブ時のガイド表示物の後処理
mouseMovingGuideBm_.alpha = 0;
mouseMovingGuideBm_.x = 0;
mouseMovingGuideBm_.y = 0;
isMouseMoving_ = false;
} else {
bitmapData_.colorTransform(rect_, FADE);
}
_drawRect.y = 0;
addEventListener(Event.ENTER_FRAME, update);
}
// イベント送出
private function update(e:Event):void {
dispatchEvent(new Event(Event.CHANGE));
}
/**
* 描画実行
*/
public function draw(data:Vector.<uint>):void {
// BitmapData の更新
bitmapData_.lock();
bitmapData_.setVector(_drawRect, data);
bitmapData_.unlock();
// 終了判定
_drawRect.y += DRAW_HEIGHT;
if (_drawRect.y >= bitmapData_.width) removeEventListener(Event.ENTER_FRAME, update);
}
}
//}
//package {
import com.bit101.components.PushButton;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.Dictionary;
/**
* プリセットパラメータボタン
* @author YOSHIDA, Akio (Aquioux)
*/
/*public*/ class Buttons extends Sprite {
/**
* ボタンアクション(外部で定義した処理)
*/
public function set action(value:Function):void { _action = value; }
private var _action:Function;
// エンジンのラベルとプロパティ値のペア
private const PAIR:Array = [
["-1 + 0i", Vector.<Number>([-1, 0])],
["-0.1 + 0i", Vector.<Number>([-0.1, 0])],
["0 + 0i", Vector.<Number>([0, 0])],
["1 + 0i", Vector.<Number>([1, 0])],
["1.2 + 0i", Vector.<Number>([1.2, 0])],
["1.6 + 0i", Vector.<Number>([1.6, 0])],
["2 + 0i", Vector.<Number>([2, 0])],
["2.5 + 0i", Vector.<Number>([2.5, 0])],
["2.9 + 0i", Vector.<Number>([2.9, 0])],
["3 + 0i", Vector.<Number>([3, 0])],
["3.1 + 0i", Vector.<Number>([3.1, 0])],
["4 + 0i", Vector.<Number>([4, 0])],
];
// ボタンの数
private const NUM_OF_BUTTON_ROW:int = 9; // 1行
private const NUM_OF_BUTTON_LASTROW:int = PAIR.length % NUM_OF_BUTTON_ROW; // 最後の行
private const NUM_OF_BUTTON_COL:int = PAIR.length / NUM_OF_BUTTON_ROW >> 0; // 列数
// 前回押したボタン
private var prevButton_:PushButton;
// _action への引数を格納する Dictionary
private var values:Dictionary;
/**
* インストラクタ
*/
public function Buttons() {
// ボタンの作成
var buttonWidth:int = 50;
var buttonHeight:int = 20;
var idx:int = 0;
var yLimit:int = (NUM_OF_BUTTON_LASTROW == 0) ? NUM_OF_BUTTON_COL : NUM_OF_BUTTON_COL + 1;
var xLimit:int = NUM_OF_BUTTON_ROW;
values = new Dictionary();
for (var y:int = 0; y < yLimit; y++) {
if ((NUM_OF_BUTTON_LASTROW != 0) && (y == NUM_OF_BUTTON_COL)) xLimit = NUM_OF_BUTTON_LASTROW;
for (var x:int = 0; x < xLimit; x++) {
var b:PushButton = new PushButton(this, buttonWidth * x, buttonHeight * y, PAIR[idx][0], handler);
b.width = buttonWidth;
b.height = buttonHeight;
values[b] = PAIR[idx][1];
idx++;
}
}
}
/**
* リセット(前回押されたボタンを有効にする)
*/
public function reset():void {
if (prevButton_) prevButton_.enabled = true;
}
// ボタンハンドラ
private function handler(e:Event):void {
// 前回押されたボタンを有効にする
reset();
// 今回押されたボタンを無効にする
var target:PushButton = PushButton(e.target);
target.enabled = false;
prevButton_ = target;
// ボタンアクション
_action(values[target]);
}
}
//}
//package aquioux.display.colorUtil {
/**
* コサインカーブで色相環的な RGB を計算
* @author Aquioux(YOSHIDA, Akio)
*/
/*public*/ class CycleRGB {
/**
* 32bit カラーのためのアルファ値(0~255)
*/
static public function get alpha():uint { return _alpha; }
static public function set alpha(value:uint):void {
_alpha = (value > 0xFF) ? 0xFF : value;
}
private static var _alpha:uint = 0xFF;
private static const PI:Number = Math.PI; // 円周率
private static const DEGREE120:Number = PI * 2 / 3; // 120度(弧度法形式)
/**
* 角度に応じた RGB を得る
* @param angle HSV のように角度(度数法)を指定
* @return 色(0xNNNNNN)
*/
public static function getColor(angle:Number):uint {
var radian:Number = angle * PI / 180;
var r:uint = (Math.cos(radian) + 1) * 0xFF >> 1;
var g:uint = (Math.cos(radian + DEGREE120) + 1) * 0xFF >> 1;
var b:uint = (Math.cos(radian - DEGREE120) + 1) * 0xFF >> 1;
return r << 16 | g << 8 | b;
}
/**
* 角度に応じた RGB を得る(32bit カラー)
* @param angle HSV のように角度(度数法)を指定
* @return 色(0xNNNNNNNN)
*/
public static function getColor32(angle:Number):uint {
return _alpha << 24 | getColor(angle);
}
}
//}
//package aquioux.math {
/**
* 複素数
* @author Aquioux(Yoshida, Akio)
*/
/*public*/ final class Complex {
// 実数部
public function get real():Number { return _rl; }
public function set real(value:Number):void { _rl = value; }
private var _rl:Number;
// 虚数部
public function get imag():Number { return _im; }
public function set imag(value:Number):void { _im = value; }
private var _im:Number;
// コンストラクタ
public function Complex(rl:Number = 0, im:Number = 0) {
_rl = rl;
_im = im;
}
// 複製
public function clone():Complex {
return new Complex(_rl, _im);
}
public function toString():String {
return _rl + " + " + _im + "i";
}
}
//}