blob: 9fc087bfc0d3d667fe1fcfec7bc49140a9919e21 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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 mx.effects.effectClasses
{
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Shape;
import flash.events.Event;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import mx.controls.SWFLoader;
import mx.core.FlexShape;
import mx.core.IContainer;
import mx.core.IInvalidating;
import mx.core.IUIComponent;
import mx.core.mx_internal;
import mx.effects.EffectInstance;
import mx.effects.EffectManager;
import mx.effects.Tween;
import mx.events.FlexEvent;
import mx.events.ResizeEvent;
import mx.events.TweenEvent;
use namespace mx_internal;
/**
* The MaskEffectInstance class is an abstract base class
* that implements the instance class for
* the MaskEffect class.
* <p>Every effect class that is a subclass of the TweenEffect class
* supports the following events:</p>
*
* <ul>
* <li><code>tweenEnd</code>: Dispatched when the tween effect ends. </li>
*
* <li><code>tweenUpdate</code>: Dispatched every time a TweenEffect
* class calculates a new value.</li>
* </ul>
*
* <p>The event object passed to the event listener for these events is of type TweenEvent.
* The TweenEvent class defines the property <code>value</code>, which contains
* the tween value calculated by the effect.
* For the Mask effect,
* the <code>TweenEvent.value</code> property contains a 4-item Array, where: </p>
* <ul>
* <li>value[0]:Number The value of the target's <code>x</code> property.</li>
*
* <li>value[1]:Number The value of the target's <code>y</code> property.</li>
*
* <li>value[2]:Number The value of the target's <code>scaleX</code> property.</li>
*
* <li>value[3]:Number The value of the target's <code>scaleY</code> property.</li>
* </ul>
*
* @see mx.effects.MaskEffect
* @see mx.events.TweenEvent
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public class MaskEffectInstance extends EffectInstance
{
include "../../core/Version.as";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @param target The Object to animate with this effect.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function MaskEffectInstance(target:Object)
{
super(target);
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* Contains the effect mask, either the default mask created
* by the <code>defaultCreateMask()</code> method,
* or the one specified by the function passed to the
* <code>createMaskFunction</code> property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var effectMask:Shape;
/**
* The actual size of the effect target, including any drop shadows.
* Flex calculates the value of this property; you do not have to set it.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected var targetVisualBounds:Rectangle;
/**
* @private
*/
private var effectMaskRefCount:Number = 0;
/**
* @private
*/
private var invalidateBorder:Boolean = false;
/**
* @private
*/
private var moveTween:Tween;
/**
* @private
*/
private var origMask:DisplayObject;
/**
* @private
*/
private var origScrollRect:Rectangle;
/**
* @private
*/
private var scaleTween:Tween;
/**
* @private
*/
private var tweenCount:int = 0;
/**
* @private
*/
private var currentMoveTweenValue:Object;
/**
* @private
*/
private var currentScaleTweenValue:Object;
/**
* @private
*/
private var MASK_NAME:String = "_maskEffectMask";
/**
* @private
*/
private var dispatchedStartEvent:Boolean = false;
/**
* @private
*/
private var useSnapshotBounds:Boolean = true;
/**
* @private
*/
private var stoppedEarly:Boolean = false;
/**
* @private
*/
mx_internal var persistAfterEnd:Boolean = false;
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
// createMaskFunction
//--------------------------------------------------------------------------
/**
* @private
* Storage for the createMaskFunction property.
*/
private var _createMaskFunction:Function;
/**
* Function called when the effect creates the mask.
* The default value is a function that returns a Rectangle
* with the same dimensions as the effect target.
*
* <p>You can use this property to specify your own callback function to draw the mask.
* The function must have the following signature:</p>
*
* <pre>
* public function createLargeMask(targ:Object, bounds:Rectangle):Shape {
* var myMask:Shape = new Shape();
* // Create mask.
*
* return myMask;
* }
* </pre>
*
* <p>You set this property to the name of the function,
* as the following example shows for the WipeLeft effect:</p>
*
* <pre>
* &lt;mx:WipeLeft id="showWL" createMaskFunction="createLargeMask" showTarget="false"/&gt;</pre>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get createMaskFunction():Function
{
return _createMaskFunction != null ?
_createMaskFunction :
defaultCreateMask;
}
/**
* @private
*/
public function set createMaskFunction(value:Function):void
{
_createMaskFunction = value;
}
//----------------------------------
// moveEasingFunction
//----------------------------------
/**
* Easing function to use for moving the mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var moveEasingFunction:Function;
//--------------------------------------------------------------------------
// playheadTime
//--------------------------------------------------------------------------
/**
* @private
*/
override public function get playheadTime():Number
{
var value:Number;
if (moveTween)
value = moveTween.playheadTime;
else if (scaleTween)
value = scaleTween.playheadTime;
else
return 0;
return value + super.playheadTime;
}
//--------------------------------------------------------------------------
// playReversed
//--------------------------------------------------------------------------
/**
* @private
*/
override mx_internal function set playReversed(value:Boolean):void
{
if (moveTween)
moveTween.playReversed = value;
if (scaleTween)
scaleTween.playReversed = value;
super.playReversed = value;
}
//----------------------------------
// scaleEasingFunction
//----------------------------------
/**
* Easing function to use for scaling the mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var scaleEasingFunction:Function;
//----------------------------------
// scaleXFrom
//----------------------------------
/**
* Initial scaleX for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var scaleXFrom:Number;
//----------------------------------
// scaleXTo
//----------------------------------
/**
* Ending scaleX for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var scaleXTo:Number;
//----------------------------------
// scaleYFrom
//----------------------------------
/**
* Initial scaleY for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var scaleYFrom:Number;
//----------------------------------
// scaleYTo
//----------------------------------
/**
* Ending scaleY for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var scaleYTo:Number;
//----------------------------------
// showTarget
//----------------------------------
[Inspectable(category="General", defaultValue="true")]
/**
* @private
* Storage for the showTarget property.
*/
private var _showTarget:Boolean = true;
/**
* @private
*/
private var _showExplicitlySet:Boolean = false;
/**
* Specifies that the target component is becoming visible,
* <code>false</code>, or invisible, <code>true</code>.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get showTarget():Boolean
{
return _showTarget;
}
/**
* @private
*/
public function set showTarget(value:Boolean):void
{
_showTarget = value;
_showExplicitlySet = true;
}
//----------------------------------
// targetArea
//----------------------------------
/**
* The area where the mask is applied on the target.
* The dimensions are relative to the target itself.
* By default, the area is the entire target and is created like this:
* <code>new Rectangle(0, 0, target.width, target.height);</code>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var targetArea:Rectangle;
//----------------------------------
// xFrom
//----------------------------------
/**
* Initial position's x coordinate for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var xFrom:Number;
//----------------------------------
// xTo
//----------------------------------
/**
* Destination position's x coordinate for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var xTo:Number;
//----------------------------------
// yFrom
//----------------------------------
/**
* Initial position's y coordinate for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var yFrom:Number;
//----------------------------------
// yTo
//----------------------------------
/**
* Destination position's y coordinate for mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public var yTo:Number;
//--------------------------------------------------------------------------
//
// Overridden methods
//
//--------------------------------------------------------------------------
/**
* @private
*/
override public function initEffect(event:Event):void
{
super.initEffect(event);
switch (event.type)
{
case "childrenCreationComplete":
case FlexEvent.CREATION_COMPLETE:
case FlexEvent.SHOW:
case Event.ADDED:
case "resizeEnd":
{
showTarget = true;
break;
}
case FlexEvent.HIDE:
case Event.REMOVED:
case "resizeStart":
{
showTarget = false;
break;
}
case Event.RESIZE:
{
// don't use the snapshot because it will be the wrong size
useSnapshotBounds = false;
break;
}
}
}
/**
* @private
*/
override public function startEffect():void
{
// Init the mask only once when the effect is played.
initMask();
// Register to be notified if the target object is resized.
target.addEventListener(ResizeEvent.RESIZE, eventHandler);
// This will call playEffect eventually.
super.startEffect();
}
/**
* @private
*/
override public function play():void
{
super.play();
// This allows the MaskEffect subclass to set the effect properties.
initMaskEffect();
EffectManager.startVectorEffect(IUIComponent(target));
//EffectManager.startBitmapEffect(target);
// Move Tween
if (!isNaN(xFrom) &&
!isNaN(yFrom) &&
!isNaN(xTo) &&
!isNaN(yTo))
{
tweenCount++;
moveTween = new Tween(this, [ xFrom, yFrom ],
[ xTo, yTo ], duration,
-1, onMoveTweenUpdate, onMoveTweenEnd);
moveTween.playReversed = playReversed;
// If the caller supplied their own easing equation, override the
// one that's baked into Tween.
if (moveEasingFunction != null)
moveTween.easingFunction = moveEasingFunction;
}
// Scale Tween
if (!isNaN(scaleXFrom) &&
!isNaN(scaleYFrom) &&
!isNaN(scaleXTo) &&
!isNaN(scaleYTo))
{
tweenCount++;
scaleTween = new Tween(this, [ scaleXFrom, scaleYFrom ],
[ scaleXTo, scaleYTo ], duration,
-1, onScaleTweenUpdate, onScaleTweenEnd);
scaleTween.playReversed = playReversed;
// If the caller supplied their own easing equation, override the
// one that's baked into Tween.
if (scaleEasingFunction != null)
scaleTween.easingFunction = scaleEasingFunction;
}
dispatchedStartEvent = false;
// Call these after tween creation so that saveTweenValues knows which values to dispatch
if (moveTween)
{
// Set the animation to the initial value
// before the screen refreshes.
onMoveTweenUpdate(moveTween.getCurrentValue(0));
}
if (scaleTween)
{
// Set the animation to the initial value
// before the screen refreshes.
onScaleTweenUpdate(scaleTween.getCurrentValue(0));
}
}
/**
* Pauses the effect until you call the <code>resume()</code> method.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function pause():void
{
super.pause();
if (moveTween)
moveTween.pause();
if (scaleTween)
scaleTween.pause();
}
/**
* @private
*/
override public function stop():void
{
EffectManager.endVectorEffect(IUIComponent(target));
stoppedEarly = true;
super.stop();
if (moveTween)
moveTween.stop();
if (scaleTween)
scaleTween.stop();
}
/**
* Resumes the effect after it has been paused
* by a call to the <code>pause()</code> method.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function resume():void
{
super.resume();
if (moveTween)
moveTween.resume();
if (scaleTween)
scaleTween.resume();
}
/**
* Plays the effect in reverse,
* starting from the current position of the effect.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function reverse():void
{
super.reverse();
if (moveTween)
moveTween.reverse();
if (scaleTween)
scaleTween.reverse();
super.playReversed = !playReversed;
}
/**
* @private
*/
override public function end():void
{
stopRepeat = true;
if (moveTween)
moveTween.endTween();
if (scaleTween)
scaleTween.endTween();
}
/**
* @private
*/
override public function finishEffect():void
{
target.removeEventListener(ResizeEvent.RESIZE, eventHandler);
if (!persistAfterEnd && !stoppedEarly)
removeMask();
super.finishEffect();
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* @private
*/
private function initMask():void
{
if (!effectMask)
{
if (useSnapshotBounds)
targetVisualBounds = getVisibleBounds(DisplayObject(target));
else
targetVisualBounds = new Rectangle(0, 0, target.width, target.height);
effectMask = createMaskFunction(target, targetVisualBounds);
// For Containers we need to add the mask
// to the "allChildren" collection so it doesn't get
// treated as a content child.
if (target is IContainer)
target.rawChildren.addChild(effectMask);
else
target.addChild(effectMask);
effectMask.name = MASK_NAME;
effectMaskRefCount = 0;
}
effectMask.x = 0;
effectMask.y = 0;
effectMask.alpha = .3;
effectMask.visible = false;
// If this object already had a transparency mask, then save off
// the original mask, so that we can restore it when we're done.
if (effectMaskRefCount++ == 0)
{
if (target.mask)
origMask = target.mask;
target.mask = effectMask;
if (target.scrollRect)
{
origScrollRect = target.scrollRect;
target.scrollRect = null;
}
}
invalidateBorder = target is IContainer &&
"border" in target &&
target["border"] != null &&
target["border"] is IInvalidating &&
DisplayObject(target["border"]).filters != null;
}
/**
* Creates the default mask for the effect.
*
* @param targ The effect target.
* @param bounds The actual visual bounds of the target which includes drop shadows
*
* @return A Shape object that defines the mask.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function defaultCreateMask(targ:Object, bounds:Rectangle):Shape
{
// By default, create a mask that is the shape of the target.
var targetWidth:Number = bounds.width / Math.abs(targ.scaleX);
var targetHeight:Number = bounds.height / Math.abs(targ.scaleY);
if (targ is SWFLoader)
{
// Make sure the loader's content has been sized
targ.validateDisplayList();
if (targ.content)
{
targetWidth = targ.contentWidth;
targetHeight = targ.contentHeight;
}
}
var newMask:Shape = new FlexShape();
var g:Graphics = newMask.graphics;
g.beginFill(0xFFFF00);
g.drawRect(0, 0, targetWidth, targetHeight);
g.endFill();
if (target.rotation == 0)
{
newMask.width = targetWidth;
newMask.height = targetHeight;
}
else
{
var angle:Number = targ.rotation * Math.PI / 180;
var sin:Number = Math.sin(angle);
var cos:Number = Math.cos(angle);
newMask.width = Math.abs(targetWidth * cos - targetHeight * sin);
newMask.height = Math.abs(targetWidth * sin + targetHeight * cos);
}
return newMask;
}
/**
* Initializes the <code>move</code> and <code>scale</code>
* properties of the effect.
* All subclasses should override this function.
* Flex calls it after the mask has been created,
* but before the tweens are created.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function initMaskEffect():void
{
if (!_showExplicitlySet &&
propertyChanges &&
propertyChanges.start["visible"] !== undefined)
{
_showTarget = !propertyChanges.start["visible"];
}
}
/**
* @private
* Returns a rectangle that describes the visible region of the component, including any dropshadows
*/
private function getVisibleBounds(targ:DisplayObject):Rectangle
{
var bitmap:BitmapData = new BitmapData(targ.width + 200, targ.height + 200, true, 0x00000000);
var m:Matrix = new Matrix();
m.translate(100, 100);
bitmap.draw(targ, m);
var actualBounds:Rectangle = bitmap.getColorBoundsRect(0xFF000000, 0x00000000, false);
actualBounds.x = actualBounds.x - 100;
actualBounds.y = actualBounds.y - 100;
bitmap.dispose();
if (actualBounds.width < targ.width)
{
actualBounds.width = targ.width;
actualBounds.x = 0;
}
if (actualBounds.height < targ.height)
{
actualBounds.height = targ.height;
actualBounds.y = 0;
}
return actualBounds;
}
/**
* Callback method that is called when the x and y position
* of the mask should be updated by the effect.
* You do not call this method directly.
* This method implements the method of the superclass.
*
* @param value Contains an interpolated
* x and y value for the mask position, where <code>value[0]</code>
* contains the new x position of the mask,
* and <code>value[1]</code> contains the new y position.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function onMoveTweenUpdate(value:Object):void
{
saveTweenValue(value,null);
if (effectMask)
{
effectMask.x = value[0];
effectMask.y = value[1];
}
if (invalidateBorder)
IInvalidating(target["border"]).invalidateDisplayList();
}
/**
* Callback method that is called when the x and y position
* of the mask should be updated by the effect for the last time.
* You do not call this method directly.
* This method implements the method of the superclass.
*
* @param value Contains the final
* x and y value for the mask position, where <code>value[0]</code>
* contains the x position of the mask,
* and <code>value[1]</code> contains the y position.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function onMoveTweenEnd(value:Object):void
{
onMoveTweenUpdate(value);
finishTween();
}
/**
* Callback method that is called when the
* <code>scaleX</code> and <code>scaleY</code> properties
* of the mask should be updated by the effect.
* You do not call this method directly.
* This method implements the method of the superclass.
*
* @param value Contains an interpolated
* <code>scaleX</code> and <code>scaleY</code> value for the mask,
* where <code>value[0]</code>
* contains the new <code>scaleX</code> value of the mask,
* and <code>value[1]</code> contains the new <code>scaleY</code> value.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function onScaleTweenUpdate(value:Object):void
{
saveTweenValue(null, value);
if (effectMask)
{
effectMask.scaleX = value[0];
effectMask.scaleY = value[1];
}
}
/**
* Callback method that is called when the
* <code>scaleX</code> and <code>scaleY</code> properties
* of the mask should be updated by the effect for the last time.
* You do not call this method directly.
* This method implements the method of the superclass.
*
* @param value Contains the final
* <code>scaleX</code> and <code>scaleY</code> value for the mask,
* where <code>value[0]</code>
* contains the <code>scaleX</code> value of the mask,
* and <code>value[1]</code> contains the <code>scaleY</code> value.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function onScaleTweenEnd(value:Object):void
{
onScaleTweenUpdate(value);
finishTween();
}
/**
* @private
*/
private function finishTween():void
{
if (tweenCount == 0 || --tweenCount == 0)
{
EffectManager.endVectorEffect(IUIComponent(target));
var values:Array = [];
var value:Object;
if (moveTween)
{
value = moveTween.getCurrentValue(duration);
values.push(value[0]);
values.push(value[1]);
}
else
{
values.push(null);
values.push(null);
}
if (scaleTween)
{
value = scaleTween.getCurrentValue(duration);
values.push(value[0]);
values.push(value[1]);
}
else
{
values.push(null);
values.push(null);
}
dispatchEvent(new TweenEvent(TweenEvent.TWEEN_END, false, false, values));
finishRepeat();
}
}
/**
* @private
*/
private function removeMask():void
{
// Although it wasn't the original intended design, it turns out that
// two mask effects can play simultaneously inside a <parallel> effect.
// The only gotcha is that we shouldn't clear the mask until both
// effects are done. The solution: a reference count.
if (--effectMaskRefCount == 0)
{
if (origMask == null || (origMask && origMask.name != MASK_NAME))
target.mask = origMask;
if (origScrollRect)
{
target.scrollRect = origScrollRect;
}
if (target is IContainer)
target.rawChildren.removeChild(effectMask);
else
target.removeChild(effectMask);
effectMask = null;
}
}
/**
* @private
*/
private function saveTweenValue(moveValue:Object, scaleValue:Object):void
{
if (moveValue != null)
{
currentMoveTweenValue = moveValue;
}
else if (scaleValue != null)
{
currentScaleTweenValue = scaleValue;
}
if ((moveTween == null || currentMoveTweenValue != null)
&& (scaleTween == null || currentScaleTweenValue != null))
{
var values:Array = [];
if (currentMoveTweenValue)
{
values.push(currentMoveTweenValue[0]);
values.push(currentMoveTweenValue[1]);
}
else
{
values.push(null);
values.push(null);
}
if (currentScaleTweenValue)
{
values.push(currentScaleTweenValue[0]);
values.push(currentScaleTweenValue[1]);
}
else
{
values.push(null);
values.push(null);
}
if (!dispatchedStartEvent)
{
dispatchEvent(new TweenEvent(TweenEvent.TWEEN_START));
dispatchedStartEvent = true;
}
dispatchEvent(new TweenEvent(TweenEvent.TWEEN_UPDATE, false, false, values));
currentMoveTweenValue = null;
currentScaleTweenValue = null;
}
}
//--------------------------------------------------------------------------
//
// Overridden event handlers
//
//--------------------------------------------------------------------------
/**
* @private
*/
override mx_internal function eventHandler(event:Event):void
{
super.eventHandler(event);
// This function is called if the target object is resized.
if (event.type == ResizeEvent.RESIZE)
{
var tween:Tween = moveTween;
if (!tween && scaleTween)
tween = scaleTween;
if (tween)
{
// Remember the amount of the effect that has already been
// played.
var elapsed:Number = getTimer() - tween.startTime;
// Destroy the old tween object. Set its listener to a dummy
// object, so that the onTweenEnd function is not called.
if (moveTween)
Tween.removeTween(moveTween);
if (scaleTween)
Tween.removeTween(scaleTween);
// Reset the tween count
tweenCount = 0;
removeMask();
// The onTweenEnd function wasn't called, so decrement the
// effectMaskRefCount here to keep it in balance.
//effectMaskRefCount--;
// Restart the effect and create a new mask. This is necessary
// so that the mask's size matches the target object's new size.
initMask();
play();
// Set the tween's clock, so that it thinks 'elapsed'
// milliseconds of the animation have already played.
if (moveTween)
{
moveTween.startTime -= elapsed;
// Update the screen before a repaint occurs
moveTween.doInterval();
}
if (scaleTween)
{
scaleTween.startTime -= elapsed;
// Update the screen before a repaint occurs
scaleTween.doInterval();
}
}
}
}
}
}