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

forked from: pbjLabratory Lite  # HueGradient Fill

とりあえずHueGradientでfork
Get Adobe Flash player
by zahir 26 Jun 2009
/**
 * Copyright zahir ( http://wonderfl.net/user/zahir )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/86vh
 */

// forked from zahir's pbjLabratory Lite  # Circle Transition Shader
/*
 *  とりあえずHueGradientでfork
*/
package{
	import flash.display.Sprite;
	[SWF(width=465, height = 465, backgroundColor = 0x666666)]
	public class PbjLabLite extends Sprite{
		public function PbjLabLite(){
			
			// 使い方は基本的に
			// パラメータのソート方法とShaderをBase64エンコードした文字列を
			// 引数に与えるだけです。
			
			// maxValue :: minVlue :: defaultValueをpbj側で設定していないときの挙動がおかしいけど気にしない方がいいです。きっと。
			// 画像を自分で設定したい場合は300行目の前後60行の範囲あたりをいじればどうにかなると思います。
			
			var sort:String = ShaderReader.SORT_INDEX;
			//  SORT_INDEX は Pixel Bender ToolKitで定義した順番で表示します(多分
			//  SORT_NAME はパラメータの名前順で表示します
			//  SORT_NONE はソートを行いません(並びは場合によりけりです)
			
			
			var code:String = "pQEAAACkCwBIdWVHcmFkaWVudKAMbmFtZXNwYWNlAHphaGlyMTkyOQCgDHZlbmRvcgB6YWhpcgCgCHZlcnNpb24AAQCgDGRlc2NyaXB0aW9uAAChAQIAAAxfT3V0Q29vcmQAoQIDAQAOZHN0AKEBAQAAAnJvdGF0ZQCiAW1heFZhbHVlAEO0AACiAW1pblZhbHVlAMO0AACiAWRlZmF1bHRWYWx1ZQAAAAAAoQECAgAMY2VudGVyAKICbWF4VmFsdWUARXoAAEV6AACiAm1pblZhbHVlAAAAAAAAAAAAogJkZWZhdWx0VmFsdWUAQwAAAEMAAAChAQgBgAhSZWZsZWN0aW9uAKIIbWF4VmFsdWUAAQCiCG1pblZhbHVlAAAAoghkZWZhdWx0VmFsdWUAAQAdAgAxAgAQAAICADEAABAAHQMAwQIAsAAdAAAQAwAAAAYAABADAEAAMgEAEDyO800EAgAgAQDAAAMCACAAAMAAHQAAEAIAgAABAAAQAACAADIBABBDtAAAHQIAIAAAwAAIAgAgAQDAAB0AABACAIAAMgGAQAEAAAAoAYCAAYBAAB0BgCAAgAAANAAAAAGAgAAyAQAQv4AAAAMAABABAMAANgAAAAAAAAAyAQAQAAAAACoAABABAMAAHQGAQACAAAA0AAAAAYBAADIBABBDtAAAAQAAEAEAwAA2AAAAAAAAADIBABBCcAAABAIAIAEAwAADAAAQAgCAABoBABAAAMAAHQIAIAEAwAAyAQAQQ38AADICABA/gAAAMgMAID+AAAAdAwAQAwCAAAIDABAAAMAAHQMAIAMAwAABAwAgAgCAAB0DABACAMAAAgMAEAMAgAAdAgAQAQDAAAMCABADAMAAGwEAEAIAwAAyAgAQQ38AAAQDACACAMAAAwMAIAEAwAAdAQAQAwCAADICABBDfwAAMgMAID+AAAAdAwAQAwCAAAIDABAAAMAAHQMAIAMAwAABAwAgAgCAAB0DABACAMAAAwMAEAMAgAAbAgAQAwDAADIDACBDfwAABAMAEAMAgAADAwAQAgDAAB0CABADAMAAMgMAIAAAAAAoAgAgAwCAAB0BgEAAgAAANAAAAAGAQAAyAwAgP4AAAB0EAIADAIAAHQQAQAEAwAAyAwAgAAAAAB0EACADAIAAHQEA4gQAGAA1AAAAAAAAADIDACA/gAAAKAIAIAMAgAAdAYAgAIAAADQAAAABgIAAHQQAgAIAwAAyAwAgP4AAAB0EAEADAIAAMgMAIAAAAAAdBAAgAwCAAB0BAOIEABgANQAAAAAAAAAyAwAgQAAAACgCACADAIAAHQGAEACAAAA0AAAAAYDAADIDACAAAAAAHQQAgAMAgAAyAwAgP4AAAB0EAEADAIAAHQQAIAEAwAAdAQDiBAAYADUAAAAAAAAAMgMAIEBAAAAoAgAgAwCAAB0CgIAAgAAANAAAAAKAAAAyAwAgAAAAAB0EAIADAIAAHQQAQAIAwAAyAwAgP4AAAB0EACADAIAAHQEA4gQAGAA1AAAAAAAAADIDACBAgAAAKAIAIAMAgAAdAoBAAIAAADQAAAACgEAAHQQAgAEAwAAyAwAgAAAAAB0EAEADAIAAMgMAID+AAAAdBAAgAwCAAB0BAOIEABgANQAAAAAAAAAyAwAgQKAAACgCACADAIAAHQKAIACAAAA0AAAAAoCAADIDACA/gAAAHQQAgAMAgAAyAwAgAAAAAB0EAEADAIAAHQQAIAIAwAAdAQDiBAAYADYAAAAAAAAANgAAAAAAAAA2AAAAAAAAADYAAAAAAAAANgAAAAAAAAA2AAAAAAAAAA==";
			
			// pbjをbase64にエンコードしたい場合は以前に投稿したpbjLab β版などを利用すると簡単です。
			// pbjLab β1.1
			//  http://wonderfl.net/code/c68bb838e74bb4d4da1ab3e77534ffc338455ed7
			
			// pbjExplorer Lite
			//  http://wonderfl.net/code/641abdd60ca3a9196e3bd1d167132fc6c8e39e5c
			
			// pbjExplorer (AIR1.5.1)
			//  http://zahir.s69.coreserver.jp/air/pbjexplorer/pbjExplorer.air
			
			// pbjBrowser (鋭意製作中)
			
			var myLab:Lab = new Lab( sort, code );
			addChild( myLab );

			Wonderfl.capture_delay(10);
		}
	}
}
	/*
	 * かなりゴチャゴチャなので見ても参考にならないと思います。
	*/
	import com.adobe.images.JPGEncoder;
	import com.adobe.images.PNGEncoder;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.BlendMode;
	import flash.display.Graphics;
	import flash.display.Loader;
	import flash.display.Shader;
	import flash.display.ShaderData;
	import flash.display.ShaderJob;
	import flash.display.ShaderParameter;
	import flash.display.ShaderInput;
	import flash.display.Sprite;
	
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.events.TextEvent;
	
	import flash.filters.DropShadowFilter;
	
	import flash.geom.Matrix;
	import flash.geom.Point;
	
	import flash.net.FileFilter;
	import flash.net.FileReference;
	
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	
	import mx.utils.Base64Decoder;
	
