How to integrate 3D Sandy objects into Flex

This small demo shows you how you can integrate Sandy objects into a Flex application. Actually, it’s quite simple. All you need to do is create a UIComponent and use the addChild() method with your Sandy Sprite. This demo takes it a tiny bit further and shows you how you can communicate between a 3D object and a Flex component. In order to illustrate this in the most basic way (without too much code clutter), a native Sandy Box object and a simple Flex component (TextInput) are used. When you click on a Sandy Box primitive, a custom event is triggered and handled in the main Flex application MXML. This custom event has a property called “which” and is used to store the name of the Shape3D object that’s been clicked on.

Here are all the code files that make this happen + explanations:

SandyFlex.mxml - The main Flex application File


<?xml version="1.0" encoding="utf-8"?>
<mx:Application
	xmlns:mx="http://www.adobe.com/2006/mxml"
	applicationComplete="addSandySprite()"
	width="400"
	height="300"
	layout="vertical"
	paddingTop="0"
	paddingRight="0"
	paddingBottom="0"
	paddingLeft="0">
<mx:Script>
<![CDATA[
			/**
			 * Add the Sandy object (Boxes) to the UIComponent.
			 *
			 */
			private function addSandySprite():void
			{
				var boxes:Boxes = new Boxes();
				boxes.addEventListener( BoxEvent.CLICKED, boxClickedHandler );
				spriteContainer.addChild( boxes );
			}

			/**
			 * The event handler for the Sandy object's click
			 * event.
			 *
			 * @see BoxEvent
			 *
			 */
			private function boxClickedHandler( event:BoxEvent ):void
			{
				textBox.text = "The " + event.which + " was clicked";
			}
		]]>
</mx:Script>
<mx:UIComponent id="spriteContainer" width="360" height="200" />
<mx:TextInput id="textBox" />
</mx:Application>

BoxEvent.as - The custom event


package
{
	import flash.events.Event;

	/**
	 * BoxEvent.as - Custom event which is dispatched from the Boxes class. In
	 * this case, it is used to pass the name of the object that's been clicked on.
	 *
	 * 26 September 2007
	 * @author Dennis Ippel - http://www.rozengain.com
	 *
	 */

	public class BoxEvent extends Event
	{
		/**
		 * The event type
		 */
		public static const CLICKED:String = "clicked";
		/**
		 * This is used to store the name of the object that's been clicked on.
		 */
		public var which:String;

		/**
		 * BoxEvent constructor. Nothing special here :-)
		 * @param type
		 * @param bubbles
		 * @param cancelable
		 *
		 */
		public function BoxEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
		{
			super(type, bubbles, cancelable);
		}
	}
}

Boxes.as - The Sandy Scene3D with Box primitives


package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.GlowFilter;

	import sandy.core.Scene3D;
	import sandy.core.scenegraph.Camera3D;
	import sandy.core.scenegraph.Group;
	import sandy.core.scenegraph.Shape3D;
	import sandy.materials.Appearance;
	import sandy.materials.ColorMaterial;
	import sandy.materials.attributes.LightAttributes;
	import sandy.materials.attributes.MaterialAttributes;
	import sandy.primitive.Box;

	/**
	 * Boxes.as
	 * 26 September 2007
	 * @author Dennis Ippel - http://www.rozengain.com
	 *
	 */

	[Event( name="clicked", type="sandydemo.BoxEvent" )]

	public class Boxes extends Sprite
	{
		private var scene:Scene3D;
		private var selectedMenuItem:Shape3D;
		private var box1:Box;
		private var box2:Box;
		private var box3:Box;	

		public function Boxes()
		{
			init();
		}

		private function init():void
		{
			// -- configure the camera, move it upwards a little
			var camera:Camera3D = new Camera3D( 400, 200 );
			camera.y = 25;
			camera.z = -150;
			camera.lookAt( 0, 0, 0 );

			// -- creat the root group and the scene
			var root:Group = new Group( "root" );
			scene = new Scene3D( "scene", this, camera, root );

			// -- box 1
			box1 = new Box( "red box", 40, 40, 40 );
			configureBox( box1, 0xff0000, -50, -25 );

			// -- box 2
			box2 = new Box( "yellow box", 40, 40, 40 );
			configureBox( box2, 0xffff00, 0, -25 );

			// -- box 3
			box3 = new Box( "green box", 40, 40, 40 );
			configureBox( box3, 0x00ff00, 50, -25 );		

			scene.render();
		}

		/**
		 * The handler for the mouse over event
		 * @param event
		 *
		 */
		private function mouseOverHandler( event:MouseEvent ):void
		{
			// -- get the target container. The event handler
			//    was attached to the Shape3D's container. Here
			//    we use it again to apply a filter
			var container:Sprite = event.target as Sprite;
			// -- apply a glow filter to the container
			container.filters = [
				new GlowFilter( 0xffffff, 1, 12, 12 )
			];
		}

		/**
		 * The handler for the mouse out event
		 * @param event
		 *
		 */
		private function mouseOutHandler( event:MouseEvent ):void
		{
			// -- get the target container. The event handler
			//    was attached to the Shape3D's container. Here
			//    we use it again to remove a filter
			var container:Sprite = event.target as Sprite;
			container.filters = [];
		}

		/**
		 * The handler for the mouse click event
		 * @param event
		 *
		 */
		private function clickHandler( event:MouseEvent ):void
		{
			// -- get the target container.
			var container:Sprite = event.target as Sprite;

			// -- get the Shape3D this container is in
			var currentShape:Shape3D = getShape3DByContainer( container );

			var boxEvent:BoxEvent = new BoxEvent( BoxEvent.CLICKED );
			boxEvent.which = currentShape.name;

			dispatchEvent( boxEvent );
		}

		/**
		 * Compares the given container Sprite to all the container Sprites
		 * in the scene.
		 * @param container
		 * @return
		 *
		 */
		private function getShape3DByContainer( container:Sprite ):Shape3D
		{
			for each( var shape:Object in scene.root.children )
				if( shape is Shape3D && shape.container == container )
					return shape as Shape3D;

			return null;
		}

		/**
		 * Adds standard properties to the items
		 * @param item
		 * @param color
		 * @param x
		 * @param y
		 *
		 */
		private function configureBox( item:Shape3D, color:uint, x:int, y:int ):void
		{
			// -- appearance / material properties
			var mattAttr:MaterialAttributes = new MaterialAttributes(
				new LightAttributes( false, 0.3 )
			);

			item.appearance = new Appearance(
				new ColorMaterial( color, 100, mattAttr )
			);
			item.appearance.frontMaterial.lightingEnable = true;

			// -- position
			item.x = x;
			item.y = y;

			// -- add event listeners to this Shape3D's container. The
			//    container is a Sprite, native to Flash
			item.container.addEventListener( MouseEvent.MOUSE_OVER, mouseOverHandler );
			item.container.addEventListener( MouseEvent.MOUSE_OUT, mouseOutHandler );
			item.container.addEventListener( MouseEvent.CLICK, clickHandler );
			item.container.useHandCursor = true;
			item.container.buttonMode = true;

			// -- add this Shape3D to the scene
			scene.root.addChild( item );
		}
	}
}

Download these files


About this entry