3D, , , " />

FlashPlatformist
Articles, Information, News, & Tutorials for Adobe Flash Platform Developers and Architects

3D UI Development – The Bleeding Edge of RIA

I’ve recently been learning a few new programs, particularly Cinema 4D and Swift 3D, in tandem with Apple Motion and Adobe After Effects CS4. I was already a pretty crafty dude with After Effects, but I had never even tapped into a fraction of what it was capable of since there is a bit of a learning curve there.

The thought came to me today as to why I have spent so much time on 3D with ActionScript when doing 3D with these tools is so much easier? My next thought was of course, the obvious answer…These 3D movies I’m making using far superior tools (for 3D design) are static in nature. These movies are quite cool to watch and fun to make, but they lack the 2 things that make ActionScript 3D so intriguing: 1) user interactivity (the thing that makes games so addicting for the “gamer” community), and 2) the ability to make the content dynamically driven by data on a server hundreds or thousands of miles away.

There are a few “blocking points” though that we developers who consider ourselves “the bleeding edge of RIA” still need to address. First, although Flash 10 has undergone substantial improvement for 3D rendering, the code required to produce 3D user interfaces is still complicated and buggy, and it is still not true 3D. The vector-based image sequences deliver the illusion of 3D through the use of carefully placed masks, shadows, gradients, and the relational sizing of objects. This is an incredibly resource intensive process from a hardware standpoint. There is a reason that almost all PC games are still developed using C++, which is the fact that the language gives you direct access to the computer’s hardware and allows the application to make decisions in the way that the interface is displayed based on the hardware resources that are available to it.

By its very nature, the Flash VM is resource-intensive to begin with for the simple fact that it is a virtual machine (the advantage being portability between platforms). This should sound quite familiar to Java enterprise developers, who also sacrifice resources for the advantage of portability. In the enterprise, the answer is always simply “throw more hardware at it” if things start slowing down. In the consumer market however, we face a different predicament developing mainstream 3D interfaces in – say – Adobe AIR. The answer there is not as simple as throwing more hardware at it because A) few consumers know what to get or how to install it, B) computer and hardware vendors purposely limit the upgrade path of computers in the consumer market, and C) this is a terrible idea to begin with and the wrong way to look things. The answer should instead be a matter of making companies like Adobe find ways to make their software more efficient… For example, change the properties of AIR to compile like C++ does instead of the Flash VM. Unfortunately, this is not cost-effective for Adobe or even logical for them at this point, which puts the problem back in the developer’s hands, especially for framework creators like the PaperVision 3D team.

…just food for thought.

Possibly Related Posts:



Posted by Dan Orlando on January 31st, 2009 :: Filed under General, User Experience
Tags :: , , ,

Simple Papervision3D

Add Animated Transitions and Custom Navigation to Your Flex Viewstack Components

One of my biggest issues with the Flex Viewstack element is the lack of built-in transitions to choose from. So in this demonstration, I will show you how to create your own. We will first create a reusable animation factory class that we can call from anywhere in our application. Then, I will demonstrate how we can put the animation factory to work by creating a slide transition for a viewstack component. Note that Flex has a built in Slide object, and if you don’t mind mixing up your ActionScript behaviors with your MXML display, then that is also a viable option worth looking into for accomplishing the same end result. Just like anything you’ll find on this site though, we want to build abstraction and reusability into our code.

Step 1: Create the Animation Factory

Our first step is to create the animation factory class. We can instantiate this object from anywhere in an application and call the animateTo method, passing it the x, y position that we want it to end at, and the duration in milliseconds that we want the animation to last.

ObjectSlider.as

package {

   import flash.display.DisplayObject;
   import flash.events.Event;
   import flash.events.TimerEvent;
   import flash.utils.Timer;
   import flash.utils.getTimer;

   /**
    * @author Dan Orlando
    */
   public class ObjectSlider
   {
        // The object being animated
	private var _target:DisplayObject;
	 // Each time an animation starts we record its start time
	private var _startTime:Number;
	 // The duration of the animation in milliseconds
	private var _duration:Number;
	 // Record the target's start position
	private var _startX:Number;
	private var _startY:Number;
	 //  Record the difference between the starting and ending positions
	private var _deltaX:Number;
	private var _deltaY:Number;

	public function ObjectSlider() { }

   // Starts an animation that moves the target object from its current
   // position to the specified new position over a specified period of time.
	public function animateTo(target:DisplayObject, toX:Number,
           toY:Number, duration:Number):void {
	   //store where the target was when the animation started
	   _target = target;
	   _startX = _target.x;
	   _startY = _target.y;
	   // calculate difference between target's start position
           // and final destination
	   _deltaX = toX - _target.x;
	   _deltaY = toY - _target.y;
	   _startTime = getTimer();
	   //store how long the animation should take
	   this._duration = duration;
	   //update target's position each time a screen update occurs
	   _target.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
	}

   // Updates the target's position on each ENTER_FRAME event
	private function enterFrameHandler(event:Event):void {
	   var elapsed:Number = getTimer()- _startTime;
	   var percentDone:Number = elapsed/_duration;
	   if (percentDone < 1) {
	      updatePosition(percentDone);
	   }
	   else {
	      updatePosition(1);
	      _target.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
	   }
	}

   // Sets the position of the target object
	private function updatePosition(percentDone:Number):void {
	   _target.x = _startX + (_deltaX * percentDone);
	   _target.y = _startY + (_deltaY * percentDone);
	}

   }
}

