Archive for November, 2008

Resizing papervision3d viewport in Flex

Wednesday, November 12th, 2008

I’ve been spending some time getting PV3D to play nicely in Flex. As others have noted, there aren’t as many tutorials out there for Flex-specific users (although that’s changing by the day).

The bad: you can’t get quick answers. The good: you’re forced to use your brain to figure the little things out, which increases your facility with the library and postpones inevitable decline.

In my case, setting the width and height of the viewport was messing me up. Should be simple right? The application I’m building for my client has a certain screen that allows the user to drag elements from a datagrid into a “comparison window” and get a visual representation.

When the user drops the item, a new component containing my papervision stuff (viewport, camera, etc) is added to the container. The component should a small 3D rendering of the building.

The user drags items from the datagrid to the comparison area (at top)

First mistake: relying on the autoScaleToStage property of the viewport.

I first started by creating a custom mxml component to hold the PV3D building rendering and some labels and such to show important data. The PV3D viewport is created in a function launched soon after the creationComplete event. The autoScaleToStage is the third parameter (Boolean).

viewport = new Viewport3D(this.width, this.height, true, false)

You can see in this shot that my building models aren’t showing up in the custom components (little blue panels) when they are dragged to the comparison area. It turns out the viewport is doing what it was instructed to do, which is size to the stage. The stage size isn’t what we want, we want to size of the UIComponent I’ve placed it in. So the models are there, they’re just behind the gray area.

No papervision models in my components. Very sad.

Second mistake: resizing the actual height and width of viewport

Ok. ok. If I can’t rely on the autoScaleToStage, I’ll just resize the viewport myself when Flex sends resize events to the component. So, I set the third parameter on the viewport creation to false and  added an event handler to my mxml component to catch the resize events. The top of my mxml file looked like this…


and my onResize() function looked like this

private function onResize():void
{
     if (viewport !=null)
     {
          viewport.width = this.width
          viewport.height = this.height
     }
}

(Note: the way my component is set up, the viewport won’t be created when the first onResize is launched. So I check to make sure it exists before resizing)

Unfortunately, this does exactly what I’m telling it to do, which like so many other times isn’t what I want. (”Just do it! Do it!”) The viewport is a flash MovieClip class, and by directly setting it’s width and height, I’m essentially squeezing and distorting the MovieClip’s children. So each time I add a custom component to the UI component that holds them (the black area at the top of the screen), it squeezes the ones already there.

You can see the result here, where the first custom component added (on the left) has gotten progressively squeezed each time I added another…

I'm squeezing the buildings by setting width and height directly

First bright idea of the day: look at the PV3D code

Ok, so let’s just check how the PV3D viewport manages scaling. Searching for the resize function in the Viewport class, we find:

/**
* Resizes the viewport when the stage is resized (if autoScaleToStage == true)
*/
protected function onStageResize(event:Event = null):void
{
     if(_autoScaleToStage)
     {
          viewportWidth = stage.stageWidth;
          viewportHeight = stage.stageHeight;
     }
}

Ah, so there we are. There are special properties called viewportWidth and viewportHeight that control the correct size of the viewport. So I can just set them from my resize function and all should be fine. My onResize() function now looks like this:

private function onResize():void
{
     if (viewport !=null)
    {
        viewport.viewportWidth = this.width
        viewport.viewportHeight = this.height
    }
}

and it does what I want.

It works.

Flex component lifecycle … can you explain that again?

Wednesday, November 12th, 2008

I keep coming back to this again and again. How, exactly, do UI components run through their creation events when they’re placed on the stage? Pre-initialize, initialize, measure, etc. etc.

Each time I go searching for some helpful blogs, find something that helps, and then promptly forget what I learned. So, I’m archiving some of those posts here to make my day happier.

Charting dateTimeAxis offset weirdness

Friday, November 7th, 2008

Hmm. I was stumped this morning for awhile on a charting problem. I’m posting the solution here for others who get stuck in same place.

Your time series graph uses dateTimeGrid, and you’ve set up some dummy data from hours 0 to 24 to make sure it works. Why the heck are the datapoints starting at 7:00 am and not 12:00 AM?

Thanks to Mr. Harker and I’ve removed this obstacle from my life and will now resume my sense of flow:

http://graemeharker.blogspot.com/2007/08/flexs-datatimeaxis-renders-in-gmt-by.html

Essentially, you have to set displayLocalTime attribute in the dateTimeAxis to true. When you create dates, they’re created as local time, but when you chart them they’re rendered as UTC. Hence (from Santa Cruz), the seven hour gap of strangeness.