1////////////////////////////////////////////////////////////////////////////////
2//
3//  ADOBE SYSTEMS INCORPORATED
4//  Copyright 2003-2008 Adobe Systems Incorporated
5//  All Rights Reserved.
6//
7//  NOTICE: Adobe permits you to use, modify, and distribute this file
8//  in accordance with the terms of the license agreement accompanying it.
9//
10////////////////////////////////////////////////////////////////////////////////
11package mx.geom
12{
13	import flash.geom.Matrix;
14	import flash.geom.Matrix3D;
15	import __AS3__.vec.Vector;
16	import flash.geom.Vector3D;
17	import flash.events.EventDispatcher;
18	import flash.events.Event;
19	import mx.core.mx_internal;
20	import mx.core.AdvancedLayoutFeatures;
21	import flash.geom.Point;
22	use namespace mx_internal;
23
24	/**
25	 *  A CompoundTransform represents a 2D or 3D matrix transform. It can be used in the postLayoutTransformOffsets property on a UIComponent or GraphicElement.
26	 *
27	 *  @langversion 3.0
28	 *  @playerversion Flash 9
29	 *  @playerversion AIR 1.1
30	 *  @productversion Flex 3
31	 */
32	public class TransformOffsets extends EventDispatcher
33	{
34    //--------------------------------------------------------------------------
35    //
36    //  Constructor
37    //
38    //--------------------------------------------------------------------------
39    /**
40     *  Constructor.
41     *
42     *  @langversion 3.0
43     *  @playerversion Flash 9
44     *  @playerversion AIR 1.1
45     *  @productversion Flex 3
46     */
47		public function TransformOffsets()
48		{
49		}
50
51
52
53    /**
54     * @private
55     * storage for transform properties. These values are concatenated together with the layout properties to
56     * form the actual computed matrix used to render the object.
57     */
58	private var _rotationX:Number = 0;
59	private var _rotationY:Number = 0;
60	private var _rotationZ:Number = 0;
61	private var _scaleX:Number = 1;
62	private var _scaleY:Number = 1;
63	private var _scaleZ:Number = 1;
64	private var _x:Number = 0;
65	private var _y:Number = 0;
66	private var _z:Number = 0;
67
68    /**
69     * @private
70     * flags for tracking whether the  transform is 3D. A transform is 3D if any of the 3D properties -- rotationX/Y, scaleZ, or z -- are set.
71     */
72	private static const IS_3D:uint 				= 0x200;
73	private static const M3D_FLAGS_VALID:uint			= 0x400;
74
75    /**
76     * @private
77     * general storage for all of our flags.
78     */
79    private var _flags:uint =  0;
80
81    /**
82     * @private
83     */
84	mx_internal var owner:AdvancedLayoutFeatures;
85	//----------------------------------------------------------------------------
86
87	/**
88	 * the  x value added to the transform
89	 *
90	 *  @langversion 3.0
91	 *  @playerversion Flash 9
92	 *  @playerversion AIR 1.1
93	 *  @productversion Flex 3
94	 */
95	public function set x(value:Number):void
96	{
97		if (value == _x)
98			return;
99		_x = value;
100		invalidate(false);
101	}
102    /**
103     * @private
104     */
105	public function get x():Number
106	{
107		return _x;
108	}
109
110	/**
111	 * the y value added to the transform
112	 *
113	 *  @langversion 3.0
114	 *  @playerversion Flash 9
115	 *  @playerversion AIR 1.1
116	 *  @productversion Flex 3
117	 */
118	public function set y(value:Number):void
119	{
120		if (value == _y)
121			return;
122		_y = value;
123		invalidate(false);
124	}
125
126    /**
127     * @private
128     */
129	public function get y():Number
130	{
131		return _y;
132	}
133
134	/**
135	 * the z value added to the transform
136	 *
137	 *  @langversion 3.0
138	 *  @playerversion Flash 9
139	 *  @playerversion AIR 1.1
140	 *  @productversion Flex 3
141	 */
142	public function set z(value:Number):void
143	{
144		if (value == _z)
145			return;
146		_z = value;
147		invalidate(true);
148	}
149
150    /**
151     * @private
152     */
153	public function get z():Number
154	{
155		return _z;
156	}
157
158	//------------------------------------------------------------------------------
159
160
161	/**
162	 * the rotationX, in degrees, added to the transform
163	 *
164	 *  @langversion 3.0
165	 *  @playerversion Flash 9
166	 *  @playerversion AIR 1.1
167	 *  @productversion Flex 3
168	 */
169	public function set rotationX(value:Number):void
170	{
171		if (value == _rotationX)
172			return;
173		_rotationX = value;
174		invalidate(true);
175	}
176
177    /**
178     * @private
179     */
180	public function get rotationX():Number
181	{
182		return _rotationX;
183	}
184
185	/**
186	 * the rotationY, in degrees, added to the transform
187	 *
188	 *  @langversion 3.0
189	 *  @playerversion Flash 9
190	 *  @playerversion AIR 1.1
191	 *  @productversion Flex 3
192	 */
193	public function set rotationY(value:Number):void
194	{
195		if (value == _rotationY)
196			return;
197		_rotationY = value;
198		invalidate(true);
199	}
200
201    /**
202     * @private
203     */
204	public function get rotationY():Number
205	{
206		return _rotationY;
207	}
208
209	/**
210	 * the rotationZ, in degrees, added to the transform
211	 *
212	 *  @langversion 3.0
213	 *  @playerversion Flash 9
214	 *  @playerversion AIR 1.1
215	 *  @productversion Flex 3
216	 */
217	public function set rotationZ(value:Number):void
218	{
219		if (value == _rotationZ)
220			return;
221		_rotationZ = value;
222		invalidate(false);
223	}
224
225    /**
226     * @private
227     */
228	public function get rotationZ():Number
229	{
230		return _rotationZ;
231	}
232
233	//------------------------------------------------------------------------------
234
235
236	/**
237	 * the multiplier applied to the scaleX of the transform.
238	 *
239	 *  @langversion 3.0
240	 *  @playerversion Flash 9
241	 *  @playerversion AIR 1.1
242	 *  @productversion Flex 3
243	 */
244	public function set scaleX(value:Number):void
245	{
246		if (value == _scaleX)
247			return;
248		_scaleX = value;
249		invalidate(false);
250	}
251
252    /**
253     * @private
254     */
255	public function get scaleX():Number
256	{
257		return _scaleX;
258	}
259
260	/**
261	 * the multiplier applied to the scaleY of the transform.
262	 *
263	 *  @langversion 3.0
264	 *  @playerversion Flash 9
265	 *  @playerversion AIR 1.1
266	 *  @productversion Flex 3
267	 */
268	public function set scaleY(value:Number):void
269	{
270		if (value == _scaleY)
271			return;
272		_scaleY = value;
273		invalidate(false);
274	}
275
276    /**
277     * @private
278     */
279	public function get scaleY():Number
280	{
281		return _scaleY;
282	}
283
284
285	/**
286	 * the multiplier applied to the scaleZ of the transform.
287	 *
288	 *  @langversion 3.0
289	 *  @playerversion Flash 9
290	 *  @playerversion AIR 1.1
291	 *  @productversion Flex 3
292	 */
293	public function set scaleZ(value:Number):void
294	{
295		if (value == _scaleZ)
296			return;
297		_scaleZ = value;
298		invalidate(true);
299	}
300
301    /**
302     * @private
303     */
304	public function get scaleZ():Number
305	{
306		return _scaleZ;
307	}
308
309
310	/**
311	 * @private
312	 * returns true if the transform has 3D values.
313	 */
314	mx_internal function get is3D():Boolean
315	{
316		if ((_flags & M3D_FLAGS_VALID) == 0)
317			update3DFlags();
318		return ((_flags & IS_3D) != 0);
319	}
320
321
322	//------------------------------------------------------------------------------
323
324	/**
325	 * @private
326	 * invalidates our various cached values.  Any change to the CompoundTransform object that affects
327	 * the various transforms should call this function.
328     * @param reason - the code indicating what changes to cause the invalidation.
329     * @param affects3D - a flag indicating whether the change affects the 2D/3D nature of the various transforms.
330     * @param dispatchChangeEvent - if true, the CompoundTransform will dispatch a change indicating that its underlying transforms
331     * have been modified.
332  	 */
333	private function invalidate(affects3D:Boolean,dispatchChangeEvent:Boolean = true):void
334	{
335		if (affects3D)
336			_flags &= ~M3D_FLAGS_VALID;
337
338		if (dispatchChangeEvent)
339			dispatchEvent(new Event(Event.CHANGE));
340	}
341
342	private static const EPSILON:Number = .001;
343	/**
344	 * @private
345	 * updates the flags that indicate whether the layout, offset, and/or computed transforms are 3D in nature.
346	 * Since the user can set either the individual transform properties or the matrices directly, we compute these
347	 * flags based on what the current 'source of truth' is for each of these values.
348  	 */
349	private function update3DFlags():void
350	{
351		if ((_flags & M3D_FLAGS_VALID) == 0)
352		{
353			var matrixIs3D:Boolean = ( // note that rotationZ is the same as rotation, and not a 3D affecting
354			  	(Math.abs(_scaleZ-1) > EPSILON) ||  // property.
355			  	((Math.abs(_rotationX)+EPSILON)%360) > 2*EPSILON ||
356			  	((Math.abs(_rotationY)+EPSILON)%360) > 2*EPSILON ||
357			  	Math.abs(_z) > EPSILON
358			  	);
359			if (matrixIs3D)
360				_flags |= IS_3D;
361			else
362				_flags &= ~IS_3D;
363			_flags |= M3D_FLAGS_VALID;
364		}
365	}
366
367}
368}
369