/*
 *  pbjLaboratory Lite
 *   本体
*/
class Lab extends Sprite{
	private var w:int, h:int;
	private var s:Shader;
	private var sd:ShaderData;
	private var sj:ShaderJob;
	
	private var file:FileReference;
	private const FF:Array = [new FileFilter("Image File (*.jpg, *.png)", "*.jpg; *.png") ];
	// gifって需要あるんですかね?
	
	private var input_arr:Array;
	private var param_arr:Array;
	private var meta:Object;
	
	private var use_image_num:int = 0;
	private var cur_input_num:int;
	private var flgs:Array;
	private var start_flg:Boolean = false;
	private var side:int = 256;
	
	private var read:ShaderReader;
	private var code:String;
	
	//Menu
	private var title:MyMenu;
	private var inputMenu:MyMenu;
	private var paramMenu:MyMenu;
	
	// menu Color
	private var link:uint = 0xFF9900;
	private var sepa:uint = 0x0099FF;
	
	private var imgs:InputImages;
	private var viewer:Viewer;
	
	private var txtView:TextViewer;
	private var txtV_open:Boolean = false;
	private var old_txtV:String = "";
	
	private var paramCont:ParameterContainer;
	private var pc_open:Boolean = false;
	private var old_pc:String = "";
	
	private var bd:BitmapData;
	
	private var dsf:DropShadowFilter;
	
