├── .gitignore
├── LICENSE
├── README.md
├── akifox-transform.sublime-project
├── com
└── akifox
│ └── transform
│ └── Transformation.hx
├── docs
├── bootstrap-combined.min.css
├── bootstrap.min.js
├── favicon.ico
├── index.html
├── index.js
├── jquery-1.9.1.min.js
├── nav.js
├── styles.css
├── triangle-closed.png
└── triangle-opened.png
├── haxelib.json
├── samples
└── interactive
│ ├── README.md
│ ├── assets
│ ├── fonts
│ │ └── 04B_03__.ttf
│ ├── graphics
│ │ ├── graphics_here
│ │ └── test.png
│ └── openfl.svg
│ ├── project.xml
│ └── src
│ └── Main.hx
└── scripts
├── gen_docs.hxml
├── gen_docs.sh
└── make_haxelib.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *bin
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Simone Cingano
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | []()
2 | [](LICENSE)
3 | [](http://www.haxe.org)
4 | [](http://www.openfl.org)
5 | [](http://www.openfl.org)
6 |
7 | [](http://lib.haxe.org/p/akifox-transform)
8 | [](http://lib.haxe.org/p/akifox-transform)
9 |
10 | # akifox-transform (com.akifox.transform.Transformation)
11 | **HAXE/OpenFL Affine transformation class**
12 |
13 | The akifox-transform class aims to provide an easy tool to manage affine transformations using a reliable pivot point.
14 | What are the affine transformation you might ask...
15 | - read this wikipedia page
16 | - read this great flash tutorial
17 |
18 | # NOTE
19 |
20 | The class works quite fine with OpenFL 3, there are just few incompatibilities that might present problems.
21 | If you see a possible bug please test your app with the option `-Dlegacy` before filing an issue.
22 |
23 | ## Example demo
24 |
25 | 
26 |
27 | **Flash build:** transformation-example.swf
28 |
29 | You should get a window with a OpenFL logo square.
30 | - Z to toggle debug drawings
31 | - SPACE to reset the transformations
32 | - Drag to move
33 | - Click to change the Pivot Point
34 | - Drag+SHIFT to rotate around the pivot point
35 | - Drag+ALT to scale related to the pivot point
36 | - Drag+CMD/CTRL to skew related to the pivot point (the cross center represents a 0,0 skew)
37 | - 1 to 9 to set the pivot point on the relative anchor point (TOPLEFT, MIDDLELEFT,BOTTOMLEFT,TOPCENTER... BOTTOMRIGHT)
38 | - UP, DOWN, RIGHT, LEFT Move 15px
39 | - Q, A to Skew X ±15deg
40 | - W, S to Skew Y ±15deg
41 | - E, D to Scale */1.5
42 | - R, F to Rotate ±15deg
43 |
44 |
45 | ## Install
46 |
47 | You can easily install the library thru haxelib
48 |
49 | ```
50 | haxelib install akifox-transform
51 | ```
52 |
53 | In your project add the library reference in your ```project.xml```
54 |
55 | ```
56 |
57 | ```
58 |
59 | and finally you can import it in your project class with this import
60 | ```
61 | import com.akifox.transform.Transformation;
62 | ```
63 |
64 | ## Documentation
65 |
66 | You can read the full Library documentation here
67 |
68 |
69 |
70 | ## Using the library
71 |
72 | The Transformation class works on Matrix objects.
73 | Anyway usually once you've got a DisplayObject (Sprites, Bitmap...) you want to link this to a Transformation.
74 |
75 | ````haxe
76 | package ;
77 | import openfl.display.Sprite;
78 | import openfl.Lib;
79 | import openfl.geom.Matrix;
80 | import com.akifox.transform.Transformation;
81 |
82 | class Main extends Sprite {
83 |
84 | public function new() {
85 | super();
86 | Lib.current.stage.addChild(this);
87 |
88 | //[...]
89 |
90 | var trf = new Transformation();
91 | trf.bind(yourDisplayObject);
92 | trf.setAnchoredPivot(Transformation.ANCHOR_TOP_LEFT);
93 |
94 | // these are the Pivot Point coordinates (they will not change unless
95 | // you change the pivot point position)
96 | var pivotCoordinates:Point = trf.getPivot();
97 |
98 | trf.rotate(20); //rotate by 20deg clockwise
99 | trf.skewX(30); //skew X axis by 30deg
100 | Actuate.tween(trf,1,{'scalingX':2,'scalingY'"2}); //scale 2X in 1s using Actuate
101 | }
102 |
103 | }
104 | ````
105 |
106 | But you can use the library to manipulate a Matrix without bind it to a DisplayObject
107 |
108 | ````haxe
109 | package ;
110 | import openfl.display.Sprite;
111 | import openfl.Lib;
112 | import openfl.geom.Matrix;
113 | import com.akifox.transform.Transformation;
114 |
115 | class Main extends Sprite {
116 |
117 | var trf:Transformation;
118 |
119 | public function new() {
120 | super();
121 | Lib.current.stage.addChild(this);
122 | trf = new Transformation(new Matrix(),100,50);
123 | addChild(trf.spriteDebug); //debug
124 | trf.addEventListener(Transformation.TRANSFORM, onTransform); //debug
125 | trf.rotate(20); //rotate by 20deg clockwise
126 | trf.skewX(30); //skew X axis by 30deg
127 |
128 | var transformedMatrix = trf.matrix; //get the matrix for your own use!
129 | }
130 |
131 | public function onTransform(event:Event) {
132 | trf.debugDraw();
133 | }
134 |
135 | }
136 | ````
137 |
138 | ## Best practice
139 |
140 | The idea behind the library wants the developer to use the transformation to change the object affine transformation properties.
141 |
142 | So you can work on the large amount of transformation properties and methods as:
143 |
144 | These assignments modify the target/matrix property according to the pivot point
145 | (all of the degree ones are provided in Rad as well)
146 | ````
147 | trf.x = valuePixels;
148 | trf.y = valuePixels;
149 | trf.rotation = valueDegrees;
150 | trf.skewingX = valueDegrees;
151 | trf.skewingY = valueDegrees;
152 | trf.scaling = valueFactor; //set X and Y scale to this factor
153 | trf.scalingX = valueFactor;
154 | trf.scalingY = valueFactor;
155 | ````
156 |
157 | The methods provide instead a algebric sum change according to the pivot point
158 | (all of the degree ones are provided in Rad as well)
159 | ````
160 | trf.translate(addPixelsX,addPixelsY);
161 | trf.translateX(addPixels);
162 | trf.translateY(addPixels);
163 | trf.rotate(addDegrees);
164 | trf.skewX(addDegree);
165 | trf.skewY(addDegree);
166 | trf.scale(multiplyFactor);
167 | trf.scaleX(multiplyFactor);
168 | trf.scaleY(multiplyFactor);
169 | ````
170 |
171 | -----
172 |
173 | There are some interesting examples in different classes on the [PLIK library](https://github.com/yupswing/plik) that shows how to encapsulate the transformation class with an object.
174 | See the [Gfx Class](https://github.com/yupswing/plik/blob/master/com/akifox/plik/Gfx.hx), or Text, or SpriteContainer for an example.
175 |
176 | #### Transformation class
177 | - [ ] *Unit test*
178 | - [x] Cleaning and documenting code
179 | - [x] Pivot point managing
180 | - [x] Support for motion.Actuate (properties linked to functions get and set)
181 | - [x] Events (Transform and Pivot change)
182 | - [x] Translate
183 | - [x] Get
184 | - [x] Set
185 | - [x] Add
186 | - [x] Skew
187 | - [x] Get
188 | - [x] Set
189 | - [x] Add
190 | - [x] Scale
191 | - [x] Get
192 | - [x] Set
193 | - [x] Add
194 | - [ ] Flip
195 | - [ ] Get (it looks like impossible!)
196 | - [x] Set
197 | - [x] Rotate
198 | - [x] Get
199 | - [x] Set
200 | - [x] Add
201 |
--------------------------------------------------------------------------------
/akifox-transform.sublime-project:
--------------------------------------------------------------------------------
1 | {
2 | "folders":
3 | [
4 | {
5 | "follow_symlinks": true,
6 | "path": "."
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/com/akifox/transform/Transformation.hx:
--------------------------------------------------------------------------------
1 | package com.akifox.transform;
2 |
3 | import openfl.geom.Matrix;
4 | import openfl.geom.Point;
5 | import openfl.events.Event;
6 | import openfl.events.EventDispatcher;
7 | import openfl.display.Shape;
8 | import openfl.display.DisplayObject;
9 |
10 | /**
11 |
12 | @author Simone Cingano (yupswing) [Akifox Studio](http://akifox.com)
13 |
14 | @licence MIT Licence
15 |
16 | @version 2.2.1
17 | [Public repository](https://github.com/yupswing/akifox-transform/)
18 |
19 | #### Transformation HAXE/OpenFL Library
20 | The akifox-transform library aims to provide an easy tool
21 | to manage affine transformations using a reliable pivot point.
22 |
23 | #### Notes:
24 | This page was very helpful to understand matrix affine transformation
25 | http://www.senocular.com/flash/tutorials/transformmatrix/
26 |
27 | */
28 | class Transformation extends EventDispatcher
29 | {
30 | /** Constant factor to pass from degrees to radians **/
31 | public static var DEG2RAD:Float = Math.PI/180;
32 | /** Constant factor to pass from radians to degrees **/
33 | public static var RAD2DEG:Float = 180/Math.PI;
34 | // temporary objects (always reset them before using)
35 | private static var point:Point = new Point();
36 | private static var point2:Point = new Point();
37 |
38 | private inline static var NULL:Float=-0.01;
39 |
40 | // Pivot Point Anchors (used by setAnchoredPivot and getAnchoredPivot)
41 | public inline static var ANCHOR_TOP_LEFT:Int = 0;
42 | public inline static var ANCHOR_TOP_CENTER:Int = 1;
43 | public inline static var ANCHOR_TOP_RIGHT:Int = 2;
44 | public inline static var ANCHOR_MIDDLE_LEFT:Int = 3;
45 | public inline static var ANCHOR_MIDDLE_CENTER:Int = 4;
46 | public inline static var ANCHOR_MIDDLE_RIGHT:Int = 5;
47 | public inline static var ANCHOR_BOTTOM_LEFT:Int = 6;
48 | public inline static var ANCHOR_BOTTOM_CENTER:Int = 7;
49 | public inline static var ANCHOR_BOTTOM_RIGHT:Int = 8;
50 |
51 | // the pivot anchor point (using Pivot Point Anchors)
52 | // example: Transformation.ANCHOR_BOTTOM_CENTER
53 | private var pivotPointAnchor:Int = -1;
54 |
55 | // the pivot offset
56 | private var offsetPoint:Point;
57 |
58 | // the target object
59 | private var _target:DisplayObject = null;
60 |
61 | // target properties
62 | private var _width:Float;
63 | private var _height:Float;
64 | private var _identityX:Float;
65 | private var _identityY:Float;
66 | private var _identityWidth:Float;
67 | private var _identityHeight:Float;
68 | /** The debug sprite where debugDraw() draws **/
69 | public var spriteDebug:Shape;
70 |
71 | // THE MATRIX!
72 | private var _matrix:Matrix;
73 |
74 |
75 | /**
76 | * Set the transformation matrix, overwriting the existing one
77 | * (the pivot point will be respected)
78 | * Get a copy of the transformation matrix
79 | **/
80 | public var matrix(get,set):Matrix;
81 | private function set_matrix(m:Matrix):Matrix {
82 | // change the matrix and adjust to respect the Pivot Point
83 | setMatrixInternal(m,true);
84 | return m;
85 | }
86 | private function get_matrix():Matrix {
87 | return getMatrixInternal();
88 | }
89 |
90 | /**
91 | * Class instance
92 | *
93 | * All the parameters are optional and you don't need to exclicit them if you plan
94 | * to bind the transformation to a DisplayObject (they will be inherited at the binding process)
95 | *
96 | * @param matrix The original matrix (optional)
97 | * @param width The rectangle width (optional)
98 | * @param height The rectangle height (optional)
99 | * @param pivot An absolute point to set the pivot (optional)
100 | **/
101 | public function new(matrix:Matrix=null,width:Float=0,height:Float=0,?pivot:Point=null)
102 | {
103 | super();
104 | // set the target and get the original properties
105 | //this.target = target;
106 | if (matrix==null) matrix = new Matrix();
107 | _matrix = matrix;
108 | _identityWidth = _width = width;
109 | _identityHeight = _height = height;
110 | _identityX = _matrix.tx;
111 | _identityY = _matrix.ty;
112 | spriteDebug = new Shape();
113 |
114 | if (pivot==null) {
115 | //set the pivot point TOPLEFT of the target if nothing specified
116 | setAnchoredPivot(Transformation.ANCHOR_TOP_LEFT);
117 | } else {
118 | //set the pivot point to the specified coords
119 | setPivot(pivot);
120 | }
121 | }
122 |
123 | public function destroy(){
124 | this.spriteDebug = null;
125 | this._matrix = null;
126 | this.release();
127 | this.offsetPoint = null;
128 | }
129 |
130 | // TARGET
131 | // #########################################################################
132 |
133 | /**
134 | * Bind the transformation matrix to a target (has to be a DisplayObject)
135 | **/
136 | public function bind(target:DisplayObject){
137 | this._target = target;
138 | this.x = target.x;
139 | this.y = target.y;
140 | this.updateSize();
141 | }
142 |
143 | private function release(){
144 | this._target = null;
145 | }
146 |
147 | /**
148 | * When the size is changed externally of the Transformation class
149 | * you should use this method to update the size internally
150 | *
151 | * **example:** a textfield object with text changed will change size
152 | * but the Transformation class can't be aware of that if you don't
153 | * call this method
154 | *
155 | * ----
156 | *
157 | * Otherwise you can set the size to arbitrary values if you want to
158 | * set a certain AnchoredPivot based on the rect you specify
159 | *
160 | **/
161 | public function updateSize(?nw:Float=0,?nh:Float=0) {
162 | /* */
163 |
164 | // get current translation and the complete matrix
165 | var translation:Point = getTranslation();
166 | var currentMatrix:Matrix = getMatrixInternal();
167 |
168 | // remove all transformation
169 | this.identity();
170 |
171 | // get the _identity width and height without transformations
172 | if ((nw==0 || nh==0)&&(_target != null)) {
173 | _identityWidth = _target.width;
174 | _identityHeight = _target.height;
175 | } else {
176 | _identityWidth = nw;
177 | _identityHeight = nh;
178 | }
179 |
180 | // reset the anchored pivot (based on new size)
181 | if (this.pivotPointAnchor!=-1) setAnchoredPivot(this.pivotPointAnchor);
182 |
183 | // restore the transformation
184 | this.setMatrixInternal(currentMatrix);
185 |
186 | // restore the original translation
187 | // (the new given anchored pivot will count)
188 | this.setTranslation(translation);
189 | currentMatrix = null;
190 | translation = null;
191 | }
192 |
193 |
194 |
195 | // EVENTS
196 | // #########################################################################
197 |
198 | /**
199 | * The transform event
200 | * It will be called every time the class change the transformation matrix
201 | *
202 | * **example:**
203 | * ```
204 | * myTransformation.addEventListener(Transformation.TRANSFORM, onMyTransform);
205 | * ```
206 | **/
207 | public static inline var TRANSFORM:String = "TRANSFORM";
208 |
209 | /**
210 | * The pivot change event
211 | * It will be called every time the class change the pivot point
212 | *
213 | * **example:**
214 | * ```
215 | * myTransformation.addEventListener(Transformation.PIVOT_CHANGE, onMyPivotChange);
216 | * ```
217 | **/
218 | public static inline var PIVOT_CHANGE:String = "PIVOT_CHANGE";
219 |
220 | private function onTransform(){
221 | dispatchEvent(new Event(TRANSFORM));
222 | }
223 |
224 | private function onPivotChange(){
225 | dispatchEvent(new Event(PIVOT_CHANGE));
226 | }
227 |
228 |
229 |
230 | // STATIC UTILS
231 | // #########################################################################
232 |
233 | /**
234 | * Calculate the distance between two points
235 | *
236 | * @param p0 First point
237 | * @param p1 Second point
238 | * @return The distance
239 | **/
240 | public static inline function distance(p0:Point, p1:Point) : Float
241 | {
242 | var x = p0.x-p1.x;
243 | var y = p0.y-p1.y;
244 | return Math.sqrt(x*x + y*y);
245 | }
246 |
247 |
248 |
249 | // DEBUG
250 | // #########################################################################
251 |
252 | /**
253 | * Clear the spriteDebug:Sprite object
254 | **/
255 | public function debugClear() {
256 | spriteDebug.graphics.clear();
257 | }
258 | /**
259 | * Draw in the spriteDebug:Sprite object
260 | *
261 | * Useful to be called with the event TRANSFORM to have a graphic representation
262 | * of the ongoing transformation
263 | *
264 | * **example:**
265 | * ```haxe
266 | * // new
267 | * myspriteTrs = new Transformation(mysprite);
268 | * myspriteTrs.addEventListener(Transformation.TRANSFORM, onTransform);
269 | * addChild(myspriteTrs.debugDraw);
270 | *
271 | * //[...]
272 | *
273 | * public function onTransform(event:Event) {
274 | * myspriteTrs.debugDraw();
275 | * }
276 | * ```
277 | *
278 | * @param drawPivot Draws the pivot point flag
279 | * @param drawOrigin Draws the point 0,0 transformed (top left edge of the original rect)
280 | * @param drawOriginal Draws the original rect untransformed
281 | * @param drawBoundaries Draws the rect that enclose the transformed object
282 | * @param drawRotation Draws a circle in the pivot point with radius distance(pivotPoint, point 0,0 transformed)
283 | **/
284 | public function debugDraw( drawPivot:Bool=true,
285 | drawOrigin:Bool=true,
286 | drawOriginal:Bool=true,
287 | drawBoundaries:Bool=true,
288 | drawRotation:Bool=true) {
289 |
290 | debugClear();
291 |
292 | if (_target==null) {
293 |
294 | }
295 |
296 | var pivot:Point = getPivot();
297 |
298 | // p0 .___. p1
299 | // | |
300 | // p2 .___. p3
301 |
302 | var p0:Point = new Point(0,0);
303 | if (drawOrigin || drawBoundaries) {
304 | p0 = getPosition();
305 | }
306 |
307 |
308 | // pivot point
309 | if (drawPivot) {
310 | spriteDebug.graphics.beginFill(0x00FF00,1);
311 | spriteDebug.graphics.drawCircle(pivot.x,pivot.y,5);
312 | spriteDebug.graphics.endFill();
313 | }
314 |
315 | // original 0,0 transformed
316 | if (drawOrigin) {
317 | spriteDebug.graphics.beginFill(0xFFFF00,0.5);
318 | spriteDebug.graphics.drawCircle(p0.x,p0.y,5);
319 | spriteDebug.graphics.endFill();
320 | }
321 |
322 | // original target boundaries (same as original target rect)
323 | if (drawOriginal) {
324 | spriteDebug.graphics.lineStyle(2, 0x0000FF, .5, false);
325 | spriteDebug.graphics.drawRect(_identityX,_identityY,_identityWidth,_identityHeight);
326 | }
327 |
328 | // transformed target boundaries
329 | if (drawBoundaries) {
330 | var p1:Point;
331 | p1 = transformPoint(new Point(_identityWidth,0));
332 | var p2:Point;
333 | p2 = transformPoint(new Point(0,_identityHeight));
334 | var p3:Point;
335 | p3 = transformPoint(new Point(_identityWidth,_identityHeight));
336 | var _identityZeroX = Math.min(Math.min(Math.min(p0.x,p1.x),p2.x),p3.x);
337 | var _identityZeroY = Math.min(Math.min(Math.min(p0.y,p1.y),p2.y),p3.y);
338 | _width = Math.max(Math.max(Math.max(p0.x,p1.x),p2.x),p3.x)-_identityZeroX;
339 | _height = Math.max(Math.max(Math.max(p0.y,p1.y),p2.y),p3.y)-_identityZeroY;
340 | spriteDebug.graphics.lineStyle(2, 0xFF00FF, .5, false);
341 | spriteDebug.graphics.drawRect(_identityZeroX,_identityZeroY,_width,_height);
342 | }
343 |
344 | // rotation circle
345 | if (drawRotation) {
346 | spriteDebug.graphics.lineStyle(2, 0x00FF00, .5, false);
347 | spriteDebug.graphics.drawCircle(pivot.x,pivot.y,distance(pivot,p0));
348 | }
349 | }
350 |
351 |
352 | // PIVOT MANAGMENT
353 | // #########################################################################
354 |
355 | // Pivot Point Anchors
356 | // -------------------
357 | //
358 | // 0,0 - 1,0 - 2,0 x=> LEFT=0 CENTER=1 RIGHT=2
359 | // | | | y=> TOP=0 MIDDLE=1 BOTTOM=2
360 | // 0,1 - 1,1 - 2,1
361 | // | | |
362 | // 0,2 - 1,2 - 2,2
363 | //
364 |
365 | /**
366 | * Set the pivot in the Pivot Point Anchor specified (see the constants ANCHOR_*)
367 | *
368 | * @param pivotPointAnchor A pivot point anchor
369 | **/
370 | public function setAnchoredPivot(pivotPointAnchor:Int) {
371 | //set the Pivot Point Anchor as specified
372 | this.pivotPointAnchor = pivotPointAnchor;
373 | //set the pivot offset based on the Pivot Point Anchor specified
374 | offsetPoint = getAnchoredPivotOffset(pivotPointAnchor);
375 | this.onPivotChange();
376 | }
377 |
378 | /**
379 | * Set the pivot in an arbitrary point
380 | *
381 | * @param point A point
382 | **/
383 | public function setPivot(point:Point) {
384 | //unset the Pivot Point Anchor
385 | this.pivotPointAnchor = -1;
386 | //set the pivot offset
387 | offsetPoint = inverseTransformPoint(point);
388 | this.onPivotChange();
389 | }
390 |
391 | /**
392 | * Set the pivot offset (from target 0,0) in an arbitrary point
393 | *
394 | * @param point A point
395 | **/
396 | public function setPivotOffset(point:Point) {
397 | //unset the Pivot Point Anchor
398 | this.pivotPointAnchor = -1;
399 | //set the pivot offset
400 | offsetPoint = point;
401 | this.onPivotChange();
402 | }
403 |
404 | /**
405 | * Get the pivot absolute position
406 | *
407 | * @returns The pivot point absolute position
408 | **/
409 | public function getPivot():Point {
410 | return transformPoint(offsetPoint);
411 | }
412 |
413 | /**
414 | * Get the pivot offset position (from target 0,0)
415 | *
416 | * @returns The pivot point offset position
417 | **/
418 | public function getPivotOffset():Point {
419 | return offsetPoint;
420 | }
421 |
422 | /**
423 | * Get the offset (from target 0,0) position of a specified Pivot Point Anchor (see the constants ANCHOR_*)
424 | *
425 | * @return The point position
426 | **/
427 | public function getAnchoredPivotOffset(?pivotPointAnchor:Int=0):Point {
428 | return getAnchorPivot(pivotPointAnchor,false);
429 | }
430 |
431 | /**
432 | * Get the absolute position of a specified Pivot Point Anchor (see the constants ANCHOR_*)
433 | *
434 | * @return The point position
435 | **/
436 | public function getAnchoredPivot(?pivotPointAnchor:Int=0):Point {
437 | return getAnchorPivot(pivotPointAnchor,true);
438 | }
439 |
440 | // internal (used by getAnchoredPivotOffset and getAnchoredPivot)
441 | private function getAnchorPivot(pivotPointAnchor:Int,absolute:Bool):Point {
442 | // _identityWidth / 2 * 0 is LEFT .______
443 | // _identityWidth / 2 * 1 is CENTER ___.___
444 | // _identityWidth / 2 * 2 is RIGHT ______.
445 | // and so on for the Y
446 | if (pivotPointAnchor<0 || pivotPointAnchor>8) pivotPointAnchor = 0;
447 | var pivotPositionX = pivotPointAnchor % 3;
448 | var pivotPositionY = Std.int(pivotPointAnchor / 3);
449 |
450 | var x = _identityWidth/2*pivotPositionX;
451 | var y = _identityHeight/2*pivotPositionY;
452 |
453 | // add the current translation to the point
454 | // to get the absolute position
455 | if (absolute) {
456 | var translation = getPosition();
457 | x+=translation.x; // pos.x is matrix.tx
458 | y+=translation.y; // pos.y is matrix.ty
459 | }
460 | return new Point(x,y);
461 | }
462 |
463 | // #########################################################################
464 |
465 |
466 | private function setMatrixInternal(m:Matrix,?adjust=false):Void
467 | {
468 | // adjust==true is needed to respect the Pivot Point
469 | var originalPoint:Point = new Point(0,0);
470 | if (adjust) originalPoint = getPivot(); //this before apply the transform
471 | _matrix = m; //apply the transformation
472 | m = null;
473 | if (adjust) adjustOffset(originalPoint); //this after apply the transform
474 | if (_target != null) this._target.transform.matrix = getMatrixInternal();
475 | this.onTransform();
476 | }
477 |
478 | /**
479 | * Set the transformation matrix, overwriting the existing one,
480 | * using the specified values
481 | *
482 | * (the pivot point will be respected)
483 | **/
484 | public function setMatrixTo(a:Float,b:Float,c:Float,d:Float,tx:Float,ty:Float) {
485 | // update the matrix and adjust to respect the Pivot Point
486 | setMatrixInternal(new Matrix(a,b,c,d,tx,ty),true);
487 | }
488 |
489 | private function getMatrixInternal():Matrix
490 | {
491 | return _matrix.clone();
492 | }
493 |
494 | // #########################################################################
495 |
496 |
497 | private function adjustOffset(originalPoint:Point) {
498 |
499 | //get the target matrix to apply the transformation
500 | var m:Matrix = getMatrixInternal();
501 |
502 | //get the pivot NEW absolute position
503 | var transformedPoint:Point = m.transformPoint(offsetPoint);
504 | // get the Pivot position offset between before and after the transformation
505 | var offset:Point = new Point(transformedPoint.x-originalPoint.x,
506 | transformedPoint.y-originalPoint.y);
507 |
508 | // apply the offset with a translation to the target
509 | // to keep the pivot relative position coherent
510 | m.tx-=offset.x;
511 | m.ty-=offset.y;
512 |
513 | //apply the matrix to the target
514 | setMatrixInternal(m);
515 |
516 | }
517 |
518 |
519 |
520 | // POINT TRANSFORMATIONS
521 | // #########################################################################
522 |
523 | /**
524 | * Transform a point using the current transformation matrix
525 | *
526 | * @param point The point to be transformed
527 | * @returns The transformed point
528 | **/
529 | public function transformPoint(point:Point):Point {
530 | // apply the current transformation on a point
531 | return _matrix.transformPoint(point);
532 | }
533 |
534 | /**
535 | * Transform a point using the current transformation matrix
536 | * but ignoring the translation
537 | *
538 | * @param point The point to be transformed
539 | * @returns The transformed point
540 | **/
541 | public function deltaTransformPoint(point:Point):Point {
542 | // apply the current transformation on a point
543 | // [ignore the translation]
544 | return _matrix.deltaTransformPoint(point);
545 | }
546 |
547 | /**
548 | * Transform a point using the inverted current transformation matrix
549 | * This means:
550 | * ```
551 | * p == inverseTransformPoint(transformPoint(p)); // is true
552 | * ```
553 | *
554 | * @param point The point to be transformed
555 | * @returns The transformed point
556 | **/
557 | public function inverseTransformPoint(point:Point):Point {
558 | // remove the current transformation on a point
559 | // (give a transformed point to get a 'identity' point)
560 | var m:Matrix = getMatrixInternal();
561 | m.invert();
562 | return m.transformPoint(point);
563 | }
564 |
565 | /**
566 | * Transform a point using the inverted current transformation matrix
567 | * but ignoring the translation
568 | * This means:
569 | * ```
570 | * p == inverseDeltaTransformPoint(deltaTransformPoint(p)); // is true
571 | * ```
572 | *
573 | * @param point The point to be transformed
574 | * @returns The transformed point
575 | **/
576 | public function inverseDeltaTransformPoint(point:Point):Point {
577 | // remove the current transformation on a point
578 | // (give a transformed point to get a 'identity' point)
579 | // [ignore the translation]
580 | var m:Matrix = getMatrixInternal();
581 | m.invert();
582 | return m.deltaTransformPoint(point);
583 | }
584 |
585 |
586 |
587 | // IDENTITY
588 | // #########################################################################
589 |
590 | /**
591 | * Reset the matrix (no transformations)
592 | *
593 | * (the pivot point will be respected)
594 | **/
595 | public function identity(){
596 | // reset the matrix
597 | var m = new Matrix();
598 | m.tx = _identityX - offsetPoint.x;
599 | m.ty = _identityY - offsetPoint.y;
600 | setMatrixInternal(m);
601 | }
602 |
603 |
604 |
605 | // TRANSLATE TRANSFORMATION
606 | // #########################################################################
607 |
608 | /**
609 | * Delta translation
610 | * @param dx translation on the X axis
611 | * @param dy translation on the Y axis
612 | **/
613 | public function translate(dx:Float=0, dy:Float=0):Void
614 | {
615 | var m:Matrix = getMatrixInternal();
616 | m.tx += dx;
617 | m.ty += dy;
618 | setMatrixInternal(m);
619 | }
620 |
621 | /**
622 | * Delta translation on X axis
623 | * @param dx translation on the X axis
624 | **/
625 | public function translateX(dx:Float=0):Void { translate(dx,0); }
626 |
627 | /**
628 | * Delta translation on Y axis
629 | * @param dy translation on the Y axis
630 | **/
631 | public function translateY(dy:Float=0):Void { translate(0,dy); }
632 |
633 | /**
634 | * Absolute translation
635 | * @param translation The specified point
636 | **/
637 | public function setTranslation(translation:Point):Void
638 | {
639 | var m:Matrix = getMatrixInternal();
640 | var transformedOffset:Point = deltaTransformPoint(offsetPoint);
641 | m.tx = translation.x-transformedOffset.x;
642 | m.ty = translation.y-transformedOffset.y;
643 | setMatrixInternal(m);
644 | }
645 | /**
646 | * Absolute translation on the X axis
647 | * @param tx The X coordinate
648 | **/
649 | public function setTranslationX(tx:Float=0):Float {
650 | var m:Matrix = getMatrixInternal();
651 | m.tx = tx-deltaTransformPoint(offsetPoint).x;
652 | setMatrixInternal(m);
653 | return tx;
654 | }
655 | /**
656 | * Absolute translation on the Y axis
657 | * @param ty The Y coordinate
658 | **/
659 | public function setTranslationY(ty:Float=0):Float {
660 | var m:Matrix = getMatrixInternal();
661 | m.ty = ty-deltaTransformPoint(offsetPoint).y;
662 | setMatrixInternal(m);
663 | return ty;
664 | }
665 |
666 | /**
667 | * Get the current translation
668 | * @returns The current absolute translation point (relative to 0,0)
669 | **/
670 | public function getTranslation():Point
671 | {
672 | var transformedOffset:Point = deltaTransformPoint(offsetPoint);
673 | return new Point(_matrix.tx+transformedOffset.x,_matrix.ty+transformedOffset.y);
674 | }
675 |
676 | /**
677 | * Get the current translation on the X axis
678 | * @returns The current absolute translation X coordinate
679 | **/
680 | public function getTranslationX():Float
681 | {
682 | return getTranslation().x;
683 | }
684 |
685 | /**
686 | * Get the current translation on the Y axis
687 | * @returns The current absolute translation Y coordinate
688 | **/
689 | public function getTranslationY():Float
690 | {
691 | return getTranslation().y;
692 | }
693 |
694 | /**
695 | * Get the current matrix translation (matrix.tx,matrix.ty)
696 | * (this method ignore the pivot point)
697 | * @returns The current matrix translation Point(matrix.tx,matrix.ty)
698 | **/
699 | public function getPosition():Point
700 | {
701 | return new Point(_matrix.tx,_matrix.ty);
702 | }
703 |
704 | /**
705 | * Get the current matrix translation on the X axis (matrix.tx)
706 | * (this method ignore the pivot point)
707 | * @returns The current matrix translation matrix.tx
708 | **/
709 | public function getPositionX():Float
710 | {
711 | return _matrix.tx;
712 | }
713 |
714 | /**
715 | * Get the current matrix translation on the Y axis (matrix.ty)
716 | * (this method ignore the pivot point)
717 | * @returns The current matrix translation matrix.ty
718 | **/
719 | public function getPositionY():Float
720 | {
721 | return _matrix.ty;
722 | }
723 |
724 |
725 | /** Use getTranslationX and setTranslationX **/
726 | public var translationX(get, set):Float;
727 | private function get_translationX():Float { return getTranslationX(); }
728 | private function set_translationX(value:Float):Float { return setTranslationX(value); }
729 |
730 | /** Use getTranslationY and setTranslationY **/
731 | public var translationY(get, set):Float;
732 | private function get_translationY():Float { return getTranslationY(); }
733 | private function set_translationY(value:Float):Float { return setTranslationY(value); }
734 |
735 |
736 | /** Use getTranslationX and setTranslationX **/
737 | public var x(get, set):Float;
738 | private function get_x():Float { return getTranslationX(); }
739 | private function set_x(value:Float):Float { return setTranslationX(value); }
740 |
741 | /** Use getTranslationY and setTranslationY **/
742 | public var y(get, set):Float;
743 | private function get_y():Float { return getTranslationY(); }
744 | private function set_y(value:Float):Float { return setTranslationY(value); }
745 |
746 |
747 | public var width(get, never):Float;
748 | private function get_width():Float { return _width; }
749 | //private function set_width(value:Float):Float { return _width; }
750 |
751 | public var height(get, never):Float;
752 | private function get_height():Float { return _height; }
753 | //private function set_height(value:Float):Float { return _height; }
754 |
755 |
756 |
757 | // SKEW TRANSFORMATION
758 | // #########################################################################
759 |
760 | /**
761 | * Set the skew to a given value in Radians
762 | *
763 | * **NOTE:** It applies an absolute skew on the current matrix
764 | *
765 | * **NOTE:** -0.1 is a null value for cross-platform compatibility (doesn't apply the transformation)
766 | *
767 | * @param skewXRad Value for the X axis
768 | * @param skewXRad Value for the Y axis
769 | **/
770 | public function setSkewRad(skewXRad:Float, skewYRad:Float):Void
771 | {
772 |
773 | //get the target matrix to apply the transformation
774 | var m:Matrix = getMatrixInternal();
775 |
776 | // apply the skew (matrix.c is HORIZONTAL, matrix.b is VERTICAL)
777 | if (skewXRad!=NULL) {
778 | m.c = Math.tan(skewXRad)*getScaleX();
779 | }
780 | if (skewYRad!=NULL) {
781 | m.b = Math.tan(skewYRad)*getScaleY();
782 | }
783 |
784 | //apply the matrix to the target
785 | setMatrixInternal(m,true);
786 | }
787 |
788 | /**
789 | * Set the skew to a given value in Degrees
790 | *
791 | * **NOTE:** It applies an absolute skew on the current matrix
792 | *
793 | * **NOTE:** -0.1 is a null value for cross-platform compatibility (doesn't apply the transformation)
794 | *
795 | * @param skewXDeg Value for the X axis
796 | * @param skewYDeg Value for the Y axis
797 | **/
798 | public function setSkew(skewXDeg:Float, skewYDeg:Float):Void
799 | {
800 | // check null to avoid error on multiplication
801 | var skewXRad:Float=NULL;
802 | var skewYRad:Float=NULL;
803 | if (skewXDeg!=NULL) skewXRad = skewXDeg*DEG2RAD;
804 | if (skewYDeg!=NULL) skewYRad = skewYDeg*DEG2RAD;
805 | setSkewRad(skewXRad,skewYRad);
806 | }
807 |
808 | /**
809 | * Set the skew on the X axis to a given value in Degrees
810 | *
811 | * **NOTE:** It applies an absolute skew on the current matrix
812 | *
813 | * @param skewXDeg Value for the X axis
814 | **/
815 | public function setSkewX(skewXDeg:Float=NULL):Float { setSkew(skewXDeg,NULL); return skewXDeg; }
816 |
817 | /**
818 | * Set the skew on the Y axis to a given value in Degrees
819 | *
820 | * **NOTE:** It applies an absolute skew on the current matrix
821 | *
822 | * @param skewYDeg Value for the Y axis
823 | **/
824 | public function setSkewY(skewYDeg:Float):Float { setSkew(NULL,skewYDeg); return skewYDeg; }
825 |
826 | /**
827 | * Set the skew on the X axis to a given value in Radians
828 | *
829 | * **NOTE:** It applies an absolute skew on the current matrix
830 | *
831 | * @param skewXRad Value for the X axis
832 | **/
833 | public function setSkewXRad(skewXRad:Float):Float { setSkewRad(skewXRad,NULL); return skewXRad; }
834 |
835 | /**
836 | * Set the skew on the Y axis to a given value in Radians
837 | *
838 | * **NOTE:** It applies an absolute skew on the current matrix
839 | *
840 | * @param skewYRad Value for the X axis
841 | **/
842 | public function setSkewYRad(skewYRad:Float):Float { setSkewRad(NULL,skewYRad); return skewYRad; }
843 |
844 | /**
845 | * Apply a skew in Radians
846 | *
847 | * **NOTE:** -0.1 for skewYRad is a null value for cross-platform compatibility (apply the same value on X and Y)
848 | * **NOTE:** 0.0 means no transformation on that axis
849 | *
850 | * @param skewRad Value for the X axis (and Y axis if the skewY is not specified)
851 | * @param skewYRad (optional) Value for the Y axis
852 | **/
853 | public function skewRad(skewRad:Float, ?skewYRad:Float=NULL):Void
854 | {
855 | //get the target matrix to apply the transformation
856 | var m:Matrix = new Matrix();
857 |
858 | var skewXRad:Float = skewRad;
859 | // if not specified it will set the x and y skew using the same value
860 | if (skewYRad==NULL) skewYRad = skewRad;
861 |
862 | // apply the skew (matrix.c is HORIZONTAL, matrix.b is VERTICAL)
863 | if (skewXRad!=0.0) {
864 | m.c = Math.tan(skewXRad);
865 | }
866 | if (skewYRad!=0.0) {
867 | m.b = Math.tan(skewYRad);
868 | }
869 |
870 | //apply the matrix to the target
871 | m.concat(getMatrixInternal());
872 | setMatrixInternal(m,true);
873 | }
874 |
875 | /**
876 | * Apply a skew in Degrees
877 | *
878 | * **NOTE:** -0.1 for skewYDeg is a null value for cross-platform compatibility (apply the same value on X and Y)
879 | * **NOTE:** 0.0 means no transformation on that axis
880 | *
881 | * @param skewDeg Value for the X axis (and Y axis if the skewY is not specified)
882 | * @param skewYDeg (optional) Value for the Y axis
883 | **/
884 | public function skew(skewDeg:Float,?skewYDeg:Float=NULL):Void {
885 | var skewXDeg:Float = skewDeg;
886 | // if not specified it will set the x and y skew using the same value
887 | if (skewYDeg==NULL) skewYDeg = skewDeg;
888 | skewRad(skewXDeg*DEG2RAD,skewYDeg*DEG2RAD);
889 | }
890 |
891 | /**
892 | * Apply a skew on the X axis in Degrees
893 | *
894 | * @param skewXDeg Value for the skew
895 | **/
896 | public function skewX(skewXDeg:Float):Void { skew(skewXDeg,0.0); }
897 |
898 | /**
899 | * Apply a skew on the X axis in Degrees
900 | *
901 | * @param skewYDeg Value for the skew
902 | **/
903 | public function skewY(skewYDeg:Float):Void { skew(0.0,skewYDeg); }
904 |
905 | /**
906 | * Apply a skew on the X axis in Radians
907 | *
908 | * @param skewXRad Value for the skew
909 | **/
910 | public function skewXRad(skewXRad:Float):Void { skewRad(skewXRad,0.0); }
911 |
912 | /**
913 | * Apply a skew on the Y axis in Radians
914 | *
915 | * @param skewYRad Value for the skew
916 | **/
917 | public function skewYRad(skewYRad:Float):Void { skewRad(0.0,skewYRad); }
918 |
919 | /**
920 | * **NOTE:** Could not be reliable if the scale is not uniform
921 | *
922 | * @returns the current skew on the X Axis in Radians
923 | **/
924 | public function getSkewXRad():Float
925 | {
926 | point.x = 0; point.y = 1;
927 | point = deltaTransformPoint(point);
928 | return -(Math.atan2(point.y, point.x) - Math.PI/2);
929 | }
930 |
931 | /**
932 | * **NOTE:** Could not be reliable if the scale is not uniform
933 | *
934 | * @returns the current skew on the Y Axis in Radians
935 | **/
936 | public function getSkewYRad():Float
937 | {
938 | point.x = 1; point.y = 0;
939 | point = deltaTransformPoint(point);
940 | return Math.atan2(point.y, point.x);
941 | }
942 |
943 | /**
944 | * **NOTE:** Could not be reliable if the scale is not uniform
945 | *
946 | * @returns the current skew on the X Axis in Degrees
947 | **/
948 | public function getSkewX():Float { return getSkewXRad()*RAD2DEG; }
949 |
950 | /**
951 | * **NOTE:** Could not be reliable if the scale is not uniform
952 | *
953 | * @returns the current skew on the Y Axis in Degrees
954 | **/
955 | public function getSkewY():Float { return getSkewYRad()*RAD2DEG; }
956 |
957 | /** Use getSkewX and setSkewX **/
958 | public var skewingX(get, set):Float;
959 | private function get_skewingX():Float { return getSkewX(); }
960 | private function set_skewingX(value:Float):Float { return setSkewX(value); }
961 |
962 | /** Use getSkewY and setSkewY **/
963 | public var skewingY(get, set):Float;
964 | private function get_skewingY():Float { return getSkewY(); }
965 | private function set_skewingY(value:Float):Float { return setSkewY(value); }
966 |
967 | /** Use getSkewXRad and setSkewXRad **/
968 | public var skewingXRad(get, set):Float;
969 | private function get_skewingXRad():Float { return getSkewXRad(); }
970 | private function set_skewingXRad(value:Float):Float { return setSkewXRad(value); }
971 |
972 | /** Use getSkewYRad and setSkewYRad **/
973 | public var skewingYRad(get, set):Float;
974 | private function get_skewingYRad():Float { return getSkewYRad(); }
975 | private function set_skewingYRad(value:Float):Float { return setSkewYRad(value); }
976 |
977 |
978 | // SCALE TRANSFORMATION
979 | // #########################################################################
980 |
981 | private var _currentScaleX:Float = 1;
982 | private var _currentScaleY:Float = 1;
983 |
984 | /**
985 | * Apply a scale
986 | *
987 | * **NOTE:** yfactor=-0.1 is a null value for cross-platform compatibility (apply the same factor on x and y)
988 | *
989 | * @param factor Factor for the X axis (and Y axis if the yFactor is not specified)
990 | * @param yFactor (optional) Factor for the Y axis
991 | **/
992 | public function scale(factor:Float=1.0, ?yFactor:Float=NULL):Void
993 | {
994 |
995 | var xFactor:Float = factor;
996 | _currentScaleX*=xFactor;
997 | // if not specified it will scale x and y using the same factor
998 | if (yFactor==NULL) yFactor = factor;
999 | _currentScaleY*=yFactor;
1000 |
1001 | //get the pivot absolute position
1002 | // (keep this BEFORE applying the new matrix to the target)
1003 |
1004 | //get the target matrix to apply the transformation
1005 | var m:Matrix = getMatrixInternal();
1006 |
1007 | // apply the scaling
1008 | m.a *= xFactor;
1009 | m.b *= yFactor;
1010 | m.c *= xFactor;
1011 | m.d *= yFactor;
1012 | m.tx *= xFactor;
1013 | m.ty *= yFactor;
1014 |
1015 | //apply the matrix to the target
1016 | setMatrixInternal(m,true);
1017 |
1018 | }
1019 |
1020 | /**
1021 | * Apply a scale on the X axis
1022 | *
1023 | * @param factor Factor for the X axis
1024 | **/
1025 | public function scaleX(factor:Float=1):Void { scale(factor,1.0); }
1026 |
1027 | /**
1028 | * Apply a scale on the Y axis
1029 | *
1030 | * @param factor Factor for the Y axis
1031 | **/
1032 | public function scaleY(factor:Float=1):Void { scale(1.0,factor); }
1033 |
1034 | /**
1035 | * Set the scale on a given value
1036 | *
1037 | * **NOTE:** scaleY=-0.1 is a null value for cross-platform compatibility (use the same value for x and y)
1038 | *
1039 | * @param value Value for the X axis (and Y axis if the scaleY is not specified)
1040 | * @param scaleY (optional) Value for the Y axis
1041 | **/
1042 | public function setScale(value:Float=1.0, ?scaleY:Float=NULL):Float
1043 | {
1044 |
1045 | var scaleX:Float = value;
1046 | // if not specified it will set the x and y scale using the same value
1047 | if (scaleY==NULL) scaleY = value;
1048 |
1049 | //apply the transformation
1050 | setScaleX(scaleX);
1051 | setScaleY(scaleY);
1052 |
1053 | return value;
1054 |
1055 | }
1056 |
1057 | /**
1058 | * Set the scale for the X axis on a given value
1059 | *
1060 | * @param value Value for the X axis
1061 | **/
1062 | public function setScaleX(scaleX:Float):Float
1063 | {
1064 | var m:Matrix = getMatrixInternal();
1065 | var oldValue:Float = getScaleX();
1066 | // avoid division by zero
1067 | if (oldValue!=0)
1068 | {
1069 | var ratio:Float = scaleX / oldValue;
1070 | m.a *= ratio;
1071 | m.b *= ratio;
1072 | } else {
1073 | var skewYRad:Float = getSkewYRad();
1074 | m.a = Math.cos(skewYRad) * scaleX;
1075 | m.b = Math.sin(skewYRad) * scaleX;
1076 | }
1077 | setMatrixInternal(m,true);
1078 | _currentScaleX = scaleX;
1079 | return scaleX;
1080 | }
1081 |
1082 | /**
1083 | * Set the scale for the Y axis on a given value
1084 | *
1085 | * @param value Value for the Y axis
1086 | **/
1087 | public function setScaleY(scaleY:Float):Float
1088 | {
1089 | var m:Matrix = getMatrixInternal();
1090 | var oldValue:Float = getScaleY();
1091 | // avoid division by zero
1092 | if (oldValue!=0)
1093 | {
1094 | var ratio:Float = scaleY / oldValue;
1095 | m.c *= ratio;
1096 | m.d *= ratio;
1097 | }
1098 | else
1099 | {
1100 | var skewXRad:Float = getSkewXRad();
1101 | m.c = -Math.sin(skewXRad) * scaleY;
1102 | m.d = Math.cos(skewXRad) * scaleY;
1103 | }
1104 | setMatrixInternal(m,true);
1105 | _currentScaleY = scaleY;
1106 | return scaleY;
1107 | }
1108 |
1109 | /**
1110 | * @returns The current scale factor on the X axis
1111 | **/
1112 | public function getScaleX():Float
1113 | {
1114 | return _currentScaleX;
1115 | //return Math.sqrt(_matrix.a*_matrix.a + _matrix.b*_matrix.b);
1116 | }
1117 | /**
1118 | * @returns The current scale factor on the Y axis
1119 | **/
1120 | public function getScaleY():Float
1121 | {
1122 | return _currentScaleY;
1123 | //return Math.sqrt(_matrix.c*_matrix.c + _matrix.d*_matrix.d);
1124 | }
1125 |
1126 | /** Use getScale and setScale **/
1127 | public var scaling(get, set):Float;
1128 | private function get_scaling():Float { return getScaleX(); }
1129 | private function set_scaling(factor:Float):Float { return setScale(factor); }
1130 |
1131 | /** Use getScaleX and setScaleX **/
1132 | public var scalingX(get, set):Float;
1133 | private function get_scalingX():Float { return getScaleX(); }
1134 | private function set_scalingX(factor:Float):Float { return setScaleX(factor); }
1135 |
1136 | // /** Use getScaleY and setScaleY **/
1137 | public var scalingY(get, set):Float;
1138 | private function get_scalingY():Float { return getScaleY(); }
1139 | private function set_scalingY(factor:Float):Float { return setScaleY(factor); }
1140 |
1141 |
1142 |
1143 | // FLIP
1144 | // #########################################################################
1145 |
1146 | /**
1147 | * Apply a flip (mirroring) on the X axis
1148 | **/
1149 | public function flipX():Void { scaleX(-1); }
1150 |
1151 | /**
1152 | * Apply a flip (mirroring) on the Y axis
1153 | **/
1154 | public function flipY():Void { scaleY(-1); }
1155 |
1156 |
1157 | // ROTATE TRANSFORMATION
1158 | // #########################################################################
1159 |
1160 | /**
1161 | * Apply a rotation
1162 | *
1163 | * @param angle The angle in Radians
1164 | **/
1165 | public function rotateRad(angle:Float=0):Void
1166 | {
1167 | //get the pivot absolute position
1168 | var absolutePoint:Point = getPivot();
1169 |
1170 | //get the target matrix to apply the transformation
1171 | var m:Matrix = getMatrixInternal();
1172 |
1173 | //move the target(matrix)
1174 | //the pivot point will match the origin (0,0)
1175 | m.tx-=absolutePoint.x;
1176 | m.ty-=absolutePoint.y;
1177 |
1178 | //rotate the target(matrix)
1179 | // SAME AS m.rotate(angle);
1180 | var sin = Math.sin(angle);
1181 | var cos = Math.cos(angle);
1182 | var a = m.a;
1183 | var b = m.b;
1184 | var c = m.c;
1185 | var d = m.d;
1186 | var tx = m.tx;
1187 | var ty = m.ty;
1188 | m.a = a*cos - b*sin;
1189 | m.b = a*sin + b*cos;
1190 | m.c = c*cos - d*sin;
1191 | m.d = c*sin + d*cos;
1192 | m.tx = tx*cos - ty*sin;
1193 | m.ty = tx*sin + ty*cos;
1194 |
1195 | // restore the target(matrix) position
1196 | m.tx+=absolutePoint.x;
1197 | m.ty+=absolutePoint.y;
1198 |
1199 | //apply the matrix to the target
1200 | setMatrixInternal(m);
1201 | }
1202 |
1203 | /**
1204 | * Apply a rotation
1205 | *
1206 | * @param angle The angle in Degrees
1207 | **/
1208 | public function rotate(angle:Float):Void { rotateRad(angle*DEG2RAD); }
1209 |
1210 | /**
1211 | * Set the rotation on a given value
1212 | *
1213 | * @param angle The absolute angle in Radians
1214 | **/
1215 | public function setRotationRad(angle:Float):Float
1216 | {
1217 | //get the current angle
1218 | var currentRotation:Float = getRotationRad();
1219 |
1220 | //find the complementary angle to reset the rotation to 0
1221 | var resetAngle:Float = -currentRotation;
1222 |
1223 | //reset the rotation
1224 | rotateRad(resetAngle);
1225 |
1226 | //set the new rotation value
1227 | rotateRad(angle);
1228 |
1229 | return angle;
1230 | }
1231 |
1232 | /**
1233 | * Set the rotation on a given value
1234 | *
1235 | * @param angle The absolute angle in Degrees
1236 | **/
1237 | public function setRotation(angle:Float):Float { return setRotationRad(angle*DEG2RAD); }
1238 |
1239 | /**
1240 | * @returns The current angle of rotation in Radians
1241 | **/
1242 | public function getRotationRad():Float
1243 | {
1244 |
1245 | // apply the transformation matrix to a point and
1246 | // calculate the rotation happened
1247 | // thanks to http://stackoverflow.com/users/1035293/bugshake
1248 | var scale:Float;
1249 |
1250 | var m:Matrix = getMatrixInternal();
1251 |
1252 | // extract translation
1253 | point.x = point.y = 0;
1254 | point2 = m.transformPoint(point);
1255 | m.translate( -point2.x, -point2.y);
1256 |
1257 | // extract (uniform) scale...
1258 | point.x = 1; point.y = 0;
1259 | point = m.transformPoint(point);
1260 | scale = point.length;
1261 |
1262 | // ...and rotation
1263 | return Math.atan2(point.y, point.x);
1264 | }
1265 |
1266 | /**
1267 | * @returns The current angle of rotation in Degrees
1268 | **/
1269 | public function getRotation():Float { return getRotationRad() * RAD2DEG; }
1270 |
1271 | /** Use getRotation and setRotation **/
1272 | public var rotation(get, set):Float;
1273 | private function get_rotation():Float { return getRotation(); }
1274 | private function set_rotation(angle:Float):Float { return setRotation(angle); }
1275 |
1276 | /** Use getRotationRad and setRotationRad **/
1277 | public var rotationRad(get, set):Float;
1278 | private function get_rotationRad():Float { return getRotationRad(); }
1279 | private function set_rotationRad(angle:Float):Float { return setRotationRad(angle); }
1280 |
1281 | // #########################################################################
1282 | // #########################################################################
1283 |
1284 | }
1285 |
--------------------------------------------------------------------------------
/docs/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Bootstrap.js by @fat & @mdo
3 | * plugins: bootstrap-transition.js, bootstrap-modal.js, bootstrap-dropdown.js, bootstrap-scrollspy.js, bootstrap-tab.js, bootstrap-tooltip.js, bootstrap-popover.js, bootstrap-affix.js, bootstrap-alert.js, bootstrap-button.js, bootstrap-collapse.js, bootstrap-carousel.js, bootstrap-typeahead.js
4 | * Copyright 2012 Twitter, Inc.
5 | * http://www.apache.org/licenses/LICENSE-2.0.txt
6 | */
7 | !function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){var b=function(b,c){this.options=c,this.$element=a(b).delegate('[data-dismiss="modal"]',"click.dismiss.modal",a.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};b.prototype={constructor:b,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var b=this,c=a.Event("show");this.$element.trigger(c);if(this.isShown||c.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var c=a.support.transition&&b.$element.hasClass("fade");b.$element.parent().length||b.$element.appendTo(document.body),b.$element.show(),c&&b.$element[0].offsetWidth,b.$element.addClass("in").attr("aria-hidden",!1),b.enforceFocus(),c?b.$element.one(a.support.transition.end,function(){b.$element.focus().trigger("shown")}):b.$element.focus().trigger("shown")})},hide:function(b){b&&b.preventDefault();var c=this;b=a.Event("hide"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),a.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var b=this;a(document).on("focusin.modal",function(a){b.$element[0]!==a.target&&!b.$element.has(a.target).length&&b.$element.focus()})},escape:function(){var a=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(b){b.which==27&&a.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),b.hideModal()},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),b.hideModal()})},hideModal:function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('
NOTE: -0.1 for skewYDeg is a null value for cross-platform compatibility (apply the same value on X and Y)
57 | NOTE: 0.0 means no transformation on that axis
Parameters:
skewDeg
Value for the X axis (and Y axis if the skewY is not specified)
NOTE: -0.1 for skewYRad is a null value for cross-platform compatibility (apply the same value on X and Y)
59 | NOTE: 0.0 means no transformation on that axis
Parameters:
skewRad
Value for the X axis (and Y axis if the skewY is not specified)
When the size is changed externally of the Transformation class
60 | * you should use this method to update the size internally
61 |
example:* a textfield object with text changed will change size
62 |
* but the Transformation class can't be aware of that if you don't
63 |
64 |
call this method
65 |
66 | ----
67 |
68 | Otherwise you can set the size to arbitrary values if you want to
69 | set a certain AnchoredPivot based on the rect you specify