Hi there,
yesterday I ran into a problem which gave me some headaches. I had a sprite that was added as a transform item to the TransformManager. Everything worked fine so far until I added a rotationY to the entire sprite. This caused the TransformManager to throw a whole bunch of errors regarding the Matrix of the sprite. After doing some debugging I realised that the Matrix of the sprite became null as soon as the rotationY property was set.
So I tried out some possible solution which all failed. Even if the rotationY property was set to 0, the errors occured. I figured out two solutions:
1. saving the properties of the sprite on selection and resetting the Matrix like this:
private function ontransformselect(e:TransformEvent):void
{
var sp:Sprite = TransformItem(e.target).targetObject as Sprite;
if (e.type == TransformEvent.SELECT)
{
var _x:Number = sp.x;
var _y:Number = sp.y;
var _scalex:Number = sp.scaleX;
var _scaley:Number = sp.scaleY;
var _rot:Number = sp.rotation;
sp.transform.matrix3D = null;
sp.x = _x;
sp.y = _y
sp.scaleX = _scaleX;
sp.scaleY = _scaleY;
sp.rotation = _rot;
}
else
{
sp.rotationY = -30;
}
}
Although this will work it removes the 3D-rotation of the object while it is selected what I didn't want. So I tested some other things and came up with a rather simple solution. If you wrap a container sprite around the transform object and apply the 3D-rotation to this container, the TransformManager will work just fine in 3D.
If you'd like to try it yourself, here's the code I used. It let's you choose an image from your harddrive, that is loaded into the container and mask. The masking is removed if the object is selected for transformation and reapplied afterwards.
package
{
import com.greensock.events.TransformEvent;
import com.greensock.transform.TransformItem;
import com.greensock.transform.TransformManager;
import flash.display.Bitmap;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
/**
* ...
* @author Reinhart Redel
*/
public class TransformManagerWith3DContainer extends Sprite
{
private var _fref:FileReference; // needed to load local files
private var _bmp:Bitmap; // bitmap representation of loaded image
private var _browse:Sprite; // this is going to be the button to browse for an image
private var _imgLoader:Loader; // the loader for the image
private var _manager:TransformManager;
private var _3DImage:Sprite; // the root-container for the 3D-stuff
private var _3DImagecontainer:Sprite; // this is where the whole stuff will go
private var _3DImagemask:Sprite; // the mask which is applied to the 3D-Image
private var _3DImagebounds:Sprite; // just a helper which shows the bounds of the image after it is masked.
private const _3D_IMG_WIDTH:Number = 300;
private const _3D_IMG_HEIGHT:Number = 300;
public function TransformManagerWith3DContainer():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_imgLoader = new Loader();
// create and add the entire holder //
_3DImage = new Sprite();
_3DImage.x = _3DImage.y = 150;
_3DImage.rotationY = -30;
addChild(_3DImage);
// create and add the entire image container //
_3DImagecontainer = new Sprite();
_3DImage.addChild(_3DImagecontainer);
// create and add masking tho the _3DImagecontainer //
_3DImagemask = new Sprite();
_3DImagemask.graphics.beginFill(0,.25);
_3DImagemask.graphics.drawRect(0, 0, _3D_IMG_WIDTH, _3D_IMG_HEIGHT);
_3DImagemask.graphics.endFill();
_3DImagemask.mouseEnabled = false;
_3DImagemask.visible = false;
_3DImage.addChild(_3DImagemask);
_3DImagecontainer.mask = _3DImagemask;
// create boundary box //
_3DImagebounds = new Sprite();
_3DImagebounds.x = _3DImagebounds.y = 150;
_3DImagebounds.graphics.beginFill(0, 0);
_3DImagebounds.graphics.lineStyle(1);
_3DImagebounds.graphics.drawRect(0, 0, _3D_IMG_WIDTH, _3D_IMG_HEIGHT);
_3DImagebounds.graphics.endFill();
_3DImagebounds.mouseEnabled = false;
_3DImagebounds.rotationY = -30;
addChild(_3DImagebounds);
// create browse button //
_browse = new Sprite();
_browse.graphics.lineStyle(1);
_browse.graphics.beginFill(0xCCCCCC);
_browse.graphics.drawRect(0, 0, 25, 25);
_browse.graphics.endFill();
_browse.x = 125;
_browse.y = 150;
_browse.buttonMode = true;
addChild(_browse);
// create help message //
var tf:TextField = new TextField();
tf.width = 200;
tf.multiline = true;
tf.wordWrap = true;
tf.autoSize = TextFieldAutoSize.LEFT;
tf.x = 550;
tf.y = 25;
tf.htmlText = "FlashPlayer 10 required!\n\nClick the button on the left of the rectangle to choose an image on your harddrive.\n\nClick on the image to move, scale or rotate it.\n\nClick somewhere outside of the image bounds to see how it will look like.";
addChild(tf);
// initiate TransformManager //
_manager = new TransformManager();
_manager.constrainScale = true;
_manager.forceSelectionToFront = false;
var tItem:TransformItem = _manager.addItem(_3DImagecontainer);
tItem.addEventListener(TransformEvent.SELECT, ontransformselect);
tItem.addEventListener(TransformEvent.DESELECT, ontransformselect);
_browse.addEventListener(MouseEvent.CLICK, browsefiles);
}
private function ontransformselect(e:TransformEvent):void
{
if (e.type == TransformEvent.SELECT)
{
_3DImagecontainer.mask = null;
}
else
{
_3DImagecontainer.mask = _3DImagemask;
}
}
private function browsefiles(e:MouseEvent):void
{
_fref = new FileReference();
var _fileFilter:FileFilter = new FileFilter ( "Images (JPG, GIF, PNG)", "*.jpg;*.gif;*.png;" ) ;
_fref.browse([_fileFilter]);
_fref.addEventListener(Event.SELECT, loadimage);
}
private function loadimage(e:Event):void
{
_fref.removeEventListener(Event.SELECT, loadimage);
_fref.addEventListener(Event.COMPLETE, showpreview);
_fref.load();
}
private function showpreview(e:Event):void
{
_fref.removeEventListener(Event.COMPLETE, showpreview);
_imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, resizeloader);
_imgLoader.loadBytes(_fref.data);
}
private function resizeloader(e:Event):void
{
_imgLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, resizeloader);
if (_bmp)
{
_bmp.bitmapData.dispose();
_3DImagecontainer.removeChild(_bmp);
_3DImagecontainer.x = _3DImagecontainer.y = _3DImagecontainer.rotation = 0;
_3DImagecontainer.scaleX = _3DImagecontainer.scaleY = 1;
}
_bmp = Bitmap(e.target.content);
_bmp.smoothing = true;
_imgLoader.unload();
_bmp.width = _3D_IMG_WIDTH;
_bmp.scaleY = _bmp.scaleX;
if (_bmp.height > _3D_IMG_HEIGHT)
{
_bmp.height = _3D_IMG_HEIGHT;
_bmp.scaleX = _bmp.scaleY;
}
_3DImagecontainer.addChild(_bmp);
}
}
}
Hope this helps someone who runs into the same problem.
Cheers
Reinhart