3 Replies Latest reply on Jul 21, 2009 3:35 PM by Chet Haase

    UIComponent changes cause many updateDisplayList calls

    richardleggettmk

      I'm currently experiencing a bug when using the Flex 4 beta 1 SDK with regards to some UIComponent changes that have been made.

       

      There have been overrides added for many transformation properties in UIComponent, for example "rotationY". Now when I want to animate this property to rotate a component in 3D, it results in a call to invalidateDisplayList in the parent every single frame, and fails to render my view as it rotates, due to the fact it fails to update the screen at all because it appears to call invalidateDisplayList all the way up the visual hierachy so you don't even see rollovers on standard button controls when you mouse over.

       

      Below is some very simplified code that uses the Halo components. This code may look obtuse, but it's designed to mirror my real situation, which is more complex, however it still illustrates the problem.

       

      1. When I compile this with Flex SDK 3.4, I get 1 single trace of "updateDisplayList", and it animates smoothly.

      2. When I compile this with Flex SDK 4 beta 1, I get a trace of "updateDisplayList" every single frame*.

       

      * As you can imagine, in this simple scenario it's not a big problem, but when you consider I'm rotating a fairly complex UI/view, it completely falls over when compiling with Flex 4 as the CPU cannot handle the chain of invalidatations.

       

      I'm trying to figure out whether this is expected behavior. I can't see how I can rotate my view when I switch to compiling with Flex SDK 4?

       

       

      <?xml version="1.0" encoding="utf-8"?>
      <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
          <mx:Script>
              <![CDATA[
                  import mx.controls.Button;
                  import mx.core.UIComponent;
                 
                  private function init():void
                  {
                      var outer:UIComponent = new UIComponent();
                      var inner:UIComponent = new UIComponent();
                      var button:Button = new Button();

       

                      button.label = "Hello World";
                      button.width = 100;
                      button.height = 50;
                     
                      inner.addChild(button);       
                      outer.addChild(inner);
                      addChild(outer);
                         
                      addEventListener(Event.ENTER_FRAME, function(event:Event):void { outer.rotationY++; });
                  }
                 
                  override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
                  {

                     super.updateDisplayList(unscaledWidth, unscaledHeight);
                      trace("updateDisplayList");
                  }
              ]]>
          </mx:Script>
      </mx:Application>

       

      Many thanks,

      Richard

        • 1. Re: UIComponent changes cause many updateDisplayList calls
          Chet Haase Level 3

          Hi Richard,

           

          There are a couple of things going on here, and some other things not happening that you might want to know about:

          - Layouts in Flex 4 are smarter about changes in position and orientation, so component transform property changes will invalidate layout (all the way up the hierarchy) in case the new object position/orientation has any impact on the object's container tree.

          - rotationY changes the transform properties that layouts care about. But there is another structure in Flex 4 called postLayoutTransformOffsets that will affect the transform after layout runs (hence the name 'postLayout'). This means you can change transform properties without kicking off a layout pass because the layout will ignore changes in this structure. It will still cause a call to updateDisplayList on the local container (this is where the final matrix gets recalculated), but it should no longer cause a layout invalidate up the container hierarchy.

          - The new 3D effects in Flex 4 use the postLayout properties by default, so if you use the effects you may get the behavior you're looking for.

          - There's also a flag on the new Flex 4 effects called disableLayout. The default value is false, but if you set it to true, it will tell the container of the animated object to not include it in the layout pass for the duration of the effect. This can help in some situations where you simply want to animate the object without causing layout to run.

           

          Hope that helps.

           

          Chet.

          1 person found this helpful
          • 2. Re: UIComponent changes cause many updateDisplayList calls
            richardleggettmk Level 1

            Hi Chet,

             

            Thanks for this detailed explanation, it really helps clear up some of these migration questions, particularly when combining Halo components with the new improved Spark model.

             

            After posting I continued digging and found Rotate3D working as expected and began to look through the postLayout Transform stuff but didn't quite grasp the entire flow yet. But of course your post describes exactly the situation, I think it'd make for a useful devnet article perhaps for people moving from Flex 3 to 4 like myself.

             

            So if my component extends UIComponent, and previously I would have tweened rotationY, perhaps now I can run a tween and call transformAround() instead (or just use Rotate3D) in order to make use of the postLayoutTransformOffsets mentioned?

             

            I'm just a little worried about migrating projects where these sort of things that worked in Flex 3 would cause the recursive layout calls experienced. I am using compatibility-version=3 so perhaps a clause could be inserted to ignore the new transform changes in UIComponent for backwards compatibility in these cases until the developer can make the necessary changes in all places?

             

            Like many people no doubt, I'm planning to migrate projects when possible in order to make use of new features and improved programming model, for example I'm using some Flex 4 SWCs (the TLF ones), and plan to port to Spark as and when components are available.

             

            Thanks again,

            Richard

            • 3. Re: UIComponent changes cause many updateDisplayList calls
              Chet Haase Level 3

              Hi again,

               

               

              Thanks for this detailed explanation, it really helps clear up some of

              these migration questions, particularly when combining Halo components

              with the new improved Spark model.

               

              After posting I continued digging and found Rotate3D working as

              expected and began to look through the postLayout Transform stuff but

              didn't quite grasp the entire flow yet. But of course your post

              describes exactly the situation, I think it'd make for a useful devnet

              article perhaps for people moving from Flex 3 to 4 like myself.

               

              Could at least be a quick blog post

              Note that the behavior on the 3d effects that determines whether they set the layout or postLayout properties is governed by the effect property applyChangesPostLayout. This flag is true by default for the 3D effects, but false by default for the 2D transform effects (Move, Scale, Rotate).

               

              So if my component extends UIComponent, and previously I would have

              tweened rotationY, perhaps now I can run a tween and call

              transformAround() instead (or just use Rotate3D) in order to make use

              of the postLayoutTransformOffsets mentioned?

              Correct, although I think you'd be better served by just using Rotate3D and letting us figure out the details of transforming around the specified point (center by default, but specifiable if you want to rotate around a different point). At their core, the effect simply animate properties. But in the case of transform effects, they do a lot more to figure out the transform center and call transformAround() appropriately, and also combine in useful ways with other transform effects running in parallel to avoid some of the effect-fighting artifacts of previous versions.

              So use Rotate3D (and the other effects) when you can. Or use Animate if you're just doing raw property rotation. And if you have to go to the level of Animation to animate properties, please let us know why (what in the effects classes didn't suit your purpose?). Animation is certainly there to be used, but it's probably not something that developers would typically call directly.

               

              I'm just a little worried about migrating projects where these sort of

              things that worked in Flex 3 would cause the recursive layout calls

              experienced. I am using compatibility-version=3 so perhaps a clause

              could be inserted to ignore the new transform changes in UIComponent

              for backwards compatibility in these cases until the developer can make

              the necessary changes in all places?

              Not sure how embedded that logic is, but layout code is pretty extensive, so it might not be trivial to make that change. I'll forward the request...

               

               

              Like many people no doubt, I'm planning to migrate projects when

              possible in order to make use of new features and improved programming

              model, for example I'm using some Flex 4 SWCs (the TLF ones), and plan

              to port to Spark as and when components are available.

              Excellent. Let us know when you run into issues.

               

              Thanks,

              Chet.

               

               

              Thanks again,

              Richard

              >