| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 (<code>bitmapFrom</code>), and |
| * the other representing the end state (<code>bitmapTo</code>). |
| * |
| * <p>The animation is performed by running a pixel-shader program, |
| * specified by the <code>shader</code> 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.</p> |
| * |
| * <p>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.</p> |
| * |
| * <p>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.</p> |
| * |
| * <p>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.</p> |
| * |
| * <p>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.</p> |
| * |
| * @mxml |
| * |
| * <p>The <code><s:AnimateTransitionShader></code> tag |
| * inherits all of the tag attributes of its superclass, |
| * and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <s:AnimateTransitionShader |
| * <b>Properties</b> |
| * id="ID" |
| * bitmapFrom="no default" |
| * bitmapTo="no default" |
| * shaderByteCode="no default" |
| * sahderProperties="no default" |
| * /> |
| * </pre> |
| * |
| * @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). |
| * |
| * <p>The pixel-shader program can have arbitrary functionality and inputs, but |
| * must, at a minimum, have three <code>image4</code> 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.</p> |
| * |
| * <p>There must be at least two other input bitmaps |
| * named <code>from</code> and <code>to</code> |
| * which represent the before and after bitmap images. |
| * Finally, you must define one |
| * <code>float</code> parameter named <code>progress</code> |
| * that contains the elapsed fraction of the effect.</p> |
| * |
| * <p>You can specify two optional parameters, <code>width</code> |
| * and <code>height</code>. If they exist, they |
| * are automatically set to the width and height of the |
| * effect target.</p> |
| * |
| * <p>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.</p> |
| * |
| * @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 <code>direction</code> in a |
| * shader with a Pixel Bender pbj file in Wipe.pbj, the calling |
| * code could do the following: |
| * |
| * <pre> |
| * [Embed(source="Wipe.pbj", mimeType="application/octet-stream")] |
| * private var WipeCodeClass:Class; |
| * var shaderEffect = new AnimateTransitionShader(); |
| * shaderEffect.shaderByteCode = WipeCodeClass; |
| * shaderEffect.shaderProperties = {direction : 1}; |
| * </pre> |
| * |
| * @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 = {bitmap:bmData, 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; |
| } |
| } |
| } |