CFA-AS4
前回よりも色々と進化。引数が増えたり動きが増えたり。Tweener様様です。
画面クリックで再描画可能.
package {
import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;
import caurina.transitions.properties.FilterShortcuts;
import flash.display.*;
import flash.display.DisplayObjectContainer;
import flash.display.SimpleButton;
import flash.display.Stage;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
public class Main extends Sprite{
public function Main(){
//ココにCFAの記述方法で書きこむ。最初の描画分。
var cfdg :String =<><![CDATA[
startshape ellipse
background {hue -120 sat 1 b -0.4}
timer{d 0}
rule ellipse 5 {
CIRCLE {act 3}
CIRCLE {s 0.93 0.99 r -10 b 2 act 5}
ellipse {s 0.90 0.97 r -10 }
}
]]></>;
FilterShortcuts.init();
ColorShortcuts.init();
start( cfdg );
}
private function start( cfdg :String ) :void {//ASイベントリスナー、CFAを書き始める
var art :ContextFreeArt = new ContextFreeArt( cfdg,465,465 );
var txt:TextField = createTextField(cfdg, 10, 0);
addChildAt(art,0); // ContextFreeArt描画フィールドの描画
addChild(txt); // テキストフィールドの描画
var btn:CustomSimpleButton= new CustomSimpleButton();
var count:Number = 0;
addChild(btn);
btn.addEventListener(MouseEvent.CLICK, function (e:MouseEvent):void{
if (count == 0) {
count = 1;
Tweener.addTween(txt,{ x:0,y:-465,time :2,transition:"easeOutQuad"});
} else if (count == 1) {
count = 0;
Tweener.addTween(txt,{ x:0,y:0,time :2,transition:"easeOutQuad"});
}
});
stage.addEventListener(MouseEvent.CLICK,CLICK);
function CLICK(e:MouseEvent):void {
removeChild(art);
art = new ContextFreeArt(txt.text,465,465 );
addChildAt(art,0);
}
}
private function createTextField(text:String, size:int, color:int):TextField
{//書き込みスペースの設定
var txt:TextField = new TextField();
txt.defaultTextFormat = new TextFormat("_typeWriter", size, color, true);
txt.type = TextFieldType.INPUT;
txt.text = text;
txt.x = 0;
txt.height = 465;
txt.width =150;
txt.autoSize =TextFieldAutoSize.NONE;
txt.multiline = true;
txt.wordWrap = true;
txt.border = true;
txt.borderColor = 0xED1A3D;
txt.background = true;
txt.backgroundColor = 0xA6E1ED;
return txt;
}
}
}
function log(...args) :void {}
import flash.display.Sprite;
/*
CFA-ASのレンダリング
*/
class ContextFreeArt extends Sprite {
private var renderer :Renderer;
public function ContextFreeArt( cfdg_text :String, width :Number = 640, height :Number = 480 ) {
var t :Tokenizer = new Tokenizer;
var tokens :Array = t.tokenize( cfdg_text );
var c :Compiler = new Compiler;
var compiled :Object = c.compile( tokens );
logger("compiled: ",compiled);
renderer = new Renderer( width, height );
renderer.clearQueue();
renderer.render( compiled, this );
}
public function tick() :void {
renderer.tick();
}
private function logger(... args) :void {
if ( 1 ) {
return;
}
log.apply(null, (new Array("[ContextFreeArt]", this)).concat(args));
}
}
import flash.utils.getDefinitionByName;
/*
CFAとしてのコンパイラ
startshape,rule,backgroundを作る
*/
class Compiler{
private const keywords :Array = [ "startshape", "rule", "background" ];
public var compiled :Object = {};
public var state :IState;
private var curKey :String;
private var curValues :Array;
private var obj :Object;
public function Compiler(){
}
public function compile( tokens :Array ) :Object {
state = new General;
while ( tokens.length > 0 ) {
var token :String = tokens.shift();
var nextState :Array = state.eat( token, this );
if ( nextState ) {
next( nextState );
}
}
return compiled;
}
private function next( state_and_args :Array ) :void {
var className :String = state_and_args.shift();
className = className.substr(0,1).toUpperCase() + className.substr(1);
switch( className ) {
case "Startshape":
state = new Startshape;
break;
case "General":
state = new General;
break;
case "Background":
state = new Background;
break;
case "Rule":
state = new Rule;
break;
case "RuleWeight":
state = new RuleWeight( state_and_args );
break;
case "RuleDraw":
state = new RuleDraw( state_and_args );
break;
case "ShapeAdjustment":
state = new ShapeAdjustment( state_and_args );
break;
case "Timer":
state = new Timerchenge;
break;
default:
throw('クラス名が不明です: '+className);
}
}
private function logger(... args) :void {
if ( 1 ) {
return;
}
log.apply(null, (new Array("[compiler]", this)).concat(args));
}
}
/*
CFAとしてのトークンの処理
{}とか
*/
class Tokenizer{
private var input :String;
private const stopChars :Array = [" ", "{", "}", "\n", "\r", "\t"];//改行、タブ、{}の処理
public function Tokenizer() {
}
// TODO: String comments
// TODO: Handle ordered arguments (i.e., square brakets)
// TODO: Handle the | operator
public function tokenize( _input :String ) :Array {
input = _input;
input = input.replace( /([{}])/g, " $1");
var tokens :Array = new Array;
var head :Object = { lastPos: 0 };
while( 1 ) {
head = tokenizeNext( head.lastPos );
if ( head == null ) { break; }
if ( head.token ) {
tokens.push( head.token );
}
}
logger("[tokenize]tokens: ",tokens);
return tokens;
}
private function tokenizeNext( pos :Number ) :Object {
var stops :Array = new Array;
var len :int = stopChars.length;
for ( var i:int=0; i<len; i++ ) {
var stopChar :String = stopChars[ i ];
var foundPos :int = input.indexOf( stopChar, pos );
if ( foundPos != -1 ) {
stops.push( foundPos + 1 );
}
}
if ( stops.length == 0 ) { return null; }
var stopPos :Number = Math.min.apply( null, stops );
var token :String = input.substr(pos, stopPos-pos);
token = token.replace( /[ \n\r\t]/, "" );
return { token: token, lastPos: stopPos }
}
private function logger(... args) :void {
if ( 1 ) {
return;
}
log.apply(null, (new Array("[Tokenizer]", this)).concat(args));
}
}
import flash.display.DisplayObjectContainer;
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Graphics;
import flash.events.TimerEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Timer;
import flash.geom.Transform;
import flash.events.MouseEvent;
import caurina.transitions.Tweener
/*
レンダリング(背景や中央配置)
*/
class Renderer extends Sprite{
private var widths :Number = 640;
private var heights :Number = 480;
private var globalScale :Number = 300;
private var centeringScale :Number = 1;
private var centeringMatrix :Matrix = new Matrix;
private var queue :Array;
private var compiled :Object;
private var container :Sprite;
private var background :Sprite;
private var sprite :Sprite;
private var isRendering :Boolean = false;
private var maxThreads :int = 1000;
private var tickTimer :Timer;
private var globalMatrix :Matrix;
public function Renderer( _width :Number = 0, _height :Number = 0 ){
if ( _width ) { widths = _width; }
if ( _height ) { heights = _height; }
logger("w: "+widths+" h: "+heights);
}
public function render( _compiled :Object, _container :DisplayObjectContainer ) :void {
var render_time:Number = 500;
compiled = _compiled;
background = new Sprite;
_container.addChild( background );
sprite = new Sprite;
_container.addChild( sprite );
if ( ! queue ) { queue = new Array; }
globalMatrix = new Matrix;
drawBackground();
timetempo()
draw();
//描画時間変更
tickTimer = new Timer( render_time );
tickTimer.addEventListener( TimerEvent.TIMER, tick );
tickTimer.start();
function timetempo() :void {//背景の設定
if ( compiled.timerchenge ) {
var timeAdj :Adjustment = compiled.timerchenge;
var timerTime :Time = new Time;
timerTime.d = timeAdj.d; // { d:0 };
render_time = render_time * timerTime.d;
}
}
}
public function tick( e :TimerEvent = null ) :void {
if ( queue.length > 0 ) {
isRendering = true;
var concurrent :int = Math.min( queue.length - 1, maxThreads );
for ( var i :int=0; i <= concurrent; i++ ) {
var args :Array = queue.shift();
drawRule.apply( null, args );
}
center();
}
}
private function center() :void {
var rect :Rectangle = sprite.getRect( cfa_sp );
// 描画画像のリサイズ
centeringScale = Math.min( widths / rect.width, heights / rect.height ) *0.8;
centeringMatrix.a = centeringMatrix.d = centeringScale;
// センタリング
centeringMatrix.tx = widths/2 - (rect.left + rect.right ) / 2 * centeringScale;
centeringMatrix.ty = heights*2/5 - (rect.top + rect.bottom) / 2 * centeringScale;
sprite.transform.matrix = centeringMatrix;
}
private function draw() :void {
var ruleName :String = compiled.startshape;
var foregroundColor :Color = new Color;
drawRule( ruleName, new Matrix, foregroundColor );
}
/*
レンダリング停止条件
*/
private function drawRule( ruleName :String, mtx :Matrix, color :Color, priority :Number = 0 ) :void {
if( Math.abs( mtx.a ) * globalScale * centeringScale < 1.0 && Math.abs( mtx.b ) * globalScale * centeringScale < 1.0 ){
return;
}
var shape :Object = chooseShape( ruleName );
drawShape( shape, mtx, color, priority );
}
private function chooseShape( ruleName :String ) :Object {
var choices :Array = compiled[ ruleName ];
if ( ! choices ) { throw("ruleが見つかりません: "+ruleName); }
var sum :Number = 0;
for( var i :int=0; i<choices.length; i++) {
sum += choices[i].weight;
}
var shape :Object;
var r :Number = Math.random() * sum;
sum = 0;
for( i=0; i <= choices.length-1; i++) {
sum += choices[i].weight;
if( r <= sum ){
shape = choices[i];
break;
}
}
if ( ! shape ) { throw("図形名が間違っており、rule: "+ruleName+" が無効です"); }
return shape;
}
//////////////////
private var cfa_sp:Sprite = new Sprite();
/////////////////
private function drawShape( shape :Object, mtx :Matrix, color :Color, priority :Number = 0 ) :void {
var len :int = shape.draw.length;
for ( var i :int = 0; i < len; i++ ) {
var adj :Adjustment = shape.draw[ i ];
cfa_sp = new Sprite();
sprite.addChild(cfa_sp);
var localTransform :Matrix = mtx.clone();
localTransform = adjustTransform( adj, localTransform , cfa_sp );
var localColor :Color = adjustColor( adj, color );
var localMatrix :Matrix = globalMatrix.clone();
globalMatrix.concat( localTransform );
switch( adj.name ){
case "CIRCLE":
drawCIRCLE( globalMatrix, localColor ,cfa_sp);
break;
case "SQUARE":
drawSQUARE( localTransform, localColor , cfa_sp);
break;
case "TRIANGLE":
drawTRIANGLE( localTransform, localColor , cfa_sp);
break;
case "SEQ":
drawSEQ( localTransform, localColor , cfa_sp);
break;
default:
var args :Array = [ adj.name, localTransform, localColor ];
if( priority == 1 ){ queue.unshift( args ); }
else{ queue.push( args ); }
break;
}
globalMatrix = localMatrix;
}
}
private const halfScale :Number = globalScale * 0.5;
private const _P:Number = 0.7071067811865476; //Math.cos( Math.PI / 4 )
private const _T:Number = 0.41421356237309503; //Math.tan( Math.PI / 8 )
private function drawCIRCLE( mx :Matrix, color :Color, s:Sprite ) :void {//円の設定
//var g :Graphics = container.graphics;
var g :Graphics = cfa_sp.graphics;
g.beginFill.apply( null, colorToRgba(color) );
moveTo( g, mx, + halfScale, 0 );
curveTo( g, mx, + halfScale , + halfScale * _T, + halfScale * _P, + halfScale * _P );
curveTo( g, mx, + halfScale * _T, + halfScale , 0 , + halfScale );
curveTo( g, mx, - halfScale * _T, + halfScale , - halfScale * _P, + halfScale * _P );
curveTo( g, mx, - halfScale , + halfScale * _T, - halfScale , 0 );
curveTo( g, mx, - halfScale , - halfScale * _T, - halfScale * _P, - halfScale * _P );
curveTo( g, mx, - halfScale * _T, - halfScale , 0 , - halfScale );
curveTo( g, mx, + halfScale * _T, - halfScale , + halfScale * _P, - halfScale * _P );
curveTo( g, mx, + halfScale , - halfScale * _T, + halfScale , 0 );
g.endFill();
}
private function drawSQUARE( mx :Matrix, color :Color , s:Sprite) :void {//正方形の設定
//var g :Graphics = container.graphics;
var g :Graphics = cfa_sp.graphics;
g.beginFill.apply( null, colorToRgba(color) );
moveTo( g, mx, - halfScale, - halfScale );
lineTo( g, mx, + halfScale, - halfScale );
lineTo( g, mx, + halfScale, + halfScale );
lineTo( g, mx, - halfScale, + halfScale );
lineTo( g, mx, - halfScale, - halfScale );
g.endFill();
}
private const triangley :Number = Math.sqrt(3) * globalScale / 6;
private function drawTRIANGLE( mx :Matrix, color :Color , s:Sprite) :void {//三角形の描画
//var g :Graphics = container.graphics;
var g :Graphics = cfa_sp.graphics;
g.beginFill.apply( null, colorToRgba(color) );
moveTo( g, mx, - halfScale, triangley );
lineTo( g, mx, + halfScale, triangley );
lineTo( g, mx, 0, -triangley * 2 );
lineTo( g, mx, - halfScale, triangley );
g.endFill();
}
//どんな形にするか試行錯誤中
private function drawSEQ( mx :Matrix, color :Color , s:Sprite) :void {//円の設定
//var g :Graphics = container.graphics;
var g :Graphics = cfa_sp.graphics;
g.beginFill.apply( null, colorToRgba(color) );
moveTo( g, mx, - halfScale, triangley );
lineTo( g, mx, + halfScale, triangley );
lineTo( g, mx, 0, -triangley * 2 );
lineTo( g, mx, - halfScale, triangley );
moveTo( g, mx, + halfScale, -triangley );
lineTo( g, mx, - halfScale, -triangley );
lineTo( g, mx, 0, triangley * 2 );
lineTo( g, mx, + halfScale, -triangley );
g.endFill();
}
//描画位置で書くためのmoveTo,lineTo,curveToの定義
private function moveTo( g :Graphics, mx :Matrix, x :Number, y :Number ) :void {
g.moveTo( x * mx.a + y * mx.c + mx.tx,
x * mx.b + y * mx.d + mx.ty );
}
private function lineTo( g :Graphics, mx :Matrix, x :Number, y :Number ) :void {
g.lineTo( x * mx.a + y * mx.c + mx.tx,
x * mx.b + y * mx.d + mx.ty );
}
private function curveTo( g :Graphics, mx :Matrix, cx:Number, cy:Number, x:Number, y:Number ):void{
g.curveTo( cx * mx.a + cy * mx.c + mx.tx,
cx * mx.b + cy * mx.d + mx.ty,
x * mx.a + y * mx.c + mx.tx,
x * mx.b + y * mx.d + mx.ty );
}
private function drawBackground() :void {//背景の設定
if ( compiled.background ) {
var colorAdj :Adjustment = compiled.background;
var backgroundColor :Color = new Color;
backgroundColor.b = 1; // { h:0, s:0, b:1, a:1 };
var color :Color = adjustColor( colorAdj, backgroundColor );
var color_alpha :Array = colorToRgba( color );
logger("[drawBackground]color: ",color, backgroundColor,color_alpha);
var bg :Shape = new Shape;
bg.graphics.beginFill( color_alpha[0], color_alpha[1] );
bg.graphics.drawRect( 0, 0, widths, heights );
background.addChild( bg );
}
}
// order: rotate scale,flip,skew,k
private function adjustTransform( adjs :Adjustment, base :Matrix ,art:Sprite) :Matrix {
var mtx :Matrix = new Matrix;
//flip
if ( adjs.flipDefined ){
var flip :Number = adjs.flip;
var vX :Number = Math.cos( -2*Math.PI * flip / 360);
var vY :Number = Math.sin( -2*Math.PI * flip / 360);
var norm :Number = 1/(vX*vX + vY*vY);
//var flip :Matrix = new Matrix((vX*vX-vY*vY)/norm, 2*vX*vY/norm, 2*vX*vY/norm, (vY*vY-vX*vX)/norm, 0, 0);
mtx.a = (vX*vX-vY*vY)/norm;
mtx.b = 2*vX*vY/norm;
mtx.c = 2*vX*vY/norm;
mtx.d = (vY*vY-vX*vX)/norm;
}
//skew
if ( adjs.skewDefined ){
var skewX :Number = adjs.skewX;
var skewY :Number = adjs.skewY;
mtx.b = skewY * Math.PI/180;
mtx.c = skewX * Math.PI/180;
}
// Scaling
var sizeX :Number = adjs.sizeX;
var sizeY :Number = adjs.sizeY;
if ( sizeX || sizeY ) {
mtx.scale( sizeX, sizeY );
}
// Rotation
var r :Number = adjs.rotate;
if ( r != 0 ) {
mtx.rotate( - Math.PI * r / 180 );
}
// Tranalsation
var x :Number = adjs.x;
var y :Number = -adjs.y;
var point :Point = new Point( x * globalScale, y * globalScale );
if ( x != 0 || y != 0 ) {
mtx.translate( point.x, point.y );
}
//Tweener動作コマンド
// act 前後に動かす
var act :Number = adjs.act;
//mv
var mvx :Number = adjs.mvx;
var mvy :Number = -adjs.mvy;
var MV: Point = new Point(mvx*globalScale,mvy*globalScale);
// ch 色の変化
// ca 透明度の変化
var ch :Number = adjs.ch;
var ca :Number = adjs.ca;
// l 影を付ける
var sdw :Number = adjs.sdw;
//remove Tween
var stp :Number = adjs.stp;
var d :Number = adjs.d;
if ( ch != 0 || ca != 0){
Tweener.addTween(art,{ x:0, y:0, scaleX:1,scaleY:1,_hue: ch ,_color_alphaMultiplier: ca ,time :20 ,delay:d, transition:"liner"}); //色相・透明度変化
}
if ( sdw != 0 ){
Tweener.addTween(art,{ x:0, y:0, scaleX:1,scaleY:1,_DropShadow_angle:sdw, _DropShadow_distance: 10 , _DropShadow_blurX: 10, _DropShadow_blurY:10, _DropShadow_alpha: 0.5,time :5 , transition:"liner"});
}
if ( mvx!=0 || mvy!=0 ){
Tweener.addTween(art,{ x:MV.x , y:MV.y ,scaleX:1,scaleY:1,time : 5 ,delay:d,transition:"liner"});
}
if (act !=0){
Tweener.addTween(art,{ x:MV.x , y:MV.y , scaleX:1, scaleY:1 ,time : act ,delay:d, transition:"easeOutElastic",onComplete:action1,onCompleteParams:[art]});
}
if (stp != 0){//クリックで停止
art.addEventListener(MouseEvent.CLICK,Stopmotion);
art.buttonMode = true;
}
if (adjs.spnDefined){//回転
var spn1 :Number = adjs.spnDeg;
var spn2 :Number = adjs.spnTime;
Tweener.addTween(art,{ rotation:0,time: spn2 ,delay:d,transition:"liner",onComplete:Rotate1,onCompleteParams:[art]});
}
function action1(art:Sprite):void{
Tweener.addTween(art,{ x:base.tx , y:base.ty , scaleX:0, scaleY:0 ,time :act , transition:"easeOutElastic",onComplete:action2,onCompleteParams:[art]})
}
function action2(art:Sprite):void{
Tweener.addTween(art,{ x:MV.x , y:MV.y, scaleX:1, scaleY:1 ,time :act , transition:"easeOutElastic",onComplete:action1,onCompleteParams:[art]})
}
function Rotate1(art:Sprite):void{//Tweener停止
Tweener.addTween(art,{rotation:-spn1,time: spn2 ,transition:"liner",onComplete:Rotate2,onCompleteParams:[art]});
}
function Rotate2(art:Sprite):void{//Tweener停止
Tweener.addTween(art,{rotation:0,time: spn2 ,transition:"liner",onComplete:Rotate1,onCompleteParams:[art]});
}
function Stopmotion(evt:MouseEvent):void{//Tweener停止
Tweener.removeTweens(evt.target);
}
mtx.concat( base );
return mtx;
}
private function colorToRgba( color :Color ) :Array {
return hsl2rgb( color.h, color.s, color.b, color.a );
}
// hue, saturation, brightness, alpha
// hue:色彩 [0,360] default 0
// saturation:明度 [0,1] default 0
// brightness:濃度 [0,1] default 1
// alpha:透明度 [0,1] default 1
private function hsl2rgb(h :Number, s :Number, l :Number, a :Number) :Array {
if (h == 360){ h = 0;}
//
// based on C code from http://astronomy.swin.edu.au/~pbourke/colour/hsl/
//
while (h < 0){ h += 360; }
while (h > 360){ h -= 360; }
var r :Number, g :Number, b :Number;
if (h < 120){
r = (120 - h) / 60;
g = h / 60;
b = 0;
}else if (h < 240){
r = 0;
g = (240 - h) / 60;
b = (h - 120) / 60;
}else{
r = (h - 240) / 60;
g = 0;
b = (360 - h) / 60;
}
r = Math.min(r, 1);
g = Math.min(g, 1);
b = Math.min(b, 1);
r = 2 * s * r + (1 - s);
g = 2 * s * g + (1 - s);
b = 2 * s * b + (1 - s);
if (l < 0.5){
r = l * r;
g = l * g;
b = l * b;
}else{
r = (1 - l) * r + 2 * l - 1;
g = (1 - l) * g + 2 * l - 1;
b = (1 - l) * b + 2 * l - 1;
}
r = Math.ceil(r * 255);
g = Math.ceil(g * 255);
b = Math.ceil(b * 255);
return [ (r * 256*256 + g * 256 + b), a ];
}
/*
色彩設定RGB→HSVA
*/
private function adjustColor( adjs :Adjustment, color :Color ) :Color {
// See http://www.contextfreeart.org/mediawiki/index.php/Shape_adjustments
var newColor :Color = new Color;
newColor.h = color.h;
newColor.s = color.s;
newColor.b = color.b;
newColor.a = color.a;
// Add num to the drawing hue value, modulo 360
newColor.h += adjs.hue;
newColor.h %= 360;
// If adj<0 then change the drawing [blah] adj% toward 0.
// If adj>0 then change the drawing [blah] adj% toward 1.
if ( adjs.saturation != 0 ) {
if( adjs.saturation > 0 ){
newColor.s += adjs.saturation * (1-color.s);
} else {
newColor.s += adjs.saturation * color.s;
}
}
if ( adjs.brightness != 0 ) {
if( adjs.brightness > 0 ){
newColor.b += adjs.brightness * (1/2-color.b);
} else {
newColor.b += adjs.brightness * color.b;
}
}
if ( adjs.alpha != 0 ) {
if( adjs.alpha > 0 ){
newColor.a += adjs.alpha * (-1-color.a);
} else {
newColor.a += adjs.alpha * color.a;
}
}
return newColor;
}
public function clearQueue() :void {
queue = new Array;
}
private function logger(... args) :void {
if ( 1 ) {
return;
}
log.apply(null, (new Array("[Renderer]", this)).concat(args));
}
}
class Color {
public var h :Number = 0;
public var s :Number = 0;
public var b :Number = 0;
public var a :Number = 1;
public function Color(){
}
}
class Time {
public var d :Number = 1;
public function Time(){
}
}
/*
ルール指定
*/
class Adjustment{
public var name :String;
public var flipDefined :Boolean = false;
public var flip :Number;
public var sizeX :Number = 1;
public var sizeY :Number = 1;
public var rotate :Number = 0;
public var x :Number = 0;
public var y :Number = 0;
public var hue :Number = 0;
public var saturation :Number = 0;
public var brightness :Number = 0;
public var alpha :Number = 0;
public var skewDefined :Boolean = false;
public var skewX :Number = 0;
public var skewY :Number = 0;
public var act:Number = 0;
public var sdw:Number =0;
public var ch :Number = 0;
public var ca :Number = 1;
public var mvx :Number = 0;
public var mvy :Number = 0;
public var stp :Number = 10;
public var spnDefined :Boolean = false;
public var spnDeg:Number = 0;
public var spnTime:Number =0;
public var d :Number = 0;
public function fill( obj :Object ) :void {
for( var key :String in obj ){
switch( key ) {
case "f":
case "flip":
flipDefined = true;
flip = obj[key];
break;
case "s":
case "size":
var size :* = obj[key];
if ( typeof(size) == "number" ) { size = [size,size]; }
sizeX = size[0];
sizeY = size[1];
break;
case "r":
rotate = obj[key];
break;
case "h":
hue = obj[key];
break;
case "sat":
saturation = obj[key];
break;
case "b":
brightness = obj[key];
break;
case "a"://透明度
alpha = obj[key];
break;
case "skew"://skew=歪める
skewDefined =true;
var skew :* = obj[key];
if ( typeof(skew) == "number" ) { skew = [skew,skew]; }
skewX = skew[0];
skewY = skew[1];
break;
case "act"://消えては出るTween
act = obj[key];
break;
case "sdw"://影を付けるTween
sdw = obj[key];
break;
case "ch"://hue値を変化させるTween
ch = obj[key];
break;
case "ca"://alpha値を変化させるTween
ca = obj[key];
break;
case "mvx"://x方向に動かすTween
mvx = obj[key];
break;
case "mvy"://y方向に動かすTween
mvy = obj[key];
break;
case "stp"://RemoveするTween
stp = obj[key];
break;
case "spn"://回転するTween
spnDefined =true;
var spn :* = obj[key];
if ( typeof(spn) == "number" ) { spn = [spn,spn]; }
spnDeg = spn[0];
spnTime = spn[1];
break;
case "d"://timetempo用
d= obj[key];
break;
case "rotate":
case "x":
case "y":
case "hue":
case "saturation":
case "brightness":
case "alpha":
this[key] = obj[key];
break;
default:
throw("引数が正しくありません: "+key);
}
}
}
}
//}
/*
ルール設定部分
(startshapeやbgなど)
(IStateに依存)
*/
class Rule implements IState {
public function Rule(){
}
public function eat( token :String, compiler :Compiler ) :Array {
var ruleName :String = token;
if ( ! compiler.compiled[ ruleName ] ) {
compiler.compiled[ ruleName ] = [];
}
return [ "ruleWeight", ruleName ];
}
}
class RuleDraw implements IState {
private var weight :Number = 1;
private var ruleName :String;
public function RuleDraw( args :Array ) {
ruleName = args[0];
}
public function eat( token :String, compiler :Compiler ) :Array {
if( token == "}" ){
return [ "general" ];
}
return [ "shapeAdjustment", token, ruleName ];
}
}
class Startshape implements IState {
public function Startshape() {
}
public function eat( token :String, compiler :Compiler ) :Array {
compiler.compiled[ "startshape" ] = token;
return [ "general" ];
}
}
class AbstractArgument implements IState {
protected var curKey :String = null;
protected var curValues :Array = [];
protected var obj :Object = {};
protected var compiler :Compiler;
public function AbstractArgument(){
}
public function eat( token :String, _compiler :Compiler ) :Array {
compiler = _compiler;
switch ( token ) {
case "}":
flushKey();
return onDone( obj );
case "{":
return null;
}
// If it's a keyword name...
if( token.match(/[a-z_]+/i) ) {
flushKey();
curKey = token;
curValues = [];
}
// Otherwise it's a value (and hence a number)
else {
curValues.push( parseFloat(token) );
}
return null;
}
protected function onDone( obj :Object ) :Array { return null; } // abstract
protected function flushKey() :void {
if ( curKey ) {
if ( curValues.length == 1 ) {
obj[ curKey ] = curValues[0];
}
else {
obj[ curKey ] = curValues;
}
}
}
}
class Background extends AbstractArgument {
public function Background() {
}
override protected function onDone( obj :Object ) :Array {
var adj :Adjustment = new Adjustment;
adj.fill( obj );
compiler.compiled[ "background" ] = adj;
compiler = null;
return [ "general" ];
}
}
class Timerchenge extends AbstractArgument {
public function Timerchenge() {
}
override protected function onDone( obj :Object ) :Array {
var adj :Adjustment = new Adjustment;
adj.fill( obj );
compiler.compiled[ "timerchenge" ] = adj;
compiler = null;
return [ "general" ];
}
}
class ShapeAdjustment extends AbstractArgument {
private var name :String;
private var ruleName :String;
public function ShapeAdjustment( args :Array ) {
name = args[0];
ruleName = args[1];
}
override protected function onDone( obj :Object ) :Array {
var shape :Adjustment = new Adjustment();
shape.name = name;
shape.fill( obj );
var last :int = compiler.compiled[ ruleName ].length - 1;
compiler.compiled[ ruleName ][ last ].draw.push( shape )
compiler = null;
return [ "ruleDraw", ruleName ];
}
}
/*
IStateインターフェース
トークンの読み込み用のもの
*/
interface IState {
function eat( token :String, compiler :Compiler ) :Array;
}
/*
確率変動
*/
class RuleWeight implements IState {
private var weight :Number = 1;
private var ruleName :String;
public function RuleWeight( args :Array ) {
ruleName = args[0];
}
public function eat( token :String, compiler :Compiler ) :Array {
if ( token != "{" ) {
weight = parseFloat( token );
return null;
}
else {
compiler.compiled[ ruleName ].push({ weight: weight, draw: [] });
return [ "ruleDraw", ruleName ];
}
}
}
class General implements IState {
public function General(){
}
public function eat( token :String, compiler :Compiler ) :Array {
return [ token ];
}
}
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.SimpleButton;
class CustomSimpleButton extends SimpleButton {
private var upColor:uint = 0xFFCC00;
private var overColor:uint = 0xCCFF00;
private var downColor:uint = 0x00CCFF;
private var size:uint = 20;
public function CustomSimpleButton(width:Number=640,height:Number=480) {
downState = new ButtonDisplayState(downColor, size);
overState = new ButtonDisplayState(overColor, size);
upState = new ButtonDisplayState(upColor, size);
hitTestState = new ButtonDisplayState(upColor, size * 2);
hitTestState.x = -(size / 4);
hitTestState.y = hitTestState.x;
useHandCursor = true;
}
}
class ButtonDisplayState extends Shape {
private var bgColor:uint;
private var size:uint;
public function ButtonDisplayState(bgColor:uint, size:uint) {
this.bgColor = bgColor;
this.size = size;
draw();
}
private function draw():void {
graphics.beginFill(bgColor);
graphics.drawRect(0, 0, size, size);
graphics.endFill();
}
}