//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package spark.effects { import flash.display.BitmapData; import flash.geom.Rectangle; import flash.utils.ByteArray; import mx.core.IUIComponent; import mx.core.mx_internal; import mx.effects.IEffectInstance; import mx.resources.IResourceManager; import mx.resources.ResourceManager; import spark.effects.supportClasses.AnimateTransitionShaderInstance; import spark.primitives.supportClasses.GraphicElement; import spark.utils.BitmapUtil; use namespace mx_internal; //-------------------------------------- // Other metadata //-------------------------------------- /** * The AnimateTransitionShader effect uses Pixel Bender, * which is not supported for AIR mobile applications. */ [DiscouragedForProfile("mobileDevice")] [ResourceBundle("sparkEffects")] /** * The AnimateTransitionShader effect animates a transition between two bitmaps, * one representing the start state (bitmapFrom), and * the other representing the end state (bitmapTo). * *

The animation is performed by running a pixel-shader program, * specified by the shader property, * using the two bitmaps as input. * The bitmaps are represented by an instance of the flash.display.BitmapData class. * You can create your own pixel-shader program * by using Adobe Pixel Bender Toolkit.

* *

If either bitmap is * not supplied, that value is determined dynamically from * either the appropriate state of the target in a transition or, * if the effect is not running in a transition, from the * target directly. If * the effect is run in a transition and the target object either * goes away or comes into existence during that state change, * then a fully-transparent bitmap is used to represent * that object when it does not exist.

* *

This effect can only be run on targets that are either * UIComponents or GraphicElements, since capturing the bitmap * of the object requires information about the object that only * exists in these classes.

* *

Because the effect is bitmap-based, and the underlying * pixel-shader program expects both bitmaps to be the same size, * the effect only works correctly when both bitmaps are * of the same size. This means that if the target object changes * size or changes orientation leading to a different size bounding * box, then the effect might not play correctly.

* *

This effect and its subclasses differ from other effects in * Flex in that they are intended to work on their own, and may * not have the intended result when run in parallel with other effects. * This constraint comes from the fact that both of the before and after * bitmaps are captured before the start of the effect. So if something * happens to the target object after these bitmaps are calculated, * such as another effect changing the target's properties, then those * changes are not be accounted for in the pre-calculated bitmap and * the results might not be as expected. To ensure correct playing of * these bitmap-based effects, they should be played alone on * their target objects.

* * @mxml * *

The <s:AnimateTransitionShader> tag * inherits all of the tag attributes of its superclass, * and adds the following tag attributes:

* *
 *  <s:AnimateTransitionShader
 *    Properties
 *    id="ID"
 *    bitmapFrom="no default"
 *    bitmapTo="no default"
 *    shaderByteCode="no default"
 *    sahderProperties="no default"
 *  />
 *  
