Transform.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. import { ObservablePoint } from './ObservablePoint';
  6. import { Matrix } from './Matrix';
  7. /**
  8. * Transform that takes care about its versions
  9. *
  10. * @class
  11. * @memberof PIXI
  12. */
  13. export class Transform {
  14. /**
  15. * A default (identity) transform
  16. *
  17. * @static
  18. * @constant
  19. * @member {PIXI.Transform}
  20. */
  21. public static readonly IDENTITY = new Transform();
  22. public worldTransform: Matrix;
  23. public localTransform: Matrix;
  24. public position: ObservablePoint;
  25. public scale: ObservablePoint;
  26. public pivot: ObservablePoint;
  27. public skew: ObservablePoint;
  28. public _parentID: number;
  29. _worldID: number;
  30. protected _rotation: number;
  31. protected _cx: number;
  32. protected _sx: number;
  33. protected _cy: number;
  34. protected _sy: number;
  35. protected _localID: number;
  36. protected _currentLocalID: number;
  37. constructor() {
  38. /**
  39. * The world transformation matrix.
  40. *
  41. * @member {PIXI.Matrix}
  42. */
  43. this.worldTransform = new Matrix();
  44. /**
  45. * The local transformation matrix.
  46. *
  47. * @member {PIXI.Matrix}
  48. */
  49. this.localTransform = new Matrix();
  50. /**
  51. * The coordinate of the object relative to the local coordinates of the parent.
  52. *
  53. * @member {PIXI.ObservablePoint}
  54. */
  55. this.position = new ObservablePoint(this.onChange, this, 0, 0);
  56. /**
  57. * The scale factor of the object.
  58. *
  59. * @member {PIXI.ObservablePoint}
  60. */
  61. this.scale = new ObservablePoint(this.onChange, this, 1, 1);
  62. /**
  63. * The pivot point of the displayObject that it rotates around.
  64. *
  65. * @member {PIXI.ObservablePoint}
  66. */
  67. this.pivot = new ObservablePoint(this.onChange, this, 0, 0);
  68. /**
  69. * The skew amount, on the x and y axis.
  70. *
  71. * @member {PIXI.ObservablePoint}
  72. */
  73. this.skew = new ObservablePoint(this.updateSkew, this, 0, 0);
  74. /**
  75. * The rotation amount.
  76. *
  77. * @protected
  78. * @member {number}
  79. */
  80. this._rotation = 0;
  81. /**
  82. * The X-coordinate value of the normalized local X axis,
  83. * the first column of the local transformation matrix without a scale.
  84. *
  85. * @protected
  86. * @member {number}
  87. */
  88. this._cx = 1;
  89. /**
  90. * The Y-coordinate value of the normalized local X axis,
  91. * the first column of the local transformation matrix without a scale.
  92. *
  93. * @protected
  94. * @member {number}
  95. */
  96. this._sx = 0;
  97. /**
  98. * The X-coordinate value of the normalized local Y axis,
  99. * the second column of the local transformation matrix without a scale.
  100. *
  101. * @protected
  102. * @member {number}
  103. */
  104. this._cy = 0;
  105. /**
  106. * The Y-coordinate value of the normalized local Y axis,
  107. * the second column of the local transformation matrix without a scale.
  108. *
  109. * @protected
  110. * @member {number}
  111. */
  112. this._sy = 1;
  113. /**
  114. * The locally unique ID of the local transform.
  115. *
  116. * @protected
  117. * @member {number}
  118. */
  119. this._localID = 0;
  120. /**
  121. * The locally unique ID of the local transform
  122. * used to calculate the current local transformation matrix.
  123. *
  124. * @protected
  125. * @member {number}
  126. */
  127. this._currentLocalID = 0;
  128. /**
  129. * The locally unique ID of the world transform.
  130. *
  131. * @protected
  132. * @member {number}
  133. */
  134. this._worldID = 0;
  135. /**
  136. * The locally unique ID of the parent's world transform
  137. * used to calculate the current world transformation matrix.
  138. *
  139. * @protected
  140. * @member {number}
  141. */
  142. this._parentID = 0;
  143. }
  144. /**
  145. * Called when a value changes.
  146. *
  147. * @protected
  148. */
  149. protected onChange(): void {
  150. this._localID++;
  151. }
  152. /**
  153. * Called when the skew or the rotation changes.
  154. *
  155. * @protected
  156. */
  157. protected updateSkew(): void {
  158. this._cx = Math.cos(this._rotation + this.skew.y);
  159. this._sx = Math.sin(this._rotation + this.skew.y);
  160. this._cy = -Math.sin(this._rotation - this.skew.x); // cos, added PI/2
  161. this._sy = Math.cos(this._rotation - this.skew.x); // sin, added PI/2
  162. this._localID++;
  163. }
  164. /**
  165. * Updates the local transformation matrix.
  166. */
  167. updateLocalTransform(): void {
  168. const lt = this.localTransform;
  169. if (this._localID !== this._currentLocalID) {
  170. // get the matrix values of the displayobject based on its transform properties..
  171. lt.a = this._cx * this.scale.x;
  172. lt.b = this._sx * this.scale.x;
  173. lt.c = this._cy * this.scale.y;
  174. lt.d = this._sy * this.scale.y;
  175. lt.tx = this.position.x - (this.pivot.x * lt.a + this.pivot.y * lt.c);
  176. lt.ty = this.position.y - (this.pivot.x * lt.b + this.pivot.y * lt.d);
  177. this._currentLocalID = this._localID;
  178. // force an update..
  179. this._parentID = -1;
  180. }
  181. }
  182. /**
  183. * Updates the local and the world transformation matrices.
  184. *
  185. * @param {PIXI.Transform} parentTransform - The parent transform
  186. */
  187. updateTransform(parentTransform: Transform): void {
  188. const lt = this.localTransform;
  189. if (this._localID !== this._currentLocalID) {
  190. // get the matrix values of the displayobject based on its transform properties..
  191. lt.a = this._cx * this.scale.x;
  192. lt.b = this._sx * this.scale.x;
  193. lt.c = this._cy * this.scale.y;
  194. lt.d = this._sy * this.scale.y;
  195. lt.tx = this.position.x - (this.pivot.x * lt.a + this.pivot.y * lt.c);
  196. lt.ty = this.position.y - (this.pivot.x * lt.b + this.pivot.y * lt.d);
  197. this._currentLocalID = this._localID;
  198. // force an update..
  199. this._parentID = -1;
  200. }
  201. if (this._parentID !== parentTransform._worldID) {
  202. // concat the parent matrix with the objects transform.
  203. const pt = parentTransform.worldTransform;
  204. const wt = this.worldTransform;
  205. wt.a = lt.a * pt.a + lt.b * pt.c;
  206. wt.b = lt.a * pt.b + lt.b * pt.d;
  207. wt.c = lt.c * pt.a + lt.d * pt.c;
  208. wt.d = lt.c * pt.b + lt.d * pt.d;
  209. wt.tx = lt.tx * pt.a + lt.ty * pt.c + pt.tx;
  210. wt.ty = lt.tx * pt.b + lt.ty * pt.d + pt.ty;
  211. this._parentID = parentTransform._worldID;
  212. // update the id of the transform..
  213. this._worldID++;
  214. }
  215. }
  216. /**
  217. * Decomposes a matrix and sets the transforms properties based on it.
  218. *
  219. * @param {PIXI.Matrix} matrix - The matrix to decompose
  220. */
  221. setFromMatrix(matrix: Matrix): void {
  222. matrix.decompose(this);
  223. this._localID++;
  224. }
  225. /**
  226. * The rotation of the object in radians.
  227. *
  228. * @member {number}
  229. */
  230. get rotation(): number {
  231. return this._rotation;
  232. }
  233. set rotation(value: number) {
  234. if (this._rotation !== value) {
  235. this._rotation = value;
  236. this.updateSkew();
  237. }
  238. }
  239. }