OVROverlayEditor.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. [CustomEditor(typeof(OVROverlay))]
  6. public class OVROverlayEditor : Editor
  7. {
  8. /// <summary>
  9. /// Common Video Types, to ease source and dest rect creation
  10. /// </summary>
  11. public enum StereoType
  12. {
  13. Custom = 0,
  14. Mono = 1,
  15. Stereo = 2,
  16. StereoLeftRight = 3,
  17. StereoTopBottom = 4,
  18. }
  19. public enum DisplayType
  20. {
  21. Custom = 0,
  22. Full = 1,
  23. Half = 2
  24. }
  25. private bool sourceRectsVisible = false;
  26. private bool destRectsVisible = false;
  27. private Material _SrcRectMaterial;
  28. protected Material SrcRectMaterial
  29. {
  30. get
  31. {
  32. if (_SrcRectMaterial == null)
  33. {
  34. string[] shaders = AssetDatabase.FindAssets("OVROverlaySrcRectEditor");
  35. if (shaders.Length > 0)
  36. {
  37. Shader shader = (Shader)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(shaders[0]), typeof(Shader));
  38. if (shader != null)
  39. {
  40. _SrcRectMaterial = new Material(shader);
  41. }
  42. }
  43. }
  44. return _SrcRectMaterial;
  45. }
  46. }
  47. private Material _DestRectMaterial;
  48. protected Material DestRectMaterial
  49. {
  50. get
  51. {
  52. if (_DestRectMaterial == null)
  53. {
  54. string[] shaders = AssetDatabase.FindAssets("OVROverlayDestRectEditor");
  55. if (shaders.Length > 0)
  56. {
  57. Shader shader = (Shader)AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(shaders[0]), typeof(Shader));
  58. if (shader != null)
  59. {
  60. _DestRectMaterial = new Material(shader);
  61. }
  62. }
  63. }
  64. return _DestRectMaterial;
  65. }
  66. }
  67. private TextureRect _DraggingRect;
  68. private Side _DraggingSide;
  69. enum TextureRect
  70. {
  71. None,
  72. SrcLeft,
  73. SrcRight,
  74. DestLeft,
  75. DestRight
  76. }
  77. enum Side
  78. {
  79. Left,
  80. Right,
  81. Top,
  82. Bottom
  83. }
  84. public override void OnInspectorGUI()
  85. {
  86. OVROverlay overlay = (OVROverlay)target;
  87. if (overlay == null)
  88. {
  89. return;
  90. }
  91. EditorGUILayout.LabelField("Display Order", EditorStyles.boldLabel);
  92. overlay.currentOverlayType = (OVROverlay.OverlayType)EditorGUILayout.EnumPopup(new GUIContent("Current Overlay Type", "Whether this overlay should layer behind the scene or in front of it"), overlay.currentOverlayType);
  93. overlay.compositionDepth = EditorGUILayout.IntField(new GUIContent("Composition Depth", "Depth value used to sort OVROverlays in the scene, smaller value appears in front"), overlay.compositionDepth);
  94. overlay.noDepthBufferTesting = EditorGUILayout.Toggle(new GUIContent("No Depth Buffer Testing", "The noDepthBufferTesting will stop layer's depth buffer compositing even if the engine has \"Shared Depth Buffer\" enabled"), overlay.noDepthBufferTesting);
  95. EditorGUILayout.Space();
  96. EditorGUILayout.LabelField(new GUIContent("Overlay Shape", "The shape of this overlay"), EditorStyles.boldLabel);
  97. overlay.currentOverlayShape = (OVROverlay.OverlayShape)EditorGUILayout.EnumPopup(new GUIContent("Overlay Shape", "The shape of this overlay"), overlay.currentOverlayShape);
  98. EditorGUILayout.Space();
  99. EditorGUILayout.Separator();
  100. EditorGUILayout.LabelField("Textures", EditorStyles.boldLabel);
  101. #if UNITY_ANDROID
  102. bool lastIsExternalSurface = overlay.isExternalSurface;
  103. overlay.isExternalSurface = EditorGUILayout.Toggle(new GUIContent("Is External Surface", "On Android, retrieve an Android Surface object to render to (e.g., video playback)"), overlay.isExternalSurface);
  104. if (lastIsExternalSurface)
  105. {
  106. overlay.externalSurfaceWidth = EditorGUILayout.IntField("External Surface Width", overlay.externalSurfaceWidth);
  107. overlay.externalSurfaceHeight = EditorGUILayout.IntField("External Surface Height", overlay.externalSurfaceHeight);
  108. overlay.isProtectedContent = EditorGUILayout.Toggle(new GUIContent("Is Protected Content", "The external surface has L1 widevine protection."), overlay.isProtectedContent);
  109. }
  110. else
  111. #endif
  112. {
  113. if (overlay.textures == null)
  114. {
  115. overlay.textures = new Texture[2];
  116. }
  117. if (overlay.textures.Length < 2)
  118. {
  119. Texture[] tmp = new Texture[2];
  120. for (int i = 0; i < overlay.textures.Length; i++)
  121. {
  122. tmp[i] = overlay.textures[i];
  123. }
  124. overlay.textures = tmp;
  125. }
  126. var labelControlRect = EditorGUILayout.GetControlRect();
  127. EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left Texture", "Texture used for the left eye"));
  128. EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right Texture", "Texture used for the right eye"));
  129. var textureControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(64));
  130. overlay.textures[0] = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x, textureControlRect.y, 64, textureControlRect.height), overlay.textures[0], typeof(Texture), true);
  131. Texture right = (Texture)EditorGUI.ObjectField(new Rect(textureControlRect.x + textureControlRect.width / 2, textureControlRect.y, 64, textureControlRect.height), overlay.textures[1] != null ? overlay.textures[1] : overlay.textures[0], typeof(Texture), true);
  132. if (right == overlay.textures[0])
  133. {
  134. overlay.textures[1] = null;
  135. }
  136. else
  137. {
  138. overlay.textures[1] = right;
  139. }
  140. overlay.isDynamic = EditorGUILayout.Toggle(new GUIContent("Dynamic Texture", "This texture will be updated dynamically at runtime (e.g., Video)"), overlay.isDynamic);
  141. #if !UNITY_ANDROID
  142. overlay.isProtectedContent = EditorGUILayout.Toggle(new GUIContent("Is Protected Content", "The texture has copy protection, e.g., HDCP"), overlay.isProtectedContent);
  143. #endif
  144. }
  145. if (overlay.currentOverlayShape == OVROverlay.OverlayShape.Cylinder || overlay.currentOverlayShape == OVROverlay.OverlayShape.Equirect || overlay.currentOverlayShape == OVROverlay.OverlayShape.Quad) {
  146. EditorGUILayout.Separator();
  147. EditorGUILayout.Space();
  148. EditorGUILayout.LabelField("Texture Rects", EditorStyles.boldLabel);
  149. bool lastOverrideTextureRectMatrix = overlay.overrideTextureRectMatrix;
  150. overlay.overrideTextureRectMatrix = !EditorGUILayout.Toggle(new GUIContent("Use Default Rects", overlay.textures[1] == null ? "If you need to use a single texture as a stereo image, uncheck this box" : "Uncheck this box if you need to clip you textures or layer"), !overlay.overrideTextureRectMatrix);
  151. if (lastOverrideTextureRectMatrix)
  152. {
  153. sourceRectsVisible = EditorGUILayout.Foldout(sourceRectsVisible, new GUIContent("Source Rects", "What portion of the source texture will ultimately be shown in each eye."));
  154. if (sourceRectsVisible)
  155. {
  156. var mat = SrcRectMaterial;
  157. if (mat != null)
  158. {
  159. Rect drawRect = EditorGUILayout.GetControlRect(GUILayout.Height(128 + 8));
  160. mat.SetVector("_SrcRectLeft", new Vector4(Mathf.Max(0.0f, overlay.srcRectLeft.x), Mathf.Max(0.0f, overlay.srcRectLeft.y), Mathf.Min(1.0f - overlay.srcRectLeft.x, overlay.srcRectLeft.width), Mathf.Min(1.0f - overlay.srcRectLeft.y, overlay.srcRectLeft.height)));
  161. mat.SetVector("_SrcRectRight", new Vector4(Mathf.Max(0.0f, overlay.srcRectRight.x), Mathf.Max(0.0f, overlay.srcRectRight.y), Mathf.Min(1.0f - overlay.srcRectRight.x, overlay.srcRectRight.width), Mathf.Min(1.0f - overlay.srcRectRight.y, overlay.srcRectRight.height)));
  162. // center our draw rect
  163. var drawRectCentered = new Rect(drawRect.x + drawRect.width / 2 - 128 - 4, drawRect.y, 256 + 8, drawRect.height);
  164. EditorGUI.DrawPreviewTexture(drawRectCentered, overlay.textures[0] ?? Texture2D.blackTexture, mat);
  165. var drawRectInset = new Rect(drawRectCentered.x + 4, drawRectCentered.y + 4, drawRectCentered.width - 8, drawRectCentered.height - 8);
  166. UpdateRectDragging(drawRectInset, drawRectInset, TextureRect.SrcLeft, TextureRect.SrcRight, ref overlay.srcRectLeft, ref overlay.srcRectRight);
  167. CreateCursorRects(drawRectInset, overlay.srcRectLeft);
  168. CreateCursorRects(drawRectInset, overlay.srcRectRight);
  169. }
  170. var labelControlRect = EditorGUILayout.GetControlRect();
  171. EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left Source Rect", "The rect in the source image that will be displayed on the left eye layer"));
  172. EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right Source Rect", "The rect in the source image that will be displayed on the right eye layer"));
  173. var rectControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(34));
  174. overlay.srcRectLeft = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.srcRectLeft));
  175. overlay.srcRectRight = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x + rectControlRect.width / 2, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.srcRectRight));
  176. EditorGUILayout.BeginHorizontal();
  177. if (overlay.textures[1] != null)
  178. {
  179. if (GUILayout.Button(new GUIContent("Reset To Default", "Reset Source Rects to default")))
  180. {
  181. SetRectsByVideoType(overlay, StereoType.Stereo, DisplayType.Custom);
  182. }
  183. }
  184. else
  185. {
  186. if (GUILayout.Button(new GUIContent("Monoscopic", "Display the full Texture in both eyes")))
  187. {
  188. SetRectsByVideoType(overlay, StereoType.Mono, DisplayType.Custom);
  189. }
  190. if (GUILayout.Button(new GUIContent("Stereo Left/Right", "The left half of the texture is displayed in the left eye, and the right half in the right eye")))
  191. {
  192. SetRectsByVideoType(overlay, StereoType.StereoLeftRight, DisplayType.Custom);
  193. }
  194. if (GUILayout.Button(new GUIContent("Stereo Top/Bottom", "The top half of the texture is displayed in the left eye, and the bottom half in the right eye")))
  195. {
  196. SetRectsByVideoType(overlay, StereoType.StereoTopBottom, DisplayType.Custom);
  197. }
  198. }
  199. EditorGUILayout.EndHorizontal();
  200. }
  201. destRectsVisible = EditorGUILayout.Foldout(destRectsVisible, new GUIContent("Destination Rects", "What portion of the destination texture that the source will be rendered into."));
  202. if (destRectsVisible)
  203. {
  204. var mat = DestRectMaterial;
  205. if (mat != null)
  206. {
  207. Rect drawRect = EditorGUILayout.GetControlRect(GUILayout.Height(128 + 8));
  208. mat.SetVector("_SrcRectLeft", new Vector4(Mathf.Max(0.0f, overlay.srcRectLeft.x), Mathf.Max(0.0f, overlay.srcRectLeft.y), Mathf.Min(1.0f - overlay.srcRectLeft.x, overlay.srcRectLeft.width), Mathf.Min(1.0f - overlay.srcRectLeft.y, overlay.srcRectLeft.height)));
  209. mat.SetVector("_SrcRectRight", new Vector4(Mathf.Max(0.0f, overlay.srcRectRight.x), Mathf.Max(0.0f, overlay.srcRectRight.y), Mathf.Min(1.0f - overlay.srcRectRight.x, overlay.srcRectRight.width), Mathf.Min(1.0f - overlay.srcRectRight.y, overlay.srcRectRight.height)));
  210. mat.SetVector("_DestRectLeft", new Vector4(Mathf.Max(0.0f, overlay.destRectLeft.x), Mathf.Max(0.0f, overlay.destRectLeft.y), Mathf.Min(1.0f - overlay.destRectLeft.x, overlay.destRectLeft.width), Mathf.Min(1.0f - overlay.destRectLeft.y, overlay.destRectLeft.height)));
  211. mat.SetVector("_DestRectRight", new Vector4(Mathf.Max(0.0f, overlay.destRectRight.x), Mathf.Max(0.0f, overlay.destRectRight.y), Mathf.Min(1.0f - overlay.destRectRight.x, overlay.destRectRight.width), Mathf.Min(1.0f - overlay.destRectRight.y, overlay.destRectRight.height)));
  212. mat.SetColor("_BackgroundColor", EditorGUIUtility.isProSkin ? (Color)new Color32(56, 56, 56, 255) : (Color)new Color32(194, 194, 194, 255));
  213. var drawRectCentered = new Rect(drawRect.x + drawRect.width / 2 - 128 - 16 - 4, drawRect.y, 256 + 32 + 8, drawRect.height);
  214. // center our draw rect
  215. EditorGUI.DrawPreviewTexture(drawRectCentered, overlay.textures[0] ?? Texture2D.blackTexture, mat);
  216. var drawRectInsetLeft = new Rect(drawRectCentered.x + 4, drawRectCentered.y + 4, drawRectCentered.width / 2 - 20, drawRectCentered.height - 8);
  217. var drawRectInsetRight = new Rect(drawRectCentered.x + drawRectCentered.width / 2 + 16, drawRectCentered.y + 4, drawRectCentered.width / 2 - 20, drawRectCentered.height - 8);
  218. UpdateRectDragging(drawRectInsetLeft, drawRectInsetRight, TextureRect.DestLeft, TextureRect.DestRight, ref overlay.destRectLeft, ref overlay.destRectRight);
  219. CreateCursorRects(drawRectInsetLeft, overlay.destRectLeft);
  220. CreateCursorRects(drawRectInsetRight, overlay.destRectRight);
  221. }
  222. var labelControlRect = EditorGUILayout.GetControlRect();
  223. EditorGUI.LabelField(new Rect(labelControlRect.x, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Left Destination Rect", "The rect in the destination layer the left eye will display to"));
  224. EditorGUI.LabelField(new Rect(labelControlRect.x + labelControlRect.width / 2, labelControlRect.y, labelControlRect.width / 2, labelControlRect.height), new GUIContent("Right Destination Rect", "The rect in the destination layer the right eye will display to"));
  225. var rectControlRect = EditorGUILayout.GetControlRect(GUILayout.Height(34));
  226. overlay.destRectLeft = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.destRectLeft));
  227. overlay.destRectRight = Clamp01(EditorGUI.RectField(new Rect(rectControlRect.x + rectControlRect.width / 2, rectControlRect.y, rectControlRect.width / 2 - 20, rectControlRect.height), overlay.destRectRight));
  228. if (overlay.currentOverlayShape == OVROverlay.OverlayShape.Equirect)
  229. {
  230. EditorGUILayout.BeginHorizontal();
  231. if (GUILayout.Button(new GUIContent("360 Video", "Display the full 360 layer")))
  232. {
  233. SetRectsByVideoType(overlay, StereoType.Custom, DisplayType.Full);
  234. }
  235. if (GUILayout.Button(new GUIContent("180 Video", "Display the front 180 layer")))
  236. {
  237. SetRectsByVideoType(overlay, StereoType.Custom, DisplayType.Half);
  238. }
  239. EditorGUILayout.EndHorizontal();
  240. }
  241. else
  242. {
  243. if (GUILayout.Button(new GUIContent("Reset To Default", "Reset Source Rects to default")))
  244. {
  245. SetRectsByVideoType(overlay, StereoType.Custom, DisplayType.Full);
  246. }
  247. }
  248. }
  249. }
  250. }
  251. EditorGUILayout.Separator();
  252. EditorGUILayout.LabelField("Color Scale", EditorStyles.boldLabel);
  253. EditorGUILayout.Space();
  254. overlay.overridePerLayerColorScaleAndOffset = EditorGUILayout.Toggle(new GUIContent("Override Color Scale", "Manually set color scale and offset of this layer, regardless of what the global values are from OVRManager.SetColorScaleAndOffset()."), overlay.overridePerLayerColorScaleAndOffset);
  255. if (overlay.overridePerLayerColorScaleAndOffset)
  256. {
  257. Vector4 colorScale = EditorGUILayout.Vector4Field(new GUIContent("Color Scale", "Scale that the color values for this overlay will be multiplied by."), overlay.colorScale);
  258. Vector4 colorOffset = EditorGUILayout.Vector4Field(new GUIContent("Color Offset", "Offset that the color values for this overlay will be added to."), overlay.colorOffset);
  259. overlay.SetPerLayerColorScaleAndOffset(colorScale, colorOffset);
  260. }
  261. EditorUtility.SetDirty(overlay);
  262. }
  263. private Rect Clamp01(Rect rect)
  264. {
  265. rect.x = Mathf.Clamp01(rect.x);
  266. rect.y = Mathf.Clamp01(rect.y);
  267. rect.width = Mathf.Clamp01(rect.width);
  268. rect.height = Mathf.Clamp01(rect.height);
  269. return rect;
  270. }
  271. private bool IsUnitRect(Rect rect)
  272. {
  273. return IsRect(rect, 0, 0, 1, 1);
  274. }
  275. private bool IsRect(Rect rect, float x, float y, float w, float h)
  276. {
  277. return rect.x == x && rect.y == y && rect.width == w && rect.height == h;
  278. }
  279. private StereoType GetStereoType(OVROverlay overlay)
  280. {
  281. if (overlay.textures[0] != null && overlay.textures[1] != null)
  282. {
  283. if (IsUnitRect(overlay.srcRectLeft) && IsUnitRect(overlay.srcRectRight))
  284. {
  285. return StereoType.Stereo;
  286. }
  287. else
  288. {
  289. return StereoType.Custom;
  290. }
  291. }
  292. else if (overlay.textures[0] != null)
  293. {
  294. if (IsUnitRect(overlay.srcRectLeft) && IsUnitRect(overlay.srcRectRight))
  295. {
  296. return StereoType.Mono;
  297. }
  298. else if (IsRect(overlay.srcRectLeft, 0, 0, 0.5f, 1f) && IsRect(overlay.srcRectRight, 0.5f, 0, 0.5f, 1f))
  299. {
  300. return StereoType.StereoLeftRight;
  301. }
  302. else if (IsRect(overlay.srcRectLeft, 0, 0, 1f, 0.5f) && IsRect(overlay.srcRectRight, 0f, 0.5f, 1f, 0.5f))
  303. {
  304. return StereoType.StereoTopBottom;
  305. }
  306. else
  307. {
  308. return StereoType.Custom;
  309. }
  310. }
  311. else
  312. {
  313. return StereoType.Mono;
  314. }
  315. }
  316. private void SetRectsByVideoType(OVROverlay overlay, StereoType stereoType, DisplayType displayType)
  317. {
  318. Rect srcRectLeft, srcRectRight, destRectLeft, destRectRight;
  319. switch (displayType)
  320. {
  321. case DisplayType.Full:
  322. destRectLeft = destRectRight = new Rect(0, 0, 1, 1);
  323. break;
  324. case DisplayType.Half:
  325. destRectLeft = destRectRight = new Rect(0.25f, 0, 0.5f, 1);
  326. break;
  327. default:
  328. destRectLeft = overlay.destRectLeft;
  329. destRectRight = overlay.destRectRight;
  330. break;
  331. }
  332. switch (stereoType)
  333. {
  334. case StereoType.Mono:
  335. case StereoType.Stereo:
  336. srcRectLeft = srcRectRight = new Rect(0, 0, 1, 1);
  337. break;
  338. case StereoType.StereoTopBottom:
  339. srcRectLeft = new Rect(0, 0, 1, 0.5f);
  340. srcRectRight = new Rect(0, 0.5f, 1, 0.5f);
  341. break;
  342. case StereoType.StereoLeftRight:
  343. srcRectLeft = new Rect(0, 0, 0.5f, 1);
  344. srcRectRight = new Rect(0.5f, 0, 0.5f, 1);
  345. break;
  346. default:
  347. srcRectLeft = overlay.srcRectLeft;
  348. srcRectRight = overlay.srcRectRight;
  349. break;
  350. }
  351. overlay.SetSrcDestRects(srcRectLeft, srcRectRight, destRectLeft, destRectRight);
  352. }
  353. private void GetCursorPoints(Rect drawRect, Rect selectRect, out Vector2 leftPos, out Vector2 rightPos, out Vector2 topPos, out Vector2 bottomPos)
  354. {
  355. leftPos = new Vector2(drawRect.x + selectRect.x * drawRect.width, drawRect.y + (selectRect.y + selectRect.height / 2) * drawRect.height);
  356. rightPos = new Vector2(drawRect.x + (selectRect.x + selectRect.width) * drawRect.width, drawRect.y + (selectRect.y + selectRect.height / 2) * drawRect.height);
  357. topPos = new Vector2(drawRect.x + (selectRect.x + selectRect.width / 2) * drawRect.width, drawRect.y + (selectRect.y) * drawRect.height);
  358. bottomPos = new Vector2(drawRect.x + (selectRect.x + selectRect.width / 2) * drawRect.width, drawRect.y + (selectRect.y + selectRect.height) * drawRect.height);
  359. }
  360. private void CreateCursorRects(Rect drawRect, Rect selectRect)
  361. {
  362. Vector2 leftPos, rightPos, topPos, bottomPos;
  363. GetCursorPoints(drawRect, selectRect, out leftPos, out rightPos, out topPos, out bottomPos);
  364. EditorGUIUtility.AddCursorRect(new Rect(leftPos - 5 * Vector2.one, 10 * Vector2.one), MouseCursor.ResizeHorizontal);
  365. EditorGUIUtility.AddCursorRect(new Rect(rightPos - 5 * Vector2.one, 10 * Vector2.one), MouseCursor.ResizeHorizontal);
  366. EditorGUIUtility.AddCursorRect(new Rect(topPos - 5 * Vector2.one, 10 * Vector2.one), MouseCursor.ResizeVertical);
  367. EditorGUIUtility.AddCursorRect(new Rect(bottomPos - 5 * Vector2.one, 10 * Vector2.one), MouseCursor.ResizeVertical);
  368. }
  369. private bool IsOverRectControls(Rect drawRect, Vector2 mousePos, Rect selectRect, ref Side side)
  370. {
  371. Vector2 leftPos, rightPos, topPos, bottomPos;
  372. GetCursorPoints(drawRect, selectRect, out leftPos, out rightPos, out topPos, out bottomPos);
  373. if ((leftPos - mousePos).sqrMagnitude <= 25)
  374. {
  375. side = Side.Left;
  376. return true;
  377. }
  378. if ((rightPos - mousePos).sqrMagnitude <= 25)
  379. {
  380. side = Side.Right;
  381. return true;
  382. }
  383. if ((topPos - mousePos).sqrMagnitude <= 25)
  384. {
  385. side = Side.Top;
  386. return true;
  387. }
  388. if ((bottomPos - mousePos).sqrMagnitude <= 25)
  389. {
  390. side = Side.Bottom;
  391. return true;
  392. }
  393. return false;
  394. }
  395. private void UpdateRectDragging(Rect drawingRectLeft, Rect drawingRectRight, TextureRect rectLeftType, TextureRect rectRightType, ref Rect rectLeft, ref Rect rectRight)
  396. {
  397. if (!Event.current.isMouse || Event.current.button != 0)
  398. {
  399. return;
  400. }
  401. if (Event.current.type == EventType.MouseUp)
  402. {
  403. _DraggingRect = TextureRect.None;
  404. return;
  405. }
  406. Vector2 mousePos = Event.current.mousePosition;
  407. if (_DraggingRect == TextureRect.None && Event.current.type == EventType.MouseDown)
  408. {
  409. if (IsOverRectControls(drawingRectLeft, mousePos, rectLeft, ref _DraggingSide))
  410. {
  411. _DraggingRect = rectLeftType;
  412. }
  413. if (_DraggingRect == TextureRect.None || Event.current.shift)
  414. {
  415. if (IsOverRectControls(drawingRectRight, mousePos, rectRight, ref _DraggingSide))
  416. {
  417. _DraggingRect = rectRightType;
  418. }
  419. }
  420. }
  421. if (_DraggingRect == rectLeftType)
  422. {
  423. SetRectSideValue(drawingRectLeft, mousePos, _DraggingSide, ref rectLeft);
  424. }
  425. if (_DraggingRect == rectRightType)
  426. {
  427. SetRectSideValue(drawingRectRight, mousePos, _DraggingSide, ref rectRight);
  428. }
  429. }
  430. private void SetRectSideValue(Rect drawingRect, Vector2 mousePos, Side side, ref Rect rect)
  431. {
  432. // quantize to 1/32
  433. float x = Mathf.Clamp01(Mathf.Round(((mousePos.x - drawingRect.x) / drawingRect.width) * 32) / 32.0f);
  434. float y = Mathf.Clamp01(Mathf.Round(((mousePos.y - drawingRect.y) / drawingRect.height) * 32) / 32.0f);
  435. switch (side)
  436. {
  437. case Side.Left:
  438. float xMax = rect.xMax;
  439. rect.x = Mathf.Min(x, xMax);
  440. rect.width = xMax - rect.x;
  441. break;
  442. case Side.Right:
  443. rect.width = Mathf.Max(0, x - rect.x);
  444. break;
  445. case Side.Top:
  446. float yMax = rect.yMax;
  447. rect.y = Mathf.Min(y, yMax);
  448. rect.height = yMax - rect.y;
  449. break;
  450. case Side.Bottom:
  451. rect.height = Mathf.Max(0, y - rect.y);
  452. break;
  453. }
  454. }
  455. }