Step 2: Create the MXML component
For our MXML display component, we will create a simple canvas that initializes a “helper” class that contains all of the behavior and functionality for the component in ActionScript. Note that when we instantiate the helper class, we pass it the current instance of our canvas component as a display object argument using the this keyword. We also place two left and right arrow buttons here, which we will use to move the viewstack back and forward by changing the selectedIndex value of the ViewStack when one of the buttons is clicked.

CustomCanvas.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="750" height="550"
   creationComplete="init()">
   <mx:Script>
      <![CDATA[
      import com.danorlando.util.ViewStackHelper;

      private var _helper:ViewStackHelper;

      private function init():void {
         _helper = new ViewStackHelper(this);
      }
      ]]>
   </mx:Script>

// place additional mxml components that should not be part
// of the viewstack here, like buttons, labels, etc...
   <mx:HBox x="693" y="56" horizontalGap="5">
      <mx:Button x="64" y="13" id="backBtn" styleName="iconButtonBack"
         width="16" height="16"/>
      <mx:Button x="85" y="13" id="forwardBtn" styleName="iconButtonForward"
         width="16" height="16"/>
   </mx:HBox>
</mx:Canvas>

ViewStackHelper.as

package com.danorlando.util
{
   import com.danorlando.display.components.CustomCanvas;
   import com.danorlando.effects.animation.ObjectSlider;
   import flash.display.DisplayObject;
   import flash.events.MouseEvent;
   import mx.containers.ViewStack;

   public class ViewStackHelper
   {
      private var _parent:CustomCanvas;
      private var _viewStack:ViewStack;
      private var _currentIndex:Number;
      private var _slider:ObjectSlider = new ObjectSlider();

      public function ViewStackHelper(canvas:Canvas) {
            _parent = object;
            addListeners();
            createChildren();
      }

   // add event listeners to the forward and back buttons
      public function addListeners():void {
       _parent.backBtn.addEventListener(MouseEvent.CLICK, viewStackBack);
       _parent.forwardBtn.addEventListener(MouseEvent.CLICK, viewStackForward);
      }

   // create and add the viewstack and it's children
      public function createChildren():void {
         _viewStack = new ViewStack();
         _parent.addChild(_viewStack);
         _viewStack.selectedIndex = 0;
         _viewStack.x = 39;
         _viewStack.y = 72;
         _viewStack.width = 675;
         _viewStack.height = 402;
         var vsChild1:Canvas = new Canvas();
         _viewStack.addChild(vsChild1);
      // add other components and params to the 1st index/child here
         var vsChild2:Canvas = new Canvas();
         _viewStack.addChild(vsChild2);
      // add additional components and params to the 2nd index/child here
         var vsChild3:Canvas = new Canvas();
         _viewStack.addChild(vsChild3);
      // add additional components and params to the 3rd index/child here
      // get the first child that is about to be displayed in the viewstack
         var curChild:DisplayObject = _viewStack.getChildAt(_currentIndex);
      // set the x-position of the child to the x-pos of the viewstack + 600
         curChild.x = _viewStack.x + 600;
      // now slide the child into view
         _slider.animateTo(curChild, _viewStack.x-40, 0, 500);
      }

   // event handler for the back button in the parent container
      private function  viewStackBack(event:Event):void {
         if(_currentIndex > 0) {
            _currentIndex = _currentIndex - 1;
            var newChild:DisplayObject = _viewStack.getChildAt(_currentIndex);
         // set the x-position of the new child 600 pixels to the right
            newChild.x = _viewStack.x + 600;
         // use the animateTo method of our animation factory to slide the new
         // child into position
            _slider.animateTo(newChild, _viewStack.x-40, 0, 500);
         // set the new index
            _viewStack.selectedIndex = _currentIndex;
         // set the forward button to visible if it is hidden
            if (!_parent.forwardBtn.visible) {
               _parent.forwardBtn.visible = true
            }
         // if the _currentIndex property is 0, then hide the back button
            if (_currentIndex == 0) {
                _parent.backBtn.visible = false;
            }
         }
      }

   // event handler for the forward button
      private function viewStackForward(event:Event):void {
         // get the highest index value of the viewstack
         var lastIdx:Number = _viewStack.numChildren-1;
         if(_currentIndex < lastIdx) {
            _currentIndex = _currentIndex + 1;
            var newChild:DisplayObject = _viewStack.getChildAt(_currentIndex);
          // place the incoming child 600px to the left
            newChild.x = _viewStack.x - 600;
          // slide the new child into position using our animation factory
            _slider.animateTo(newFaq, _viewStack.x-40, 0, 500);
          // set the new index of the viewstack
            _viewStack.selectedIndex = _currentIndex;
          // make the back button visible if it is hidden
            if(!_parent.backBtn.visible) {
               _parent.backBtn.visible = true }
          // hide the forward button if we are at the last index
            if (_currentIndex == lastIdx) {
               _parent.forwardBtn.visible = false;
            }
         }
      }

   }
}