	public function Lab(sort:String, _code:String ){
		code = _code;
		var dec:Base64Decoder = new Base64Decoder();
		dec.decode( code );
		s = new Shader( dec.toByteArray() );
		sd = s.data;
		dec = null;
		
		w = h = 465;
		
		dsf = new DropShadowFilter( 4, 90, 0x333333 );
		read = new ShaderReader( sd , sort);
		setViewer();
		setMeta( read.metaData );
		setInputs( read.inputs );
		setParams( read.params );
	}
	private function setMeta( obj:Object ):void{
		meta = obj;
		title = new MyMenu();
		title.addSeparator( "<b>pbjLabLite</b>");
		title.addSeparator("  |", sepa );
		title.addSeparator( meta.name + "  ver."+ meta.version + "      vendor : " + meta.vendor);
		title.addSeparator("  |", sepa );
		title.addMenu( "Data", "data", link );
		title.addMenu( "Export", "exp", link );
		title.addSeparator("  |", sepa );
		addChild( title );
		title.filters = [dsf ];
		
		title.addEventListener(TextEvent.LINK, function (e:TextEvent):void{
			if(txtView){
				if( contains( txtView ) ){
					removeChild(txtView);
				}txtView = null;
			}
			var txt:String = "";
			if(e.text == "data" && !txtV_open){
				txtV_open = true;
				txt = read.InputHtml;
				txt += "\n\n";
				txt += read.ParamHtml;
				openView(txt);
			}else if(e.text == "exp" && !txtV_open){
				txtV_open = true;
				txt = Export.conv(meta.name, code );
				openView(txt);
			}else if(e.text != old_txtV){
				if(e.text == "data"){
					txtV_open = true;
					txt = read.InputHtml;
					txt += "\n\n";
					txt += read.ParamHtml;
					openView(txt);
				}else if(e.text == "exp"){
					txtV_open = true;
					txt = Export.conv(meta.name, code );
					openView(txt);
				}
			}else txtV_open = false;
			
			old_txtV = e.text;
		});
		function openView( str:String ):void{
			txtView = new TextViewer(str);
			addChild(txtView);
			txtView.x = (w - txtView.width) >>1;
			txtView.y = (h - txtView.height) >>1;
		}
	}
	private function setInputs( arr:Array ):void{
		input_arr = arr;
		flgs = [];
		use_image_num = input_arr.length;
		
		var m:MyMenu = new MyMenu();
		m.addSeparator("Source Image");
		m.addSeparator("|",sepa);
		if(!arr.length){
			start_flg = true;
			start();
		}else{
			for(var i:int=0; i<use_image_num; i++){
				m.addMenu( input_arr[i].name, String(i), link);
				flgs[flgs.length] = false;
			}
			m.addSeparator("|",sepa);
		}
		m.addSeparator("Save Image");
		m.addMenu("jpg",  "jpg", link);
		m.addMenu("png", "png", link );
		
		m.filters = [dsf ];
		m.y = title.height + 8;
		m.x = 16;
		inputMenu = m;
		addChild(inputMenu);
		inputMenu.addEventListener(TextEvent.LINK,onInputLink);
		
		imgs = new InputImages( arr );
		imgs.x = 32;
		imgs.y = m.y + m.height + 10 ;
		imgs.filters = [dsf];
		addChild( imgs );
	}
	private function setParams( arr:Array ):void{
		param_arr = arr;
		var m:MyMenu = new MyMenu();
		m.addSeparator("Shader Parameter");
		for(var i:int=0, len:int=arr.length; i<len; i++){
			m.addSeparator("\n");
			m.addMenu(arr[i].name + "  (<font color=\"#CC3300\">" + arr[i].type + "</font>)", String(i) , link);
		}
		m.y = viewer.y;
		m.x = 16;
		m.filters = [dsf];
		paramMenu = m;
		addChild(paramMenu);
		m.addEventListener(TextEvent.LINK,function(e:TextEvent):void{
			if(paramCont){
				if(contains(paramCont))
					removeChild(paramCont);
				paramCont = null;
			}
			var i:int;
			if(e.text == old_pc && !pc_open){
				old_pc = e.text;
				pc_open = true;
				i = parseInt( e.text );
				paramCont = new ParameterContainer( arr[i].name, sd, arr[i].type, arr[i].values, onChange);
				addChild(paramCont);
				paramCont.x = m.x + m.width - 15;
				paramCont.y = mouseY - 5;
			}else if(e.text != old_pc){
				old_pc = e.text;
				pc_open = true;
				i = parseInt( e.text );
				paramCont = new ParameterContainer( arr[i].name, sd, arr[i].type, arr[i].values, onChange);
				addChild(paramCont);
				paramCont.x = m.x + m.width -15;
				paramCont.y = mouseY - 5;
			}else{
				pc_open = false;
			}
		});
	}
	private function setViewer():void{
		bd = new BitmapData(256,256,false, 0x999999)
		viewer = new Viewer( 256, 256, bd );
		viewer.filters = [ dsf ];
		viewer.x = 465 - viewer.width - 16;
		viewer.y = 465 - viewer.height - 16;
		addChild(viewer);
	}
	private function onInputLink(e:TextEvent):void{
		parseInt(e.text) is int ? loadImage( parseInt(e.text)) : saveImage(e.text);
	}
	private function loadImage(num:int):void{
		cur_input_num = num;
		file = new FileReference();
		file.addEventListener(Event.SELECT, onSelect);
		file.browse(FF);
	}
	private function onSelect(e:Event):void{
		file.removeEventListener(Event.SELECT, onSelect);
		file.addEventListener(Event.COMPLETE, onComp);
		file.load();
	}
	private function onComp(e:Event):void{
		file.removeEventListener(Event.COMPLETE, onComp);
		var l:Loader = new Loader();
		l.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void{
			var _w:int = l.width; var _h:int = l.height;
			var m:Matrix = new Matrix();
			if(_w > _h){
				if(_w > side){
					l.width = side;
					l.scaleY = l.scaleX;
				}
			}else{
				if(_h > side){
					l.height = side;
					l.scaleX = l.scaleY;
				}
			}m.scale( l.scaleX, l.scaleY );
			_w = (side - l.width) >>1;
			_h = (side - l.height) >>1;
			m.translate( _w,  _h);
			var name:String = input_arr[ cur_input_num ].name;
			var image:BitmapData = new BitmapData(side,side,false, 0xFFFFFF);
			image.draw( l, m );
			sd[name].input = image;
			sd[name].width = sd[name].height = side;
			
			var side2:int = 90;
			m = new Matrix();
			_w = l.width;  _h = l.height;
			if(_w > _h){
				if(_w > side2){
					l.width = side2;
					l.scaleY = l.scaleX;
				}
			}else{
				if(_h > side2){
					l.height = side2;
					l.scaleX = l.scaleY;
				}
			}m.scale( l.scaleX, l.scaleY );
			_w = (side2 - l.width) >>1;
			_h = (side2 - l.height) >>1;
			m.translate( _w, _h );
			imgs.update( cur_input_num, l, m);
			
			flgs[ cur_input_num ] = true;
			for(var i:int = 0; i<use_image_num; i++){
				if( !flgs[i] ) break;
				else if(flgs[i] && i == use_image_num-1){
					start_flg = true;
					start();
				}
			}
		});
		l.loadBytes( file.data );
	}
	private function saveImage(txt:String):void{
		file = new FileReference();
		var date:Date = new Date();
		var str:String = meta.name + String(date.fullYear) + String(date.month + 1) + String(date.date);
		switch(txt){
			case "jpg":
				var jpg:JPGEncoder = new JPGEncoder(90);
				file.save( jpg.encode( bd ),  str + ".jpg");
				break;
			case "png":
				file.save( PNGEncoder.encode( bd ), str + ".png");
				break;
		}
	}
	private function onChange(name:String, num:int, value:Number):void{
		sd[name].value[num] = value;
		if(start_flg)
			start();
	}
	private function start():void{
		sj = new ShaderJob(s,bd,side,side);
		sj.start( true );
	}
	//end
}


