forked from: Embedded PixelBender Generator
forked from Embedded PixelBender Generator (diff: 286)
Embedded PixelBender Generator. * pbjファイルをコード内に埋め込むためのASクラスを生成するツールです. * パラメータがある場合はgetter/setterも適宜自動生成します. * * getter/setterを生成するためにpbjのディスアセンブラを作った後に, * ShaderDataから必要な情報を取り出せることに気づき泣きました. * pbjのディスアセンブラはまた機会があれば晒します. * * 2010.07.12 パラメータのgetter/setter部分にデフォルト値が反映されていなかったのを修正 * * @author Yukiya Okuda
ActionScript3 source code
/**
* Copyright nojyfied ( http://wonderfl.net/user/nojyfied )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/kUok
*/
// forked from alumican_net's Embedded PixelBender Generator
/**
* Embedded PixelBender Generator.
* pbjファイルをコード内に埋め込むためのASクラスを生成するツールです.
* パラメータがある場合はgetter/setterも適宜自動生成します.
*
* getter/setterを生成するためにpbjのディスアセンブラを作った後に,
* ShaderDataから必要な情報を取り出せることに気づき泣きました.
* pbjのディスアセンブラはまた機会があれば晒します.
*
* 2010.07.12 パラメータのgetter/setter部分にデフォルト値が反映されていなかったのを修正
*
* @author Yukiya Okuda<alumican.net>
*/
package
{
import com.bit101.components.Label;
import com.bit101.components.PushButton;
import com.bit101.components.RadioButton;
import com.bit101.components.TextArea;
import flash.display.BlendMode;
import flash.display.Shader;
import flash.display.ShaderData;
import flash.display.ShaderInput;
import flash.display.ShaderParameter;
import flash.display.ShaderParameterType;
import flash.display.Sprite;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.IOErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.TimerEvent;
import flash.filters.ShaderFilter;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.text.TextField;
import flash.utils.ByteArray;
import flash.utils.Timer;
public class Main extends Sprite
{
private var _file:FileReference;
private var _shader:Shader;
private var _bytes:ByteArray;
private var _inputs:Object;
private var _parameters:Object;
private var _metadata:Object;
public function Main():void
{
Wonderfl.disable_capture();
stage.scaleMode = StageScaleMode.NO_SCALE;
var template:XML = <data><code><![CDATA[package
{
import flash.display.Shader;
import flash.utils.ByteArray;
/**
* %CLASS%
* %META_DESCRIPTION%
* @author %META_VENDER%
* @version %META_VERSION%
* @namespace %META_NAMESPACE%
*/
class %CLASS% extends Shader
{
//Parameters
%BEGIN_PARAMS%/**
* %PARAM_NAME% %PARAM_TYPEARRAY%
* %PARAM_DESCRIPTION%
* @type %PARAM_PBJTYPE%
* @minValue %PARAM_MIN%
* @maxValue %PARAM_MAX%
* @defaultValue %PARAM_DEFAULT%
*/
public function get %PARAM_NAME%():Array { return data.%PARAM_NAME%.value; }
public function set %PARAM_NAME%(value:Array):void { data.%PARAM_NAME%.value = value; }
%END_PARAMS%//Constructor
public function %CLASS%():void
{
if (_byte == null)
{
_byte = new ByteArray();
for (var i:uint = 0, l:uint = _data.length; i < l; ++i) _byte.writeByte(_data[i]);
}
super(_byte);
}
//Data
private static var _byte:ByteArray = null;
private static var _data:Vector.<int> = Vector.<int>(%DATA%);
}
}]]></code><usage><filter><![CDATA[var myShader:%CLASS% = new %CLASS%();
var myFilter:ShaderFilter = new ShaderFilter(myShader);
//if target is DisplayObject
target.filters = [myFilter];
//if target is BitmapData
target.applyFilter(target, target.rect, new Point(), myFilter);]]></filter><shader><![CDATA[var myShader:%CLASS% = new %CLASS%();
//target is DisplayObject
target.blendMode = BlendMode.SHADER;
target.blendShader = myShader;]]></shader></usage></data>;
var title:Label = new Label(this, 6, 0, "Embedded PixelBender Generator");
title.scaleX = title.scaleY = 2;
title.alpha = 0.7;
new Label(this, 8, 333, "Main Code");
var usageField:TextArea = new TextArea(this, 10, 353);
usageField.width = 443;
usageField.height = 100;
usageField.textField.addEventListener(FocusEvent.FOCUS_IN, _selectField);
var usageTypeFilter:RadioButton = new RadioButton(this, 359, 338, "Filter", true, function(e:Event):void {
if (_shader) usageField.text = _generateCode(template.usage.filter.text());
} );
var usageTypeShader:RadioButton = new RadioButton(this, 409, 338, "Shader", false, function(e:Event):void {
if (_shader) usageField.text = _generateCode(template.usage.shader.text());
} );
new Label(this, 8, 75, "Shader Code");
var codeField:TextArea = new TextArea(this, 10, 95);
codeField.width = 443;
codeField.height = 230;
codeField.textField.addEventListener(FocusEvent.FOCUS_IN, _selectField);
_file = new FileReference();
_file.addEventListener(Event.CANCEL, trace);
_file.addEventListener(IOErrorEvent.IO_ERROR, trace);
_file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, trace);
_file.addEventListener(Event.SELECT, function(e:Event):void
{
_file.load();
} );
_file.addEventListener(Event.COMPLETE, function(e:Event):void
{
_shader = new Shader(_bytes = _file.data);
_inputs = new Object();
_parameters = new Object();
_metadata = new Object();
var data:ShaderData = _shader.data;
for (var name:String in data)
{
if (data[name] is ShaderInput) _inputs[name] = data[name];
else if (data[name] is ShaderParameter) _parameters[name] = data[name];
else _metadata[name] = data[name];
}
codeField.text = _generateCode(template.code.text());
usageField.text = _generateCode(usageTypeFilter.selected ? template.usage.filter.text() : template.usage.shader.text());
codeField.textField.scrollV = 1;
usageField.textField.scrollV = 1;
saveButton.alpha = 1;
} );
var loadButton:PushButton = new PushButton(this, 10, 45, "Load .pbj File", function(e:Event):void {
_file.browse([new FileFilter("*.pbj", "*.pbj")]);
} );
loadButton.width = 215;
var saveButton:PushButton = new PushButton(this, 239, 45, "Save .as File", function(e:Event):void {
if (_shader) (new FileReference()).save(codeField.text, _metadata["name"] + ".as");
} );
saveButton.blendMode = BlendMode.LAYER;
saveButton.width = 215;
saveButton.alpha = 0.3;
}
private function _selectField(e:FocusEvent):void
{
var tf:TextField = TextField(e.target);
var timer:Timer = new Timer(10);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void
{
e.target.removeEventListener(e.type, arguments.callee);
var scroll:int = tf.scrollV;
tf.setSelection(0, tf.text.length);
tf.scrollV = scroll;
} );
timer.start();
}
private function _generateCode(template:String, removeLF:Boolean = true):String
{
template = template.replace(/\r\n/g, "\n");
template = template.replace(/\r/g, "\n");
var byteList:Array = new Array();
_bytes.position = 0;
while (_bytes.bytesAvailable) byteList.push(_bytes.readByte());
var byteString:String = "[" + byteList.join(", ") + "]";
template = template.replace(/%CLASS%/g, _metadata["name"]);
template = template.replace(/%DATA%/g, byteString);
template = template.replace(/(.*?)%BEGIN_PARAMS%(.*?)%END_PARAMS%(.*?)/s, function(matched:String, capture0:String, capture1:String, capture2:String, index:int, string:String):String
{
for each (var parameter:ShaderParameter in _parameters)
{
var code:String = capture1;
var type:String;
var length:int;
switch (parameter["type"])
{
case ShaderParameterType.FLOAT:
type = "Number";
length = 1;
break;
case ShaderParameterType.FLOAT2:
type = "Number";
length = 2;
break;
case ShaderParameterType.FLOAT3:
type = "Number";
length = 3;
break;
case ShaderParameterType.FLOAT4:
type = "Number";
length = 4;
break;
case ShaderParameterType.INT:
type = "int";
length = 1;
break;
case ShaderParameterType.INT2:
type = "int";
length = 2;
break;
case ShaderParameterType.INT3:
type = "int";
length = 3;
break;
case ShaderParameterType.INT4:
type = "int";
length = 4;
break;
case ShaderParameterType.BOOL:
type = "Boolean";
length = 1;
break;
case ShaderParameterType.BOOL2:
type = "Boolean";
length = 2;
break;
case ShaderParameterType.BOOL3:
type = "Boolean";
length = 3;
break;
case ShaderParameterType.BOOL4:
type = "Boolean";
length = 4;
break;
case ShaderParameterType.MATRIX2X2:
type = "Number";
length = 4;
break;
case ShaderParameterType.MATRIX3X3:
type = "Number";
length = 9;
break;
case ShaderParameterType.MATRIX4X4:
type = "Number";
length = 16;
break;
}
var types:Array = new Array(length);
for (var i:int = 0; i < length; ++i) types[i] = type;
code = code.replace(/%PARAM_TYPEARRAY%/g, "[" + types.join(", ") + "]");
code = code.replace(/%PARAM_TYPE%/g, type);
code = code.replace(/%PARAM_LENGTH%/g, length);
code = code.replace(/%PARAM_NAME%/g, parameter["name"]);
code = code.replace(/%PARAM_PBJTYPE%/g, parameter["type"]);
code = code.replace(/%PARAM_DESCRIPTION%/g, parameter["description"] != null ? parameter["description"] : "%REMOVE_LINE%");
code = code.replace(/%PARAM_MIN%/g, parameter["minValue"] != null ? parameter["minValue"] : "%REMOVE_LINE%");
code = code.replace(/%PARAM_MAX%/g, parameter["maxValue"] != null ? parameter["maxValue"] : "%REMOVE_LINE%");
code = code.replace(/%PARAM_DEFAULT%/g, parameter["defaultValue"] != null ? parameter["defaultValue"] : "%REMOVE_LINE%");
capture0 += code;
}
return capture0 + capture2;
} );
template = template.replace(/%META_VENDER%/g, _metadata["vendor"] != null ? _metadata["vendor"] : "%REMOVE_LINE%");
template = template.replace(/%META_VERSION%/g, _metadata["version"] != null ? _metadata["version"] : "%REMOVE_LINE%");
template = template.replace(/%META_NAMESPACE%/g, _metadata["namespace"] != null ? _metadata["namespace"] : "%REMOVE_LINE%");
template = template.replace(/%META_DESCRIPTION%/g, _metadata["description"] != null ? _metadata["description"] : "%REMOVE_LINE%");
template = template.replace(/\n(.*?)%REMOVE_LINE%(.*?)\n/g, "\n");
template = template.replace(/\n(.*?)%REMOVE_LINE%(.*?)\n/g, "\n");
return template;
}
}
}