Ok, so we’ve got a few things going on here in the helper class. The first thing we do is set the Canvas object that was passed in the constructor to our local (i.e. private) canvas property which is of type CustomCanvas. We then add the event listeners to the forward and back buttons of the parent container – which is the Canvas object that was passed in the constructor – with the addListeners method. We then instantiate the ViewStack and add its children with the createChildren method. You will see the use of our animation factory with the call to _slider.animateTo. Notice that we are initially setting the position of the child off to the left or the right, depending on which button was clicked, then we slide the child into place. Lastly, in order to ensure that we never get a runtime error because the forward button was clicked when we were already viewing the last child, or the back button was clicked when we were already on the first child, we simply set the visible property to false for the respective button based on said conditions.

Possibly Related Posts:



Posted by Dan Orlando on October 14th, 2008 :: Filed under Tutorials, User Experience
Tags :: , , , , , , , ,

MXML vs. Actionscript

I had an interesting conversation this morning with a colleague, who is also a Flex/Actionscript developer, about how we end up using very little MXML when building enterprise level RIA applications. That’s not to say that we don’t leverage the classes that are encapsulated inside of the flex framework, but there is no question that 90% of our code is written in Actionscript. The other 10% are simple MXML files that have no purpose other than to instantiate our Actionscript components on the stage. I think as the Flex developer grows, evolution has it that he or she would move toward the use of Actionscript more than MXML.

A comment I made during this converstaion was that Flex/MXML was great for building little RIA “widgets” that use the built in flex components, which can all be skinned to your heart’s desire. However, it is definitely not well-suited for enterprise level RIA applications because there is too much flexibility (pardon the pun), where we often see programmers literally taking a framework (flex) and language (actionscript 3) that essentially forces you into some form of an object-oriented design, then flipping it on its back to where we see these mxml files that are reminiscent of procedural programming, complete with plenty of inline Actionscript and random switches from mxml to straight Actionscript and back again. This tends to be mostly due to a lack of knowledge on using events and multiple design patterns in a larger application, which takes a while to pick up.

Don’t get me wrong, Flex Builder is definitely the tool of choice for coding RIA applications, but I think the general rule of thumb is that any application that is more than just a “widget”, is going to end up about 80% – 90% Actionscript files and 10% – 20% MXML files. That’s a good way to tell right off the bat if an application is using abstraction and encapsulation of the client-side business logic and behavior versus strictly display. I’ll get more into layering applications in a later blog. For now, here are a few books worth taking a look at if you’re a flex developer on a journey toward learning how to build large-scale RIA apps. All books I recommend are from my personal collection, and I never recommend a book that I haven’t read in its entirety. In other words, I’m not trying to make some cash off an Amazon affiliate program here.

There aren’t too many out there yet on more advanced subjects in Actionscript 3.0, but these 3 will surely help you take it to the next level. Note that the first one I am listing, I attribute some of my most valuable learning to this book and I strongly recommend it to any Actionscript developer aspiring to be an expert at their trade:

AdvancED Flex Application Development; Building Rich Media X
Authors: R Blank, Hasan Otuome, Omar Gonzalez, Chris Charlton
Publisher: Friends of ED
Amazon Link

Actionscript 3.0 Design Patterns
Authors: William Sanders, Chandima Cumaranatunge
Publisher: O’Reilly Media
Amazon Link

Object-Oriented ActionScript 3.0
Authors: Peter Elst, Sas Jacobs, Todd Yard
Publisher: Friends of ED
Amazon Link

Possibly Related Posts:



Posted by Dan Orlando on September 29th, 2008 :: Filed under General
Tags :: , , , , , , , ,