* * @see flash.display.BitmapData * @see spark.effects.supportClasses.AnimateTransitionShaderInstance * @see spark.primitives.supportClasses.GraphicElement * * @includeExample examples/AnimateTransitionShaderExample.mxml * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public class AnimateTransitionShader extends Animate { /** * Constructor. * * @param target The Object to animate with this effect. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function AnimateTransitionShader(target:Object=null) { super(target); instanceClass = AnimateTransitionShaderInstance; } //-------------------------------------------------------------------------- // // Class variables // //-------------------------------------------------------------------------- /** * @private * Storage for the resourceManager getter. * This gets initialized on first access, * not at static initialization time, in order to ensure * that the Singleton registry has already been initialized. */ private static var _resourceManager:IResourceManager; /** * @private * A reference to the object which manages * all of the application's localized resources. * This is a singleton instance which implements * the IResourceManager interface. */ private static function get resourceManager():IResourceManager { if (!_resourceManager) _resourceManager = ResourceManager.getInstance(); return _resourceManager; } /** * The bitmap data representing the start state of this effect. * If this property is not set, it is calculated automatically * when the effect is played by taking a snapshot of the target * object, or by using a transparent bitmap if the object does not * exist in the start view state of a transition. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public var bitmapFrom:BitmapData; /** * The bitmap data representing the end state of this effect. * If this property is not set, it is calculated automatically * when the effect is played by taking a snapshot of the target * object, or by using a transparent bitmap if the object does not * exist in the end view state of a transition. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public var bitmapTo:BitmapData; /** * The bytecode for the pixel-shader program that the effect uses * to animate between the two bitmaps. This * property can be represented as either a ByteArray or as a * Class representing a ByteArray (which is what results * when you embed a resource). * *

The pixel-shader program can have arbitrary functionality and inputs, but * must, at a minimum, have three image4 inputs. * The first input, which can be named anything, should go * unused by your pixel-shader program code - it exists only to satisfy the * Flash requirement of assigning a filtered object to the * first input. Note that inputs that go completely unused in a * pixel-shader program might be optimized out, so your code should * at least reference this input once.

* *

There must be at least two other input bitmaps * named from and to * which represent the before and after bitmap images. * Finally, you must define one * float parameter named progress * that contains the elapsed fraction of the effect.

* *

You can specify two optional parameters, width * and height. If they exist, they * are automatically set to the width and height of the * effect target.

* *

See the Pixel Bender Toolkit documentation for more * information on writing pixel-shader programs for Flash. * You can also look at the source code for the CrossFade.pbk file in the * frameworks\projects\flex4\src\spark\effects directory of the Flex source code.

* * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public var shaderByteCode:Object; /** * A map of parameter name/value pairs passed to the pixel-shader program * before playing. For example, * to set a parameter named direction in a * shader with a Pixel Bender pbj file in Wipe.pbj, the calling * code could do the following: * *
     *   [Embed(source="Wipe.pbj", mimeType="application/octet-stream")]
     *   private var WipeCodeClass:Class;
     *   var shaderEffect = new AnimateTransitionShader();
     *   shaderEffect.shaderByteCode = WipeCodeClass;
     *   shaderEffect.shaderProperties = {direction : 1};
     * 
* * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public var shaderProperties:Object; /** * @private */ override public function getAffectedProperties():Array /* of String */ { // We track visible and parent so that we can automatically // perform transitions from/to states where the target either // does not exist or is not visible // Note that 'bitmapInfo' is an Object map containing both a bitmap // and the visual bounds of that bitmap on the screen return ["bitmapInfo", "visible", "parent"]; } /** * @private */ override protected function getValueFromTarget(target:Object, property:String):* { if (property != "bitmapInfo") return super.getValueFromTarget(target, property); // Return a null bitmap for non-visible targets if (!target.visible || !target.parent) return null; if (!(target is GraphicElement || target is IUIComponent)) throw new Error(resourceManager.getString("sparkEffects", "cannotOperateOn")); var bmData:BitmapData; var tempFilters:Array = target.filters; var bounds:Rectangle; target.filters = []; try { if (target is GraphicElement) { bmData = GraphicElement(target).captureBitmapData(true, 0, false); // The GraphicElement version does not calculate the visual bounds, // so just create dummy bounds with the correct width/height bounds = new Rectangle(0, 0, bmData ? bmData.width : 0, bmData ? bmData.height : 0); } else { // Passing in a non-null bounds parameter forces getSnapshot() // to return the visual bounds of the object bounds = new Rectangle(); bmData = BitmapUtil.getSnapshot(IUIComponent(target), bounds, true); } } catch (e:SecurityError) { // Do nothing and let it return null. } // The effect instance will retrieve the bitmap and bounds from the object // stored here var bmHolder:Object = new Object(); bmHolder["bitmap"] = bmData; bmHolder["bounds"] = bounds; target.filters = tempFilters; return bmHolder; } /** * @private */ override protected function initInstance(instance:IEffectInstance):void { super.initInstance(instance); var animateTransitionShaderInstance:AnimateTransitionShaderInstance = AnimateTransitionShaderInstance(instance); animateTransitionShaderInstance.bitmapFrom = bitmapFrom; animateTransitionShaderInstance.bitmapTo = bitmapTo; if (!shaderByteCode) // User should always supply a shader, but if they don't just // pass it on animateTransitionShaderInstance.shaderByteCode = null; else animateTransitionShaderInstance.shaderByteCode = (shaderByteCode is ByteArray) ? ByteArray(shaderByteCode) : new shaderByteCode(); animateTransitionShaderInstance.shaderProperties = shaderProperties; } } }