/*
 *  Parameter Container
 *   ターゲットとなるShaderDataのパラメータを表示するクラスを格納するクラス
*/
class ParameterContainer extends Sprite{
	private var g:Graphics;
	private var _bg:uint;
	private var _stroke:uint;
	private var _color:uint;
	private var dsf:Array = [new DropShadowFilter(4, 90, 0, 0.4)];
	
	public function ParameterContainer(name:String, sd:ShaderData, type:String, values:Array, change:Function, bg:uint = 0x111111, stroke:uint = 0x333333, color:uint = 0xCCCCCC){
		g = this.graphics;
		_bg = bg;
		_stroke = stroke;
		_color = color;
		
		switch(type){
			case "int":createInt(name, sd, 1, values, change); break;
			case "int2":createInt(name, sd, 2, values, change); break;
			case "int3":createInt(name, sd, 3, values, change); break;
			case "int4":createInt(name, sd, 4, values, change); break;
			case "float":createFloat(name, sd, 1, values, change); break;
			case "float2":createFloat(name, sd, 2, values, change); break;
			case "float3":createFloat(name, sd, 3, values, change); break;
			case "float4":createFloat(name, sd, 4, values, change); break;
			case "matrix2x2": createMatrix(name, sd, 2, values, change);break;
			case "matrix3x3": createMatrix(name, sd, 3, values, change);break;
			case "matrix4x4":createMatrix(name, sd, 4, values, change); break;
			default: trace("boolなんて対応してないです");
		}
		this.filters = dsf;
	}
	private function createInt(name:String, sd:ShaderData, num:int, values:Array, change:Function):void{
		var _mx:String = (values[1].type) ? values[1].value : "1";
		var mn:String = (values[2].type) ? values[2].value : "0";
		var def:String = (values[3].type) ? values[3].value : "0";
		var value:Number = (sd[name].value[i]) ? sd[name].value[i]: Number(def);
		var max:Boolean = (values[1].type) ? false : true;
		var min:Boolean = (values[2].type) ? false : true;
		
		var x_a:Array = setArray( _mx);
		var n_a:Array = setArray( mn);
		var d_a:Array = setArray( def);
		if(num != 1){
			var k:int = 0;
			var ll:int = num;
			if(x_a.length == 1){
				for(k = 0; k<ll; k++)
					x_a[k] = 1;
			}
			if(n_a.length == 1){
				for(k = 0; k<ll; k++)
					n_a[k] = 0;
			}
			if(d_a.length == 1){
				for(k = 0; k<ll; k++)
					d_a[k] = 0;
			}
		}
		
		for(var i:int = 0; i<num; i++){
			var tb:TxtBox = new TxtBox(name, i, change, openSlider, closeSlider, Number(x_a[i]), Number(n_a[i]), Number(d_a[i]), sd, max, min, true);
			this.addChild( tb );
			tb.width = 40;
			tb.x = 5;
			tb.y = i * 23 + 5;
		}
		g.lineStyle( 1, _stroke );
		g.beginFill( _bg );
		g.drawRoundRect(0, 0, 50, i*23 + 5, 5, 5);
		g.endFill();
	}
	private function createFloat(name:String, sd:ShaderData, num:int, values:Array, change:Function):void{
		var _mx:String = (values[1].type) ? values[1].value : "1";
		var mn:String = (values[2].type) ? values[2].value : "0";
		var def:String = (values[3].type) ? values[3].value : "0";
		var value:Number = (sd[name].value[i]) ? sd[name].value[i]: Number(def);
		var max:Boolean = (values[1].type) ? false : true;
		var min:Boolean = (values[2].type) ? false : true;
		
		var x_a:Array = setArray( _mx);
		var n_a:Array = setArray( mn);
		var d_a:Array = setArray( def);
		if(num != 1){
			var k:int = 0;
			var ll:int = num;
			if(x_a.length == 1){
				for(k = 0; k<ll; k++)
					x_a[k] = 1;
			}
			if(n_a.length == 1){
				for(k = 0; k<ll; k++)
					n_a[k] = 0;
			}
			if(d_a.length == 1){
				for(k = 0; k<ll; k++)
					d_a[k] = 0;
			}
		}
		for(var i:int = 0; i<num; i++){
			var tb:TxtBox = new TxtBox(name, i, change, openSlider, closeSlider, Number(x_a[i]), Number(n_a[i]), Number(d_a[i]), sd, max, min);
			this.addChild( tb );
			tb.width = 40;
			tb.x = 5;
			tb.y = i * 23 + 5;
		}
		g.lineStyle( 1, _stroke );
		g.beginFill( _bg );
		g.drawRoundRect(0, 0, 50, i*23 + 5, 5, 5);
		g.endFill();
	}
	private function setArray(str:String):Array{
		var _arr:Array = [];
		var sub:String = "";
		var n:int=0;
		if(str){
			_arr[n] = new String();
			for(var i:int=0, len2:int = str.length; i<len2; i++){
				sub = str.substr(i,1);
				if(sub == ","){
					n++;
					_arr[n] = new String();
				}else
					_arr[n]+=sub;
			}
		}
		return _arr;
	}
	private function createMatrix(name:String, sd:ShaderData, num:int, values:Array, change:Function):void{
		var n:int = 0;
		var _mx:String = (values[1].type) ? values[1].value : "1";
		var mn:String = (values[2].type) ? values[2].value : "0";
		var def:String = (values[3].type) ? values[3].value : "0";
		var value:Number = (sd[name].value[i]) ? sd[name].value[i]: Number(def);
		var max:Boolean = (values[1].type) ? false : true;
		var min:Boolean = (values[2].type) ? false : true;
		var x_a:Array = setArray( _mx);
		var n_a:Array = setArray( mn);
		var d_a:Array = setArray( def);
		
		var k:int = 0;
		var ll:int = num * num;
		if(x_a.length == 1){
			for(k = 0; k<ll; k++)
				x_a[k] = 1;
		}
		if(n_a.length == 1){
			for(k = 0; k<ll; k++)
				n_a[k] = 0;
		}
		if(d_a.length == 1){
			for(k = 0; k<ll; k++)
				d_a[k] = 0;
		}
		
		for(var i:int = 0; i<num; i++){
			for(var j:int = 0; j<num; j++){
				var tb:TxtBox = new TxtBox(name, n, change, openSlider, closeSlider, Number(x_a[n]), Number(n_a[n]), Number(d_a[n]), sd, max, min);
				this.addChild( tb );
				tb.width = 40;
				tb.x = j * 45 + 5;
				tb.y = i * 23 + 5;
				////////////////////////////////
				n++;
			}
		}
		g.lineStyle( 1, _stroke );
		g.beginFill( _bg );
		g.drawRoundRect(0, 0, 45 * j + 5, i*23 + 5, 5, 5);
		g.endFill();
	}
	private var s:Slider;
	private var open_flg:Boolean = false;
	private var old_name:String = "";
	private var old_num:int = 99;
	private function openSlider( _name:String, num:int, max:Number, min:Number, value:Number, w:int, change:Function, change2:Function, maxEdit:Boolean = false, minEdit:Boolean = false, int_flg:Boolean = false):void{
		if(s){
			if(contains( s ))
				removeChild( s );
			s = null;
		}
		
		if(_name == old_name && num == old_num && !open_flg){
				old_name = _name;
				old_num = num;
				open_flg = true;
				
				s = new Slider( _name, num,max,min, value, w, change, change2, maxEdit, minEdit, int_flg);
				s.x = this.width - 3;
				s.y = mouseY - 10;
				s.filters = dsf;
				addChild(s);
			}else if(_name != old_name || num != old_num){
				old_name = _name;
				old_num = num;
				open_flg = true;
				
				s = new Slider( _name, num,max,min, value, w, change, change2, maxEdit, minEdit, int_flg);
				s.x = this.width - 3;
				s.y = mouseY - 10;
				s.filters = dsf;
				addChild(s);
			}else{
				open_flg = false;
			}
	}
	private function closeSlider():void{
		if(s && !Slider.none_close_flg){
			if(contains( s ))
				removeChild( s );
			s = null;
			open_flg = false;
		}
	}
}

