1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2005-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.effects.effectClasses 13{ 14 15import flash.display.BitmapData; 16import flash.display.DisplayObject; 17import flash.display.Graphics; 18import flash.display.Shape; 19import flash.events.Event; 20import flash.filters.DropShadowFilter; 21import flash.geom.Matrix; 22import flash.geom.Rectangle; 23import flash.utils.getTimer; 24import mx.controls.SWFLoader; 25import mx.core.Container; 26import mx.core.FlexShape; 27import mx.core.IInvalidating; 28import mx.core.IUIComponent; 29import mx.core.mx_internal; 30import mx.effects.EffectInstance; 31import mx.effects.EffectManager; 32import mx.effects.Tween; 33import mx.events.FlexEvent; 34import mx.events.ResizeEvent; 35import mx.events.TweenEvent; 36 37use namespace mx_internal; 38 39/** 40 * The MaskEffectInstance class is an abstract base class 41 * that implements the instance class for 42 * the MaskEffect class. 43 * <p>Every effect class that is a subclass of the TweenEffect class 44 * supports the following events:</p> 45 * 46 * <ul> 47 * <li><code>tweenEnd</code>: Dispatched when the tween effect ends. </li> 48 * 49 * <li><code>tweenUpdate</code>: Dispatched every time a TweenEffect 50 * class calculates a new value.</li> 51 * </ul> 52 * 53 * <p>The event object passed to the event listener for these events is of type TweenEvent. 54 * The TweenEvent class defines the property <code>value</code>, which contains 55 * the tween value calculated by the effect. 56 * For the Mask effect, 57 * the <code>TweenEvent.value</code> property contains a 4-item Array, where: </p> 58 * <ul> 59 * <li>value[0]:Number The value of the target's <code>x</code> property.</li> 60 * 61 * <li>value[1]:Number The value of the target's <code>y</code> property.</li> 62 * 63 * <li>value[2]:Number The value of the target's <code>scaleX</code> property.</li> 64 * 65 * <li>value[3]:Number The value of the target's <code>scaleY</code> property.</li> 66 * </ul> 67 * 68 * @see mx.effects.MaskEffect 69 * @see mx.events.TweenEvent 70 */ 71public class MaskEffectInstance extends EffectInstance 72{ 73 include "../../core/Version.as"; 74 75 //-------------------------------------------------------------------------- 76 // 77 // Constructor 78 // 79 //-------------------------------------------------------------------------- 80 81 /** 82 * Constructor. 83 * 84 * @param target The Object to animate with this effect. 85 */ 86 public function MaskEffectInstance(target:Object) 87 { 88 super(target); 89 } 90 91 //-------------------------------------------------------------------------- 92 // 93 // Variables 94 // 95 //-------------------------------------------------------------------------- 96 97 /** 98 * Contains the effect mask, either the default mask created 99 * by the <code>defaultCreateMask()</code> method, 100 * or the one specified by the function passed to the 101 * <code>createMaskFunction</code> property. 102 */ 103 protected var effectMask:Shape; 104 105 /** 106 * The actual size of the effect target, including any drop shadows. 107 * Flex calculates the value of this property; you do not have to set it. 108 */ 109 protected var targetVisualBounds:Rectangle; 110 111 /** 112 * @private 113 */ 114 private var effectMaskRefCount:Number = 0; 115 116 /** 117 * @private 118 */ 119 private var invalidateBorder:Boolean = false; 120 121 /** 122 * @private 123 */ 124 private var moveTween:Tween; 125 126 /** 127 * @private 128 */ 129 private var origMask:DisplayObject; 130 131 /** 132 * @private 133 */ 134 private var origScrollRect:Rectangle; 135 136 /** 137 * @private 138 */ 139 private var scaleTween:Tween; 140 141 /** 142 * @private 143 */ 144 private var tweenCount:int = 0; 145 146 /** 147 * @private 148 */ 149 private var currentMoveTweenValue:Object; 150 151 /** 152 * @private 153 */ 154 private var currentScaleTweenValue:Object; 155 156 /** 157 * @private 158 */ 159 private var MASK_NAME:String = "_maskEffectMask"; 160 161 /** 162 * @private 163 */ 164 private var dispatchedStartEvent:Boolean = false; 165 166 /** 167 * @private 168 */ 169 private var useSnapshotBounds:Boolean = true; 170 171 /** 172 * @private 173 */ 174 private var stoppedEarly:Boolean = false; 175 176 /** 177 * @private 178 */ 179 mx_internal var persistAfterEnd:Boolean = false; 180 181 //-------------------------------------------------------------------------- 182 // 183 // Properties 184 // 185 //-------------------------------------------------------------------------- 186 187 //-------------------------------------------------------------------------- 188 // createMaskFunction 189 //-------------------------------------------------------------------------- 190 191 /** 192 * @private 193 * Storage for the createMaskFunction property. 194 */ 195 private var _createMaskFunction:Function; 196 197 /** 198 * Function called when the effect creates the mask. 199 * The default value is a function that returns a Rectangle 200 * with the same dimensions as the effect target. 201 * 202 * <p>You can use this property to specify your own callback function to draw the mask. 203 * The function must have the following signature:</p> 204 * 205 * <pre> 206 * public function createLargeMask(targ:Object, bounds:Rectangle):Shape { 207 * var myMask:Shape = new Shape(); 208 * // Create mask. 209 * 210 * return myMask; 211 * } 212 * </pre> 213 * 214 * <p>You set this property to the name of the function, 215 * as the following example shows for the WipeLeft effect:</p> 216 * 217 * <pre> 218 * <mx:WipeLeft id="showWL" createMaskFunction="createLargeMask" showTarget="false"/></pre> 219 */ 220 public function get createMaskFunction():Function 221 { 222 return _createMaskFunction != null ? 223 _createMaskFunction : 224 defaultCreateMask; 225 } 226 227 /** 228 * @private 229 */ 230 public function set createMaskFunction(value:Function):void 231 { 232 _createMaskFunction = value; 233 } 234 235 //---------------------------------- 236 // moveEasingFunction 237 //---------------------------------- 238 239 /** 240 * Easing function to use for moving the mask. 241 */ 242 public var moveEasingFunction:Function; 243 244 //-------------------------------------------------------------------------- 245 // playheadTime 246 //-------------------------------------------------------------------------- 247 248 /** 249 * @private 250 */ 251 override public function get playheadTime():Number 252 { 253 var value:Number; 254 255 if (moveTween) 256 value = moveTween.mx_internal::playheadTime; 257 258 else if (scaleTween) 259 value = scaleTween.mx_internal::playheadTime; 260 261 else 262 return 0; 263 264 return value + super.playheadTime; 265 266 } 267 268 //-------------------------------------------------------------------------- 269 // playReversed 270 //-------------------------------------------------------------------------- 271 272 /** 273 * @private 274 */ 275 override mx_internal function set playReversed(value:Boolean):void 276 { 277 if (moveTween) 278 moveTween.playReversed = value; 279 280 if (scaleTween) 281 scaleTween.playReversed = value; 282 283 super.playReversed = value; 284 } 285 286 //---------------------------------- 287 // scaleEasingFunction 288 //---------------------------------- 289 290 /** 291 * Easing function to use for scaling the mask. 292 */ 293 public var scaleEasingFunction:Function; 294 295 //---------------------------------- 296 // scaleXFrom 297 //---------------------------------- 298 299 /** 300 * Initial scaleX for mask. 301 */ 302 public var scaleXFrom:Number; 303 304 //---------------------------------- 305 // scaleXTo 306 //---------------------------------- 307 308 /** 309 * Ending scaleX for mask. 310 */ 311 public var scaleXTo:Number; 312 313 //---------------------------------- 314 // scaleYFrom 315 //---------------------------------- 316 317 /** 318 * Initial scaleY for mask. 319 */ 320 public var scaleYFrom:Number; 321 322 //---------------------------------- 323 // scaleYTo 324 //---------------------------------- 325 326 /** 327 * Ending scaleY for mask. 328 */ 329 public var scaleYTo:Number; 330 331 //---------------------------------- 332 // showTarget 333 //---------------------------------- 334 335 [Inspectable(category="General", defaultValue="true")] 336 337 /** 338 * @private 339 * Storage for the showTarget property. 340 */ 341 private var _showTarget:Boolean = true; 342 343 /** 344 * @private 345 */ 346 private var _showExplicitlySet:Boolean = false; 347 348 /** 349 * Specifies that the target component is becoming visible, 350 * <code>false</code>, or invisible, <code>true</code>. 351 * 352 * @default true 353 */ 354 public function get showTarget():Boolean 355 { 356 return _showTarget; 357 } 358 359 /** 360 * @private 361 */ 362 public function set showTarget(value:Boolean):void 363 { 364 _showTarget = value; 365 _showExplicitlySet = true; 366 } 367 368 //---------------------------------- 369 // targetArea 370 //---------------------------------- 371 372 /** 373 * The area where the mask is applied on the target. 374 * The dimensions are relative to the target itself. 375 * By default, the area is the entire target and is created like this: 376 * <code>new Rectangle(0, 0, target.width, target.height);</code> 377 */ 378 public var targetArea:Rectangle; 379 380 //---------------------------------- 381 // xFrom 382 //---------------------------------- 383 384 /** 385 * Initial position's x coordinate for mask. 386 */ 387 public var xFrom:Number; 388 389 //---------------------------------- 390 // xTo 391 //---------------------------------- 392 393 /** 394 * Destination position's x coordinate for mask. 395 */ 396 public var xTo:Number; 397 398 //---------------------------------- 399 // yFrom 400 //---------------------------------- 401 402 /** 403 * Initial position's y coordinate for mask. 404 */ 405 public var yFrom:Number; 406 407 //---------------------------------- 408 // yTo 409 //---------------------------------- 410 411 /** 412 * Destination position's y coordinate for mask. 413 */ 414 public var yTo:Number; 415 416 //-------------------------------------------------------------------------- 417 // 418 // Overridden methods 419 // 420 //-------------------------------------------------------------------------- 421 422 /** 423 * @private 424 */ 425 override public function initEffect(event:Event):void 426 { 427 super.initEffect(event); 428 429 switch (event.type) 430 { 431 case "childrenCreationComplete": 432 case FlexEvent.CREATION_COMPLETE: 433 case FlexEvent.SHOW: 434 case Event.ADDED: 435 case "resizeEnd": 436 { 437 showTarget = true; 438 break; 439 } 440 441 case FlexEvent.HIDE: 442 case Event.REMOVED: 443 case "resizeStart": 444 { 445 showTarget = false; 446 break; 447 } 448 case Event.RESIZE: 449 { 450 // don't use the snapshot because it will be the wrong size 451 useSnapshotBounds = false; 452 break; 453 } 454 } 455 } 456 457 /** 458 * @private 459 */ 460 override public function startEffect():void 461 { 462 // Init the mask only once when the effect is played. 463 initMask(); 464 465 // Register to be notified if the target object is resized. 466 target.addEventListener(ResizeEvent.RESIZE, eventHandler); 467 468 // This will call playEffect eventually. 469 super.startEffect(); 470 } 471 472 /** 473 * @private 474 */ 475 override public function play():void 476 { 477 super.play(); 478 479 // This allows the MaskEffect subclass to set the effect properties. 480 initMaskEffect(); 481 482 EffectManager.mx_internal::startVectorEffect(IUIComponent(target)); 483 484 //EffectManager.mx_internal::startBitmapEffect(target); 485 486 // Move Tween 487 488 if (!isNaN(xFrom) && 489 !isNaN(yFrom) && 490 !isNaN(xTo) && 491 !isNaN(yTo)) 492 { 493 tweenCount++; 494 495 moveTween = new Tween(this, [ xFrom, yFrom ], 496 [ xTo, yTo ], duration, 497 -1, onMoveTweenUpdate, onMoveTweenEnd); 498 499 moveTween.playReversed = playReversed; 500 501 // If the caller supplied their own easing equation, override the 502 // one that's baked into Tween. 503 if (moveEasingFunction != null) 504 moveTween.easingFunction = moveEasingFunction; 505 506 507 } 508 509 // Scale Tween 510 511 if (!isNaN(scaleXFrom) && 512 !isNaN(scaleYFrom) && 513 !isNaN(scaleXTo) && 514 !isNaN(scaleYTo)) 515 { 516 tweenCount++; 517 518 scaleTween = new Tween(this, [ scaleXFrom, scaleYFrom ], 519 [ scaleXTo, scaleYTo ], duration, 520 -1, onScaleTweenUpdate, onScaleTweenEnd); 521 522 scaleTween.playReversed = playReversed; 523 524 // If the caller supplied their own easing equation, override the 525 // one that's baked into Tween. 526 if (scaleEasingFunction != null) 527 scaleTween.easingFunction = scaleEasingFunction; 528 } 529 530 dispatchedStartEvent = false; 531 532 // Call these after tween creation so that saveTweenValues knows which values to dispatch 533 if (moveTween) 534 { 535 // Set the animation to the initial value 536 // before the screen refreshes. 537 onMoveTweenUpdate(moveTween.mx_internal::getCurrentValue(0)); 538 } 539 540 if (scaleTween) 541 { 542 // Set the animation to the initial value 543 // before the screen refreshes. 544 onScaleTweenUpdate(scaleTween.mx_internal::getCurrentValue(0)); 545 } 546 } 547 548 /** 549 * Pauses the effect until you call the <code>resume()</code> method. 550 */ 551 override public function pause():void 552 { 553 super.pause(); 554 555 if (moveTween) 556 moveTween.pause(); 557 558 if (scaleTween) 559 scaleTween.pause(); 560 } 561 562 /** 563 * @private 564 */ 565 override public function stop():void 566 { 567 stoppedEarly = true; 568 super.stop(); 569 570 if (moveTween) 571 moveTween.stop(); 572 573 if (scaleTween) 574 scaleTween.stop(); 575 } 576 577 /** 578 * Resumes the effect after it has been paused 579 * by a call to the <code>pause()</code> method. 580 */ 581 override public function resume():void 582 { 583 super.resume(); 584 585 if (moveTween) 586 moveTween.resume(); 587 588 if (scaleTween) 589 scaleTween.resume(); 590 } 591 592 /** 593 * Plays the effect in reverse, 594 * starting from the current position of the effect. 595 */ 596 override public function reverse():void 597 { 598 super.reverse(); 599 600 if (moveTween) 601 moveTween.reverse(); 602 603 if (scaleTween) 604 scaleTween.reverse(); 605 606 super.playReversed = !playReversed; 607 } 608 609 /** 610 * @private 611 */ 612 override public function end():void 613 { 614 stopRepeat = true; 615 616 if (moveTween) 617 moveTween.endTween(); 618 619 if (scaleTween) 620 scaleTween.endTween(); 621 } 622 623 /** 624 * @private 625 */ 626 override public function finishEffect():void 627 { 628 target.removeEventListener(ResizeEvent.RESIZE, eventHandler); 629 630 if (!persistAfterEnd && !stoppedEarly) 631 removeMask(); 632 633 super.finishEffect(); 634 } 635 636 //-------------------------------------------------------------------------- 637 // 638 // Methods 639 // 640 //-------------------------------------------------------------------------- 641 642 /** 643 * @private 644 */ 645 private function initMask():void 646 { 647 if (!effectMask) 648 { 649 if (useSnapshotBounds) 650 targetVisualBounds = getVisibleBounds(DisplayObject(target)); 651 else 652 targetVisualBounds = new Rectangle(0, 0, target.width, target.height); 653 effectMask = createMaskFunction(target, targetVisualBounds); 654 655 // For Containers we need to add the mask 656 // to the "allChildren" collection so it doesn't get 657 // treated as a content child. 658 if (target is Container) 659 target.rawChildren.addChild(effectMask); 660 else 661 target.addChild(effectMask); 662 663 effectMask.name = MASK_NAME; 664 effectMaskRefCount = 0; 665 } 666 667 effectMask.x = 0; 668 effectMask.y = 0; 669 effectMask.alpha = .3; 670 effectMask.visible = false; 671 672 // If this object already had a transparency mask, then save off 673 // the original mask, so that we can restore it when we're done. 674 if (effectMaskRefCount++ == 0) 675 { 676 if (target.mask) 677 origMask = target.mask; 678 679 target.mask = effectMask; 680 681 if (target.scrollRect) 682 { 683 origScrollRect = target.scrollRect; 684 target.scrollRect = null; 685 } 686 } 687 688 invalidateBorder = target is Container && 689 Container(target).border != null && 690 Container(target).border is IInvalidating && 691 DisplayObject(Container(target).border).filters != null; 692 } 693 694 /** 695 * Creates the default mask for the effect. 696 * 697 * @param targ The effect target. 698 * @param bounds The actual visual bounds of the target which includes drop shadows 699 * 700 * @return A Shape object that defines the mask. 701 */ 702 protected function defaultCreateMask(targ:Object, bounds:Rectangle):Shape 703 { 704 // By default, create a mask that is the shape of the target. 705 var targetWidth:Number = bounds.width / Math.abs(targ.scaleX); 706 var targetHeight:Number = bounds.height / Math.abs(targ.scaleY); 707 708 if (targ is SWFLoader) 709 { 710 // Make sure the loader's content has been sized 711 targ.validateDisplayList(); 712 if (targ.content) 713 { 714 targetWidth = targ.contentWidth; 715 targetHeight = targ.contentHeight; 716 } 717 } 718 719 var newMask:Shape = new FlexShape(); 720 721 var g:Graphics = newMask.graphics; 722 g.beginFill(0xFFFF00); 723 g.drawRect(0, 0, targetWidth, targetHeight); 724 g.endFill(); 725 726 if (target.rotation == 0) 727 { 728 newMask.width = targetWidth; 729 newMask.height = targetHeight; 730 } 731 else 732 { 733 var angle:Number = targ.rotation * Math.PI / 180; 734 735 var sin:Number = Math.sin(angle); 736 var cos:Number = Math.cos(angle); 737 738 newMask.width = Math.abs(targetWidth * cos - targetHeight * sin); 739 newMask.height = Math.abs(targetWidth * sin + targetHeight * cos); 740 } 741 742 return newMask; 743 } 744 745 /** 746 * Initializes the <code>move</code> and <code>scale</code> 747 * properties of the effect. 748 * All subclasses should override this function. 749 * Flex calls it after the mask has been created, 750 * but before the tweens are created. 751 */ 752 protected function initMaskEffect():void 753 { 754 if (!_showExplicitlySet && 755 propertyChanges && 756 propertyChanges.start["visible"] !== undefined) 757 { 758 _showTarget = !propertyChanges.start["visible"]; 759 } 760 } 761 762 /** 763 * @private 764 * Returns a rectangle that describes the visible region of the component, including any dropshadows 765 */ 766 private function getVisibleBounds(targ:DisplayObject):Rectangle 767 { 768 var bitmap:BitmapData = new BitmapData(targ.width + 200, targ.height + 200, true, 0x00000000); 769 var m:Matrix = new Matrix(); 770 m.translate(100, 100); 771 bitmap.draw(targ, m); 772 var actualBounds:Rectangle = bitmap.getColorBoundsRect(0xFF000000, 0x00000000, false); 773 774 actualBounds.x = actualBounds.x - 100; 775 actualBounds.y = actualBounds.y - 100; 776 777 bitmap.dispose(); 778 779 if (actualBounds.width < targ.width) 780 { 781 actualBounds.width = targ.width; 782 actualBounds.x = 0; 783 } 784 if (actualBounds.height < targ.height) 785 { 786 actualBounds.height = targ.height; 787 actualBounds.y = 0; 788 } 789 790 return actualBounds; 791 } 792 793 /** 794 * Callback method that is called when the x and y position 795 * of the mask should be updated by the effect. 796 * You do not call this method directly. 797 * This method implements the method of the superclass. 798 * 799 * @param value Contains an interpolated 800 * x and y value for the mask position, where <code>value[0]</code> 801 * contains the new x position of the mask, 802 * and <code>value[1]</code> contains the new y position. 803 */ 804 protected function onMoveTweenUpdate(value:Object):void 805 { 806 saveTweenValue(value,null); 807 808 if (effectMask) 809 { 810 effectMask.x = value[0]; 811 effectMask.y = value[1]; 812 } 813 814 if (invalidateBorder) 815 IInvalidating(Container(target).border).invalidateDisplayList(); 816 } 817 818 /** 819 * Callback method that is called when the x and y position 820 * of the mask should be updated by the effect for the last time. 821 * You do not call this method directly. 822 * This method implements the method of the superclass. 823 * 824 * @param value Contains the final 825 * x and y value for the mask position, where <code>value[0]</code> 826 * contains the x position of the mask, 827 * and <code>value[1]</code> contains the y position. 828 */ 829 protected function onMoveTweenEnd(value:Object):void 830 { 831 onMoveTweenUpdate(value); 832 833 finishTween(); 834 } 835 836 /** 837 * Callback method that is called when the 838 * <code>scaleX</code> and <code>scaleY</code> properties 839 * of the mask should be updated by the effect. 840 * You do not call this method directly. 841 * This method implements the method of the superclass. 842 * 843 * @param value Contains an interpolated 844 * <code>scaleX</code> and <code>scaleY</code> value for the mask, 845 * where <code>value[0]</code> 846 * contains the new <code>scaleX</code> value of the mask, 847 * and <code>value[1]</code> contains the new <code>scaleY</code> value. 848 */ 849 protected function onScaleTweenUpdate(value:Object):void 850 { 851 saveTweenValue(null, value); 852 853 if (effectMask) 854 { 855 effectMask.scaleX = value[0]; 856 effectMask.scaleY = value[1]; 857 } 858 } 859 860 /** 861 * Callback method that is called when the 862 * <code>scaleX</code> and <code>scaleY</code> properties 863 * of the mask should be updated by the effect for the last time. 864 * You do not call this method directly. 865 * This method implements the method of the superclass. 866 * 867 * @param value Contains the final 868 * <code>scaleX</code> and <code>scaleY</code> value for the mask, 869 * where <code>value[0]</code> 870 * contains the <code>scaleX</code> value of the mask, 871 * and <code>value[1]</code> contains the <code>scaleY</code> value. 872 */ 873 protected function onScaleTweenEnd(value:Object):void 874 { 875 onScaleTweenUpdate(value); 876 877 finishTween(); 878 } 879 880 /** 881 * @private 882 */ 883 private function finishTween():void 884 { 885 if (tweenCount == 0 || --tweenCount == 0) 886 { 887 EffectManager.mx_internal::endVectorEffect(IUIComponent(target)); 888 889 var values:Array = []; 890 var value:Object; 891 if (moveTween) 892 { 893 value = moveTween.getCurrentValue(duration); 894 values.push(value[0]); 895 values.push(value[1]); 896 } 897 else 898 { 899 values.push(null); 900 values.push(null); 901 } 902 903 if (scaleTween) 904 { 905 value = scaleTween.getCurrentValue(duration); 906 values.push(value[0]); 907 values.push(value[1]); 908 } 909 else 910 { 911 values.push(null); 912 values.push(null); 913 } 914 915 dispatchEvent(new TweenEvent(TweenEvent.TWEEN_END, false, false, values)); 916 917 finishRepeat(); 918 } 919 } 920 921 /** 922 * @private 923 */ 924 private function removeMask():void 925 { 926 // Although it wasn't the original intended design, it turns out that 927 // two mask effects can play simultaneously inside a <parallel> effect. 928 // The only gotcha is that we shouldn't clear the mask until both 929 // effects are done. The solution: a reference count. 930 if (--effectMaskRefCount == 0) 931 { 932 if (origMask == null || (origMask && origMask.name != MASK_NAME)) 933 target.mask = origMask; 934 935 if (origScrollRect) 936 { 937 target.scrollRect = origScrollRect; 938 } 939 940 if (target is Container) 941 target.rawChildren.removeChild(effectMask); 942 else 943 target.removeChild(effectMask); 944 945 effectMask = null; 946 } 947 } 948 949 /** 950 * @private 951 */ 952 private function saveTweenValue(moveValue:Object, scaleValue:Object):void 953 { 954 if (moveValue != null) 955 { 956 currentMoveTweenValue = moveValue; 957 } 958 else if (scaleValue != null) 959 { 960 currentScaleTweenValue = scaleValue; 961 } 962 963 if ((moveTween == null || currentMoveTweenValue != null) 964 && (scaleTween == null || currentScaleTweenValue != null)) 965 { 966 var values:Array = []; 967 if (currentMoveTweenValue) 968 { 969 values.push(currentMoveTweenValue[0]); 970 values.push(currentMoveTweenValue[1]); 971 } 972 else 973 { 974 values.push(null); 975 values.push(null); 976 } 977 978 if (currentScaleTweenValue) 979 { 980 values.push(currentScaleTweenValue[0]); 981 values.push(currentScaleTweenValue[1]); 982 } 983 else 984 { 985 values.push(null); 986 values.push(null); 987 } 988 989 if (!dispatchedStartEvent) 990 { 991 dispatchEvent(new TweenEvent(TweenEvent.TWEEN_START)); 992 dispatchedStartEvent = true; 993 } 994 995 dispatchEvent(new TweenEvent(TweenEvent.TWEEN_UPDATE, false, false, values)); 996 997 currentMoveTweenValue = null; 998 currentScaleTweenValue = null; 999 } 1000 } 1001 1002 //-------------------------------------------------------------------------- 1003 // 1004 // Overridden event handlers 1005 // 1006 //-------------------------------------------------------------------------- 1007 1008 /** 1009 * @private 1010 */ 1011 override mx_internal function eventHandler(event:Event):void 1012 { 1013 super.eventHandler(event); 1014 1015 // This function is called if the target object is resized. 1016 if (event.type == ResizeEvent.RESIZE) 1017 { 1018 var tween:Tween = moveTween; 1019 if (!tween && scaleTween) 1020 tween = scaleTween; 1021 1022 if (tween) 1023 { 1024 // Remember the amount of the effect that has already been 1025 // played. 1026 var elapsed:Number = getTimer() - tween.mx_internal::startTime; 1027 1028 // Destroy the old tween object. Set its listener to a dummy 1029 // object, so that the onTweenEnd function is not called. 1030 if (moveTween) 1031 Tween.mx_internal::removeTween(moveTween); 1032 1033 if (scaleTween) 1034 Tween.mx_internal::removeTween(scaleTween); 1035 1036 // Reset the tween count 1037 tweenCount = 0; 1038 removeMask(); 1039 1040 // The onTweenEnd function wasn't called, so decrement the 1041 // effectMaskRefCount here to keep it in balance. 1042 //effectMaskRefCount--; 1043 // Restart the effect and create a new mask. This is necessary 1044 // so that the mask's size matches the target object's new size. 1045 initMask(); 1046 play(); 1047 1048 // Set the tween's clock, so that it thinks 'elapsed' 1049 // milliseconds of the animation have already played. 1050 if (moveTween) 1051 { 1052 moveTween.mx_internal::startTime -= elapsed; 1053 // Update the screen before a repaint occurs 1054 moveTween.mx_internal::doInterval(); 1055 } 1056 1057 if (scaleTween) 1058 { 1059 scaleTween.mx_internal::startTime -= elapsed; 1060 // Update the screen before a repaint occurs 1061 scaleTween.mx_internal::doInterval(); 1062 } 1063 } 1064 } 1065 } 1066} 1067 1068} 1069