RectTransformData.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Serialization;
  4. namespace TheraBytes.BetterUi
  5. {
  6. [Serializable]
  7. public class RectTransformData : IScreenConfigConnection
  8. {
  9. public static readonly RectTransformData Invalid = new RectTransformData();
  10. public static readonly RectTransformData Identity = new RectTransformData()
  11. {
  12. Rotation = Quaternion.identity,
  13. Scale = Vector3.one,
  14. };
  15. public Vector3 LocalPosition;
  16. public Vector2 AnchoredPosition;
  17. public Vector2 SizeDelta;
  18. public Vector2 AnchorMin;
  19. public Vector2 AnchorMax;
  20. public Vector2 Pivot;
  21. public Vector3 Scale;
  22. [FormerlySerializedAs("Rotation")]
  23. [SerializeField]
  24. Quaternion rotation;
  25. public Vector3 EulerAngles;
  26. public Quaternion Rotation
  27. {
  28. get
  29. {
  30. return (saveRotationAsEuler) ? Quaternion.Euler(EulerAngles) : rotation;
  31. }
  32. set
  33. {
  34. rotation = value;
  35. if (saveRotationAsEuler)
  36. {
  37. EulerAngles = rotation.eulerAngles;
  38. }
  39. }
  40. }
  41. [SerializeField]
  42. bool saveRotationAsEuler = false;
  43. public bool SaveRotationAsEuler
  44. {
  45. get
  46. {
  47. return saveRotationAsEuler;
  48. }
  49. set
  50. {
  51. if (saveRotationAsEuler == value)
  52. return;
  53. saveRotationAsEuler = value;
  54. }
  55. }
  56. /// <summary>
  57. /// <para>The offset of the upper right corner of the rectangle relative to the upper right anchor.</para>
  58. /// </summary>
  59. public Vector2 OffsetMax
  60. {
  61. get
  62. {
  63. return this.AnchoredPosition + Vector2.Scale(this.SizeDelta, Vector2.one - this.Pivot);
  64. }
  65. set
  66. {
  67. Vector2 v = value - (this.AnchoredPosition + Vector2.Scale(this.SizeDelta, Vector2.one - this.Pivot));
  68. this.SizeDelta = this.SizeDelta + v;
  69. this.AnchoredPosition = this.AnchoredPosition + Vector2.Scale(v, this.Pivot);
  70. }
  71. }
  72. /// <summary>
  73. /// <para>The offset of the lower left corner of the rectangle relative to the lower left anchor.</para>
  74. /// </summary>
  75. public Vector2 OffsetMin
  76. {
  77. get
  78. {
  79. return this.AnchoredPosition - Vector2.Scale(this.SizeDelta, this.Pivot);
  80. }
  81. set
  82. {
  83. Vector2 v = value - (this.AnchoredPosition - Vector2.Scale(this.SizeDelta, this.Pivot));
  84. this.SizeDelta = this.SizeDelta - v;
  85. this.AnchoredPosition = this.AnchoredPosition + Vector2.Scale(v, Vector2.one - this.Pivot);
  86. }
  87. }
  88. [SerializeField]
  89. string screenConfigName;
  90. public string ScreenConfigName { get { return screenConfigName; } set { screenConfigName = value; } }
  91. public RectTransformData()
  92. {
  93. }
  94. public RectTransformData(RectTransform rectTransform)
  95. {
  96. PullFromTransform(rectTransform);
  97. }
  98. public static RectTransformData Combine(RectTransformData original, RectTransformData addition)
  99. {
  100. RectTransformData result = new RectTransformData();
  101. result.AnchoredPosition = original.AnchoredPosition + addition.AnchoredPosition;
  102. result.AnchorMin = original.AnchorMin + addition.AnchorMin;
  103. result.AnchorMax = original.AnchorMax + addition.AnchorMax;
  104. result.Pivot = original.Pivot + addition.Pivot;
  105. result.SizeDelta = original.SizeDelta + addition.SizeDelta;
  106. result.LocalPosition = original.LocalPosition + addition.LocalPosition;
  107. result.Scale = new Vector3(
  108. original.Scale.x * addition.Scale.x,
  109. original.Scale.y * addition.Scale.y,
  110. original.Scale.z * addition.Scale.z);
  111. result.saveRotationAsEuler = original.saveRotationAsEuler;
  112. result.Rotation = original.Rotation * addition.Rotation;
  113. return result;
  114. }
  115. public static RectTransformData Separate(RectTransformData original, RectTransformData subtraction)
  116. {
  117. RectTransformData result = new RectTransformData();
  118. result.AnchoredPosition = original.AnchoredPosition - subtraction.AnchoredPosition;
  119. result.AnchorMin = original.AnchorMin - subtraction.AnchorMin;
  120. result.AnchorMax = original.AnchorMax - subtraction.AnchorMax;
  121. result.Pivot = original.Pivot - subtraction.Pivot;
  122. result.SizeDelta = original.SizeDelta - subtraction.SizeDelta;
  123. result.LocalPosition = original.LocalPosition - subtraction.LocalPosition;
  124. result.Scale = new Vector3(
  125. original.Scale.x / subtraction.Scale.x,
  126. original.Scale.y / subtraction.Scale.y,
  127. original.Scale.z / subtraction.Scale.z);
  128. result.saveRotationAsEuler = original.saveRotationAsEuler;
  129. result.Rotation = original.Rotation * Quaternion.Inverse(subtraction.Rotation);
  130. return result;
  131. }
  132. public RectTransformData PullFromData(RectTransformData transformData)
  133. {
  134. this.LocalPosition = transformData.LocalPosition;
  135. this.AnchorMin = transformData.AnchorMin;
  136. this.AnchorMax = transformData.AnchorMax;
  137. this.Pivot = transformData.Pivot;
  138. this.AnchoredPosition = transformData.AnchoredPosition;
  139. this.SizeDelta = transformData.SizeDelta;
  140. this.Scale = transformData.Scale;
  141. this.saveRotationAsEuler = transformData.saveRotationAsEuler;
  142. this.Rotation = transformData.Rotation;
  143. this.EulerAngles = transformData.EulerAngles;
  144. return this;
  145. }
  146. public void PullFromTransform(RectTransform transform)
  147. {
  148. this.LocalPosition = transform.localPosition;
  149. this.AnchorMin = transform.anchorMin;
  150. this.AnchorMax = transform.anchorMax;
  151. this.Pivot = transform.pivot;
  152. this.AnchoredPosition = transform.anchoredPosition;
  153. this.SizeDelta = transform.sizeDelta;
  154. this.Scale = transform.localScale;
  155. this.Rotation = transform.localRotation;
  156. this.EulerAngles = transform.localEulerAngles;
  157. }
  158. public void PushToTransform(RectTransform transform)
  159. {
  160. transform.localPosition = this.LocalPosition;
  161. transform.anchorMin = this.AnchorMin;
  162. transform.anchorMax = this.AnchorMax;
  163. transform.pivot = this.Pivot;
  164. transform.anchoredPosition = this.AnchoredPosition;
  165. transform.sizeDelta = this.SizeDelta;
  166. transform.localScale = this.Scale;
  167. if (SaveRotationAsEuler)
  168. {
  169. transform.eulerAngles = this.EulerAngles;
  170. }
  171. else
  172. {
  173. transform.localRotation = this.Rotation;
  174. }
  175. }
  176. public Rect ToRect(Rect parentRect, bool relativeSpace = false)
  177. {
  178. float xMin = (AnchorMin.x * parentRect.width) + AnchoredPosition.x - Pivot.x * SizeDelta.x;
  179. float xMax = (AnchorMax.x * parentRect.width) + AnchoredPosition.x + (1 - Pivot.x) * SizeDelta.x;
  180. float yMin = (AnchorMin.y * parentRect.height) + AnchoredPosition.y - Pivot.y * SizeDelta.y;
  181. float yMax = (AnchorMax.y * parentRect.height) + AnchoredPosition.y + (1 - Pivot.y) * SizeDelta.y;
  182. if(relativeSpace)
  183. {
  184. xMin /= parentRect.width;
  185. xMax /= parentRect.width;
  186. yMin /= parentRect.height;
  187. yMax /= parentRect.height;
  188. }
  189. return new Rect(xMin, yMin, xMax - xMin, yMax - yMin);
  190. }
  191. public static RectTransformData Lerp(RectTransformData a, RectTransformData b, float amount)
  192. {
  193. return Lerp(a, b, amount, a.SaveRotationAsEuler || b.SaveRotationAsEuler);
  194. }
  195. public static RectTransformData Lerp(RectTransformData a, RectTransformData b, float amount, bool eulerRotation)
  196. {
  197. return new RectTransformData()
  198. {
  199. AnchoredPosition = Vector2.Lerp(a.AnchoredPosition, b.AnchoredPosition, amount),
  200. AnchorMax = Vector2.Lerp(a.AnchorMax, b.AnchorMax, amount),
  201. AnchorMin = Vector2.Lerp(a.AnchorMin, b.AnchorMin, amount),
  202. LocalPosition = Vector3.Lerp(a.LocalPosition, b.LocalPosition, amount),
  203. Pivot = Vector2.Lerp(a.Pivot, b.Pivot, amount),
  204. Scale = Vector3.Lerp(a.Scale, b.Scale, amount),
  205. SizeDelta = Vector2.Lerp(a.SizeDelta, b.SizeDelta, amount),
  206. Rotation = Quaternion.Lerp(a.Rotation, b.Rotation, amount),
  207. EulerAngles = Vector3.Lerp(a.EulerAngles, b.EulerAngles, amount),
  208. SaveRotationAsEuler = eulerRotation
  209. };
  210. }
  211. public static RectTransformData LerpUnclamped(RectTransformData a, RectTransformData b, float amount)
  212. {
  213. return LerpUnclamped(a, b, amount, a.SaveRotationAsEuler || b.SaveRotationAsEuler);
  214. }
  215. public static RectTransformData LerpUnclamped(RectTransformData a, RectTransformData b, float amount, bool eulerRotation)
  216. {
  217. return new RectTransformData()
  218. {
  219. AnchoredPosition = Vector2.LerpUnclamped(a.AnchoredPosition, b.AnchoredPosition, amount),
  220. AnchorMax = Vector2.LerpUnclamped(a.AnchorMax, b.AnchorMax, amount),
  221. AnchorMin = Vector2.LerpUnclamped(a.AnchorMin, b.AnchorMin, amount),
  222. LocalPosition = Vector3.LerpUnclamped(a.LocalPosition, b.LocalPosition, amount),
  223. Pivot = Vector2.LerpUnclamped(a.Pivot, b.Pivot, amount),
  224. Scale = Vector3.LerpUnclamped(a.Scale, b.Scale, amount),
  225. SizeDelta = Vector2.LerpUnclamped(a.SizeDelta, b.SizeDelta, amount),
  226. Rotation = Quaternion.LerpUnclamped(a.Rotation, b.Rotation, amount),
  227. EulerAngles = Vector3.LerpUnclamped(a.EulerAngles, b.EulerAngles, amount),
  228. SaveRotationAsEuler = eulerRotation
  229. };
  230. }
  231. public override int GetHashCode()
  232. {
  233. return this.AnchoredPosition.GetHashCode()
  234. ^ this.AnchorMin.GetHashCode()
  235. ^ this.AnchorMax.GetHashCode()
  236. ^ this.LocalPosition.GetHashCode()
  237. ^ this.Pivot.GetHashCode()
  238. ^ this.Scale.GetHashCode()
  239. ^ this.SizeDelta.GetHashCode()
  240. ^ this.rotation.GetHashCode()
  241. ^ this.saveRotationAsEuler.GetHashCode()
  242. ^ this.EulerAngles.GetHashCode();
  243. }
  244. public override bool Equals(object obj)
  245. {
  246. return this.GetHashCode() == obj.GetHashCode();
  247. }
  248. public static bool operator ==(RectTransformData a, RectTransformData b)
  249. {
  250. bool aIsNull = ReferenceEquals(a, null);
  251. bool bIsNull = ReferenceEquals(b, null);
  252. if (aIsNull || bIsNull)
  253. return aIsNull && bIsNull;
  254. return a.AnchoredPosition == b.AnchoredPosition
  255. && a.AnchorMin == b.AnchorMin
  256. && a.AnchorMax == b.AnchorMax
  257. && a.Pivot == b.Pivot
  258. && a.SizeDelta == b.SizeDelta
  259. && a.LocalPosition == b.LocalPosition
  260. && a.Scale == b.Scale
  261. && a.Rotation.Equals(b.Rotation);
  262. }
  263. public static bool operator !=(RectTransformData a, RectTransformData b)
  264. {
  265. return !(a == b);
  266. }
  267. public override string ToString()
  268. {
  269. return string.Format("RectTransformData: sizeDelta {{{0}, {1}}} - anchoredPosition {{{2}, {3}}}",
  270. SizeDelta.x, SizeDelta.y, AnchoredPosition.x, AnchoredPosition.y);
  271. }
  272. }
  273. }