/*
 * TxtBox
 *  ShaderDataの現在の値を表示するクラス
*/
class TxtBox extends TextField{
	private var int_flg:Boolean;
	public function TxtBox( _name:String, num:int, change:Function, doubleClick:Function, close:Function, max:Number, min:Number, def:Number, sd:ShaderData,maxEdit:Boolean = false, minEdit:Boolean = false, integer:Boolean = false, bg:uint = 0x111111, stroke:uint = 0x666666, color:uint = 0xCCCCCC){
		this.background = this.border = true;
		this.backgroundColor = bg;
		this.borderColor = stroke;
		this.textColor = color;
		this.height = 18;
		var value:Number = sd[_name].value[num] ? sd[_name].value[num] :0;
		var format:TextFormat = new TextFormat();
		format.align = "right";
		this.defaultTextFormat = format;
		this.mouseEnabled = true;
		this.doubleClickEnabled = true;
		int_flg = integer;
		if(int_flg){
			text = String( Math.round( value ) );
		}else text = value.toString();
		
		var focus:String = "";
		
		
		this.addEventListener( MouseEvent.CLICK ,function(e:MouseEvent):void{
			doubleClick(_name, num,max,min, value, 250, change, onChange, maxEdit, minEdit, int_flg);
		});
		
		this.addEventListener(Event.CHANGE, function(e:Event):void{
			var v:Number = Number(text) is Number ? Number(text) : Number(focus);
			if(v > max) v = max;
			else if( v < min) v = min;
			
			if(int_flg){
				v = Math.round( v );
			}
			text = String( v );
			
			change(_name, num,  v);
		});
		function onChange(value:Number):void{
			if(int_flg){
				value = Math.round( value );
			}
			if(value > max) value = max;
			else if( value< min) value = min;
			text = String(value);
		}
	}
}
/*
 *  Slider
 *   いろいろテキトウ
 *   縦表示にしようか迷ったけどめんどくさかったのでほぼそのまま前作から流用
*/
class Slider extends Sprite{
	public static var none_close_flg:Boolean = false;
	
	private var _name:String;
	private var _max:Number, _min:Number, _def:Number;
	private var now:Number;
	private var v:Number;
	private var _v:Number;
	private var flg:Boolean;
	private var pick:Sprite;
	private var maxT:TextField;
	private var minT:TextField;
	private var nowT:TextField;
	private var btn:SliderBtn;
	private var left:int, right:int, side:int;
	
	private var s_change:Function;
	private var p_change:Function;
	private var num:int;
	private var f_int:Boolean;
	
	private var format:TextFormat;
	private var focus_str:String = "";
	private var curX:int, curY:int;
	private var move_flg:Boolean = true;
	
