package { import flash.display.Shader; import flash.events.Event; import flash.events.EventDispatcher; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; import flash.utils.ByteArray; /** * Class to handle loading or embedding, and passing values to a shader * to make it easier dealing with the quirks of the Shader class and bytecode. */ public class graphic_flex_image_effects_05_Flex_ShaderWrapper extends EventDispatcher { private var _shader:Shader; /** * Constructor. This accepts a path to a .pbj file to load or * a shader bytecode class to instantiate. If a file needs to be loaded, * the loading is initiated immediately. Completion of load will result in * a COMPLETE event being fired. * * @param pathOrClass Either the path to a .pbj file or the shader bytecode class. */ public function graphic_flex_image_effects_05_Flex_ShaderWrapper(pathOrClass:Object) { var shaderClass:Class = pathOrClass as Class; // if a class is passed, immediately instantiate it if (shaderClass != null) { createShader(ByteArray(new shaderClass())); // if a file path is passed, immediately load it } else if ((pathOrClass as String) != null) { load(pathOrClass as String); } else { throw new Error("Invalid object passed to constructor."); } } /** * Creates the Shader instance from the bytecode. * * @param data The ByteArray containing the shader bytecode. */ private function createShader(data:ByteArray):void { _shader = new Shader(data); dispatchEvent(new Event(Event.COMPLETE)); } /** * Loads the specified .pbj file. * * @param path The path to the .pbj file to load. */ private function load(path:String):void { var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onShaderLoaded); loader.load(new URLRequest(path)); } /** * Handler for when the .pbj file completes loading. * * @param event Event dispatched by URLLoader. */ private function onShaderLoaded(event:Event):void { var loader:URLLoader = event.target as URLLoader; createShader(loader.data as ByteArray); } /** * Returns the value of the specified parameter from the shader. * This method ensures that float and int values are extracted from * the Array that wraps them. * * @param name The name of the parameter to retrieve. * * @return The value of the parameter. */ public function getParameter(name:String):Object { // check to see if parameter exists if (_shader.data.hasOwnProperty(name)) { var value:Object = _shader.data[name].value; var type:String = _shader.data[name].type; // if type is float or int, grab the only value from the array if (type == "float" || type == "int") { value = (value as Array)[0]; } return value; } return null; } /** * Sets the value of the specified parameter of the shader. * This method ensures that all values are passed as arrays to the shader, * even if the parameter is scalar. * * @param name The name of the parameter to set. * @param value The value to give the parameter. * * @return True if the parameter was found and set. */ public function setParameter(name:String, value:Object):Boolean { // check to see if parameter exists if (_shader.data.hasOwnProperty(name)) { // wrap scalar values in an array if (!(value is Array)) { value = [value]; } _shader.data[name].value = value; return true; } return false; } /** * Returns the Shader instance this class wraps. * * @return The Shader instance managed by this class. */ public function get shader():Shader { return _shader; } } }