 	private static const RADIANS_PER_DEGREES:Number = Math.PI / 180;
 
 	private static const ZERO_REPLACEMENT_IN_3D:Number = .00000000000001;
+	
+	private static var tempTransformCenter:Vector3D;
 	
 	//------------------------------------------------------------------------------
 	

						

	/**
	 * @private
	 * call when you're about to change the transform, and when complete you want to keep a particular point fixed in its parent coordinate space.
	 */
	public function prepareForTransformCenterAdjustment(affectLayout:Boolean,propertyIs3D:Boolean,tx:Number = NaN,ty:Number = NaN,tz:Number = NaN):Object
	{
		var computedCenterV:Vector3D;
		var computedCenterP:Point;
		var token:Object = {};
		
		if(isNaN(tx))
			tx = layout.transformX;
		if(isNaN(ty))
			ty = layout.transformY;
		if(isNaN(tz))
			tz = layout.transformZ;
				
		var needAdjustment:Boolean = (tx != 0 || ty != 0 || tz != 0);
		
		if(needAdjustment == false)
		{
			return null;		
		}

		if (is3D || propertyIs3D) 
		{
			var centerV:Vector3D = new Vector3D(tx,ty,tz);
			if(affectLayout)
			{
				var layoutCenterV:Vector3D = layoutMatrix3D.transformVector(centerV);
				layoutCenterV.project();
				token.layout = layoutCenterV;
			} 
			
			if(_offsets != null)
			{			
				computedCenterV = computedMatrix3D.transformVector(centerV);
				computedCenterV.project();
				token.offset = computedCenterV;
			}
			token.center = centerV;
		}
		else
		{
			var centerP:Point = new Point(tx,ty);
			if(affectLayout)
				token.layout = layoutMatrix.transformPoint(centerP);

			if(_offsets != null)
				token.offset = computedMatrix.transformPoint(centerP);
			token.center = centerP;
		}
		return token;
	}

	/**
	 * @private
	 * call when you've changed the inputs to the computed transform to make any adjustments to keep a particular point fixed in parent coordinates.
	 */
	public function completeTransformCenterAdjustment(token:Object,changeIs3D:Boolean):void
	{
		if(token == null)
			return;
			
		var computedCenterV:Vector3D;
		var computedCenterP:Point;
		var layoutCenterV:Vector3D;
		var layoutCenterP:Point;
		
		if(is3D || changeIs3D)
		{
			var centerV:Vector3D = token.center;
			computedCenterV = token.offset;
			layoutCenterV = token.layout;
			if(layoutCenterV != null)
			{
				var adjustedLayoutCenterV:Vector3D = layoutMatrix3D.transformVector(centerV);
				adjustedLayoutCenterV.project();
				if(adjustedLayoutCenterV.equals(layoutCenterV) == false)
				{
					layout.translateBy(layoutCenterV.x - adjustedLayoutCenterV.x,
								layoutCenterV.y - adjustedLayoutCenterV.y,	
								layoutCenterV.z - adjustedLayoutCenterV.z
								);
					invalidate(); 
				}		
			}
			if(computedCenterV != null)
			{
				var adjustedComputedCenterV:Vector3D = computedMatrix3D.transformVector(centerV);
				adjustedComputedCenterV.project();
				if(adjustedComputedCenterV.equals(computedCenterV) == false)
				{
					offsets.x +=computedCenterV.x - adjustedComputedCenterV.x;
					offsets.y += computedCenterV.y - adjustedComputedCenterV.y;
					offsets.z += computedCenterV.z - adjustedComputedCenterV.z;
					invalidate(); 
				}		
			}
		}
		else
		{
			var centerP:Point = token.center;
			computedCenterP = token.offset;
			layoutCenterP = token.layout;
			if(layoutCenterP != null)
			{
				var adjustedLayoutCenterP:Point = layoutMatrix.transformPoint(centerP);
				if(adjustedLayoutCenterP.equals(layoutCenterP) == false)
				{
					layout.translateBy(layoutCenterP.x - adjustedLayoutCenterP.x,
								layoutCenterP.y - adjustedLayoutCenterP.y,
								0
								);
					invalidate(); 
				}		
			}
			
			if(computedCenterP != null)
			{			
				var adjustedComputedCenterP:Point = computedMatrix.transformPoint(centerP);
				if(adjustedComputedCenterP.equals(computedCenterP) == false)
				{
					_offsets.x += computedCenterP.x - adjustedComputedCenterP.x;
				    _offsets.y += computedCenterP.y - adjustedComputedCenterP.y;
					invalidate(); 
				}		
			}
		}
	}	
	
	/**
	 * A utility method to update the rotation and scale of the transform while keeping a particular point, specified in the component's own coordinate space, 
	 * fixed in the parent's coordinate space.  This function will assign the rotation and scale values provided, then update the x/y/z properties
	 * as necessary to keep tx/ty/tz fixed.
	 * @param rx,ry,rz the new values for the rotation of the transform
	 * @param sx,sy,sz the new values for the scale of the transform
	 * @param tx,ty,tz the point, in the component's own coordinates, to keep fixed relative to its parent.
	 * affectLayout: whether the rotation and scale should be applied to the layout transform or the offsets.  Note that the offsets might be updated
	 * even when the new values are being applied to the layout.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function transformAround(rx:Number,ry:Number,rz:Number,sx:Number,sy:Number,sz:Number,tx:Number,ty:Number,tz:Number,affectLayout:Boolean = true):void
	{
		var is3D:Boolean = ((!isNaN(rx) && rx != 0) || (!isNaN(ry) && ry != 0) || (!isNaN(sz) && sz != 1));
		
		var token:Object = prepareForTransformCenterAdjustment(affectLayout,is3D,tx,ty,tz);
		if(affectLayout)
		{
			if(!isNaN(rx))
				layout.rotationX = rx;
			if(!isNaN(ry))
				layout.rotationY = ry;
			if(!isNaN(rz))
				layout.rotationZ = rz;
			if(!isNaN(sx))
				layout.scaleX = sx;
			if(!isNaN(sx))
				layout.scaleY = sy;
			if(!isNaN(sz))
				layout.scaleZ = sz;			
		}
		else
		{
			if(_offsets == null)
				offsets = new TransformOffsets();
				
			if(!isNaN(rx))
				_offsets.rotationX = rx;
			if(!isNaN(ry))
				_offsets.rotationY = ry;
			if(!isNaN(rz))
				_offsets.rotationZ = rz;
			if(!isNaN(sx))
				_offsets.scaleX = sx;
			if(!isNaN(sx))
				_offsets.scaleY = sy;
			if(!isNaN(sz))
				_offsets.scaleZ = sz;			
		}
		invalidate();
		completeTransformCenterAdjustment(token,is3D);
		
	}
		
}
}


	}
	
	
	/**
	 * @private
	 * convenience function for building a 2D matrix from the convenience properties 