	public function Slider( name:String, num:int,  max:Number, min:Number, def:Number, w:int , change:Function, parentChange:Function, xedit:Boolean = false, nedit:Boolean = false, integer:Boolean = false){
		_max = max;
		_min = min;
		_def = def;
		_name = name;
		this.num = num;
		f_int = integer;
		s_change = change;
		p_change = parentChange;
		
		var g:Graphics = this.graphics;
		g.lineStyle( 1, 0x666666);
		g.beginFill(0x111111, 0.8);
		g.drawRoundRect(0,0, w, 50, 5, 5);
		g.endFill();
		
		format = new TextFormat();
		format.align = flash.text.TextFormatAlign.RIGHT;
		minT = textBox(min.toString(), 40, 18, nedit);
		minT.setTextFormat( format );
		//if(nedit)
		this.addChild( minT );
		minT.x = 5;
		maxT = textBox(max.toString(), 40, 18, xedit);
		maxT.setTextFormat( format );
		this.addChild( maxT );
		maxT.x = w - (40 + 5);
		
		nowT = textBox(def.toString(), 60, 18, true);
		nowT.setTextFormat( format );
		this.addChild( nowT );
		nowT.x =( w - (60)) >> 1;
		nowT.addEventListener(KeyboardEvent.KEY_DOWN, changeNow);
		nowT.addEventListener(FocusEvent.FOCUS_IN,function(e:FocusEvent):void{
			focus_str = nowT.text;
			nowT.text = "";
		});
		nowT.addEventListener(FocusEvent.FOCUS_OUT,function(e:FocusEvent):void{
			if(nowT.text == "" || !Number(nowT.text) is Number)
				nowT.text = focus_str;
		});
		
		maxT.y = minT.y = nowT.y = 5;
		
		g.moveTo( 5, 29);
		g.lineTo( 5, 45);
		var _a:Number = w-5;
		g.moveTo( _a, 29);
		g.lineTo( _a, 45);
		
		g.moveTo( 5, 37);
		g.lineTo(_a, 37);
		g.lineStyle(1, 0x00CCFF);
		_a = w>>1;
		g.moveTo( _a, 34);
		g.lineTo( _a, 40);
		
		left = 5;
		right = w - 5;
		side = right - left;
		
		var n1:Number = 0;
		var n2:Number = 0;
		if(max<0) n1 = -max;
		else n1 = max;
		if(min<0) n2= -min;
		else n2= min;
		v = (n1+n2);
		_v = side * n2/v;
		
		btn = new SliderBtn(8, 14, 0xCCCCCC, 0xCC6600);
		this.addChild( btn );
		btn.y = 37;
		
		btn.x = side * (def/v) + _v +left; // やけに難しかった…
		
		btn.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void{
			move_flg = false;
			none_close_flg = true;
			btn.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
			btn.stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
		});
		this.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void{
			if(move_flg){
				curX = mouseX;
				curY = mouseY;
				stage.addEventListener(MouseEvent.MOUSE_MOVE, thisMove);
				stage.addEventListener(MouseEvent.MOUSE_UP, thisUp);
			}
		});
	}
	
	private function thisMove(e:MouseEvent):void{
		e.updateAfterEvent();
		x += mouseX - curX;
		y += mouseY - curY;
	}
	private function thisUp(e:MouseEvent):void{
		stage.removeEventListener(MouseEvent.MOUSE_MOVE, thisMove);
		stage.removeEventListener(MouseEvent.MOUSE_UP, thisUp);
	}
	private function onMove(e:MouseEvent):void{
		btn.x = mouseX;
		if(btn.x < left) btn.x = left;
		else if(btn.x > right) btn.x = right;
		
		now = (btn.x - left - _v) / side * v; 
		if(f_int) now = Math.round( now );
		
		p_change(now);
		nowT.text = now.toString();
		
		s_change( _name, num.toString(), now );
		p_change(now);
		none_close_flg = true;
	}
	
	private function onUp(e:MouseEvent):void{
		btn.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
		btn.stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
		none_close_flg = false;
		move_flg = true;
	}
	
	private function textBox( txt:String, w:int, h:int, edit:Boolean):TextField{
		var t:TextField = new TextField();
		t.width = w;
		t.height = h;
		t.text = txt;
		if(!edit){
			t.border = true;
			t.textColor = t.borderColor = 0xCCCCCC;
			t.thickness = 1;
		}else{
			t.background = t.border =  true;
			t.backgroundColor = 0xCCCCCC;
			t.thickness = 1;
			t.borderColor = 0xFFFFFF;
			t.mouseEnabled = t.selectable = true;
			t.type = "input";
		}
		return t;
	}
	
	private function changeMax(e:KeyboardEvent):void{
		none_close_flg = true;
		if(e.keyCode == 13){
			var n1:Number = Number(maxT.text) is Number ? Number(maxT.text) : 1;
			var n2:Number = _min;
			if(n1<0) n1 = -n1;
			else n1 = n1;
			if(n2<0) n2= -n2;
			else n2= n2;
			v = (n1+n2);
			_v = side * n2/v;
			
			now = Number(nowT.text);
			if(f_int) now = Math.round( now );
			btn.x = side * (now/v) + _v +left; 
			s_change( _name, num.toString(), now );
			p_change(now);
		}
	}
	
	private function changeMin(e:KeyboardEvent):void{
		none_close_flg = true;
		if(e.keyCode == 13){
			var n1:Number = _max;
			var n2:Number = Number(minT.text) is Number ? Number(minT.text) : 0;
			if(n1<0) n1 = -n1;
			else n1 = n1;
			if(n2<0) n2= -n2;
			else n2= n2;
			v = (n1+n2);
			_v = side * n2/v;
			
			now = Number(nowT.text);
			nowT.setTextFormat( format );
			if(f_int) now = Math.round( now );
			btn.x = side * (now/v) + _v +left; 
			s_change( _name, num.toString(), now );
			p_change(now);
		}
	}
	private function changeNow(e:KeyboardEvent):void{
		if(e.keyCode == 13){
			if(Number(nowT.text) is Number)
				now = Number(nowT.text);
			else now = Number(focus_str);
			if(f_int) now = Math.round( now );
			nowT.text = now.toString();
			btn.x = side * (now/v) + _v +left; 
			s_change( _name, num.toString(), now );
			p_change(now);
		}
	}
	
	public function get value():Number{
		if(!flg) return v;
		else return Math.round( v );
	}
}

/*
*		SliderBtn
*		Sliderのつまみ
*/
class SliderBtn extends Sprite{
	private var g:Graphics;
	private var color:uint;
	private var over:uint;
	private var w:int, h:int;
	
	public function SliderBtn(_w:int, _h:int , _color:uint, overColor:uint){
		w = _w >>1;
		h = _h >>1;
		color = _color;
		over = overColor;
		
		g = this.graphics;
		draw(color);
		this.addEventListener(Event.ADDED,function(e:Event):void{
			add();
		});
	}
	
	private function add():void{
		this.addEventListener(MouseEvent.ROLL_OVER, function(e:MouseEvent):void{
			draw(over);
		});
		this.addEventListener(MouseEvent.ROLL_OUT, function(e:MouseEvent):void{
			draw(color);
		});
	}
	
	private function draw(c:uint):void{
		g.clear();
		g.lineStyle(1, c );
		g.drawRect(-w,-h,w*2, h*2);
		g.lineStyle( undefined );
		g.beginFill( c );
		g.moveTo(-w,-h);
		g.lineTo( w, -h);
		g.lineTo(-w,h);
		g.lineTo(w,h);
		g.lineTo(-w,-h);
		g.endFill();
	}
}

/*
 *  textViewer
 *   parameter群の情報やExportの文字列を表示するクラス
*/
class TextViewer extends Sprite{
	public function TextViewer(txt:String, w:int = 400, h:int = 400, bg:uint = 0x111111, stroke:uint = 0x333333, textBG:uint = 0xCCCCCC, textBorder:uint = 0x666666, color:uint = 0 ){
		var g:Graphics = this.graphics;
		g.lineStyle(1, stroke);
		g.beginFill(bg);
		g.drawRoundRect( 0,0,w,h, 5,5);
		g.endFill();
		
		var t:TextField = new TextField();
		t.background = t.border = true;
		t.backgroundColor = textBG;
		t.borderColor = textBorder;
		t.textColor = color;
		t.width = w - 40;
		t.height = h - 40;
		t.htmlText = txt;
		addChild( t );
		t.x = (w - t.width) >>1;
		t.y = (h - t.height) >> 1;
	}
}


/*
 *  input する画像を表示するクラスを格納するクラス
 *  別に要らない気もする
*/
class InputImages extends Sprite{
	private var imgs:Array = [];
	private var damy:BitmapData = new BitmapData(90,90, true, 0xFFFFFF );
	public function InputImages( _arr:Array , bg:uint = 0x111111, stroke:uint = 0x333333){
		var len:int = _arr.length;
		for(var i:int = 0; i<len; i++){
			var img:Img = new Img(_arr[i].name, stroke);
			img.x = i * 105 + 6;
			img.y = 5;
			addChild(img);
			imgs[i] = img;
		}
		var g:Graphics = this.graphics;
		g.lineStyle( 2, stroke );
		g.beginFill( bg );
		g.drawRoundRect(0,0, i * 105 + 7, 110 , 5, 5);
		g.endFill();
	}
	public function update( num:int , source:Loader, matrix:Matrix ):void{
		var img:Img = imgs[num] as Img;
		img.bmp.bitmapData.copyPixels(damy, damy.rect, new Point(0,0));
		img.bmp.bitmapData.draw( source, matrix );
	}
}

/*
 *  Shaderにinputする画像を表示するクラス
 */
class Img extends Sprite{
	public var bmp:Bitmap;
	public function Img( _name:String ,stroke:uint){
		var g:Graphics = this.graphics;
		g.lineStyle(1, stroke);
		g.drawRect( 0,0,100,100);
		
		bmp = new Bitmap( new BitmapData( 90,90, true, 0xFFFFFF));
		addChild( bmp );
		bmp.x = bmp.y = 5;
		
		var t:TextField = new TextField();
		t.text = _name;
		t.x = 5;
		t.y = 2;
		t.blendMode = flash.display.BlendMode.INVERT;
		addChild(t)
	}
}

/*
 *  ShaderJobの実行結果画像を表示するGUIクラス
*/
class Viewer extends Sprite{
	public var bmp:Bitmap;
	public function Viewer(w:int, h:int, bd:BitmapData, bg:uint = 0x111111, stroke:uint = 0x333333){
		var g:Graphics = this.graphics;
		g.lineStyle(2, stroke );
		g.beginFill( bg );
		g.drawRoundRect( 0, 0, w + 10, h + 10, 5, 5);
		g.endFill();
		
		bmp = new Bitmap( bd );
		bmp.x = (this.width - bmp.width) >> 1;
		bmp.y = (this.height - bmp.height) >> 1;
		bmp.x -= 1;
		bmp.y -= 1;
		addChild(bmp);
	}
}

/*
 *  メニュークラス
 *  いちいちSpriteとか使うのが面倒なので
 *  TextEvent.LINKで簡単に
*/
class MyMenu extends TextField{
	private var str:String = "    ";
	public function MyMenu(bg:uint = 0x111111, stroke:uint = 0x666666, color:uint = 0xCCCCCC){
		autoSize = "left";
		border = background = true;
		backgroundColor = bg;
		borderColor = stroke;
		textColor = color;
	}
	public function addMenu(txt:String, eventTxt:String, color:uint = 0xCCCCCC, decoration:Boolean = true):void{
		if(decoration){
			str += setColor("<u><a href=\"event:" + eventTxt + "\">" + txt + "</a></u>", color) + "    ";
		}else{
			str += setColor("<a href=\"event:" + eventTxt + "\">" + txt + "</a>", color) + "    ";
		}
		htmlText = str ;
	}
	public function addSeparator(txt:String, color:uint = 0xCCCCCC):void{
		str += setColor(txt, color) + "    ";
		htmlText = str;
	}
	private function setColor(txt:String, color:uint):String{
		return "<font color = \"#"+ color.toString(16) + "\">" + txt + "</font>";
	}
}
/*
*		Export
*		BASE64形式でwonderflで使いやすい感じで出力
*/
class Export{
	public static function conv( name:String, code:String):String{
		var br:String = "\n";
		var tab:String = "\t";
		var tab2:String = "\t\t";
		var tab3:String = tab + tab2;
		
        return "" +
"class " + name + " extends Shader" + br +
"{" + br +
tab + "public function " + name+ "()" + br +
tab + "{" + br +
tab2 +"var dec:Base64Decoder = new Base64Decoder();" + br +
tab2 +"dec.decode( \"" + code+ "\" );" + br +
tab2 +"this.byteCode = dec.toByteArray();" + br +
tab2 +"dec = null;" + br + 
tab + "}"+ br +
"}" + br + br + br +
"/*高機能なExport機能は\n↓にて配布中の pbjExplorer をお使いください。" + br +
"http://zahir.s69.coreserver.jp/air/pbjexplorer/pbjExplorer.air" + br +
"要 Adobe AIR1.5以上*/";
	}
}

/*
 *  Shaderのパラメータ群のデータを読み取るクラス
 *  ソートの方法を選択できるようにした。
*/
class ShaderReader{
	public static const SORT_INDEX:String = "index";
	public static const SORT_NAME:String = "name";
	public static const SORT_NONE:String = "none";
	
	private var input:Array;
	private var param:Array;
	private var meta:Object;
	
	public function get inputs():Array{ return input; }
	public function get params():Array{ return param; }
	public function get metaData():Object{ return meta; }
	
	public function ShaderReader( sd:ShaderData , sort:String ="index"){
		input = [];
		param = [];
		for( var p:String in sd){
			if( sd[p] is ShaderParameter ){
				var v:Array = [];
				for(var m:String in sd[p]) v[v.length] = {"type":m, "value":sd[p][m]};
				param[param.length] = {"name":p, "index":sd[p].index, "type":sd[p].type, "values":sortValues( v )};
			}else if( sd[p] is ShaderInput ){
				input[input.length] = {"name":p, "index":sd[p].index, "channels":sd[p].channels};
			}
		}
		meta = {
			"name": (sd["name"] != null) ? sd["name"] : "",
			"namespace":(sd["namespace"] != null) ? sd["namespace"] : "",
			"vendor":(sd["vendor"] != null) ? sd["vendor"] : "",
			"version":(sd["version"] != null) ? sd["version"] : "",
			"description":(sd["description"] != null) ? sd["description"] : ""
		};
		
		if(sort == "index"){
			param.sortOn( "index", Array.CASEINSENSITIVE );
			input.sortOn("index", Array.CASEINSENSITIVE );
		}else if(sort == "name"){
			param.sortOn( "name", Array.CASEINSENSITIVE );
			input.sortOn("name", Array.CASEINSENSITIVE );
		}
	}
	private function sortValues( v:Array ):Array{
		if(v){
			var _name:Object = {};
			var _des:Object = {};
			var _max:Object = {};
			var _min:Object = {};
			var _def:Object = {};
			
			for(var i:int=0, len:int= v.length; i<len;  i++){
				if(v[i].type == "name") _name = v[i]; 
				else if(v[i].type == "description") _des = v[i];
				else if(v[i].type == "maxValue") _max = v[i];
				else if(v[i].type == "minValue") _min = v[i];
				else if(v[i].type == "defaultValue") _def = v[i];
            }
            v = null;
            
			return [_name, _max, _min, _def, _des];
		}else return [];
	}
	public function get InputHtml():String{
		var str:String = "";
		if(input.length){
			str = "<font color=\"#339900\">";
			str += "//    Input's </font>\n\n";
			for(var i:int=0, len:int= input.length; i<len; i++){
				str += "\t<font color=\"#0000FF\">" + input[i].name +"</font>";
				str += " ( <font color=\"#339900\">" + input[i].channels + "</font> )\n";
			}
		}
		return str;
	}
	public function get ParamHtml():String{
		var str:String = "";
		if(param.length){
			str = "<font color=\"#339900\">";
			str += "//    Parameter's </font>\n\n";
			for(var i:int=0, len:int= param.length; i<len; i++){
				var v:Array = param[i].values;
				str += "\t<font color=\"#0000FF\">" + param[i].name +"</font>";
				str += " ( <font color=\"#339900\">" + param[i].type + "</font> )\n";
				str += "\t<\n";
				if(v){
					for(var j:int = 0, len2:int = v.length; j<len2; j++){
						if(v[j].type)
							str += "\t\t<font color=\"#FF6600\">" + v[j].type + "</font> : " + v[j].value + "\n";
					}
				}
				str += "\t>;\n\n";
			}
		}
		return str;
	}
}