SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

302 lines
12 KiB

4 years ago
  1. using System;
  2. using UnityEngine;
  3. using UnityEditor.XR.ARSubsystems.InternalBridge;
  4. using UnityEngine.XR.ARSubsystems;
  5. namespace UnityEditor.XR.ARSubsystems
  6. {
  7. [CustomEditor(typeof(XRReferenceImageLibrary))]
  8. class XRReferenceImageLibraryEditor : Editor
  9. {
  10. static class Content
  11. {
  12. static readonly int s_AddImageControlId;
  13. static readonly GUIContent s_AddButtonContent;
  14. static readonly GUIContent s_RemoveButtonContent;
  15. static Content()
  16. {
  17. s_AddButtonContent = new GUIContent("Add Image");
  18. s_AddImageControlId = GUIUtility.GetControlID(s_AddButtonContent, FocusType.Keyboard);
  19. s_RemoveButtonContent = new GUIContent(
  20. string.Empty,
  21. EditorGUIUtility.FindTexture("d_winbtn_win_close"),
  22. "Remove this image from the database");
  23. }
  24. public static readonly GUIContent keepTexture = new GUIContent(
  25. "Keep Texture at Runtime",
  26. "If enabled, the texture will be available in the Player. Otherwise, the texture will be null in the Player.");
  27. public static readonly GUIContent name = new GUIContent(
  28. "Name",
  29. "The name of the reference image. This can useful for matching detected images with their reference image at runtime.");
  30. public static readonly GUIContent specifySize = new GUIContent(
  31. "Specify Size",
  32. "If enabled, you can specify the physical dimensions of the image in meters. Some platforms require this.");
  33. public static readonly GUIContent sizePixels = new GUIContent(
  34. "Texture Size (pixels)",
  35. "The texture dimensions, in pixels.");
  36. public static readonly GUIContent sizeMeters = new GUIContent(
  37. "Physical Size (meters)",
  38. "The dimensions of the physical image, in meters.");
  39. public static int addImageControlId
  40. {
  41. get
  42. {
  43. return s_AddImageControlId;
  44. }
  45. }
  46. public static bool addButton
  47. {
  48. get
  49. {
  50. return GUILayout.Button(s_AddButtonContent);
  51. }
  52. }
  53. public static bool removeButton
  54. {
  55. get
  56. {
  57. return GUI.Button(
  58. GUILayoutUtility.GetRect(s_RemoveButtonContent, GUI.skin.button, GUILayout.ExpandWidth(false)),
  59. s_RemoveButtonContent,
  60. GUI.skin.button);
  61. }
  62. }
  63. }
  64. SerializedProperty m_ReferenceImages;
  65. void OnEnable()
  66. {
  67. m_ReferenceImages = serializedObject.FindProperty("m_Images");
  68. }
  69. public override void OnInspectorGUI()
  70. {
  71. serializedObject.Update();
  72. int indexToRemove = -1;
  73. for (int i = 0; i < m_ReferenceImages.arraySize; ++i)
  74. {
  75. var shouldRemove = ReferenceImageField(i);
  76. if (shouldRemove)
  77. {
  78. indexToRemove = i;
  79. }
  80. EditorGUILayout.Separator();
  81. if (i < m_ReferenceImages.arraySize - 1)
  82. EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider);
  83. }
  84. if (indexToRemove > -1)
  85. m_ReferenceImages.DeleteArrayElementAtIndex(indexToRemove);
  86. serializedObject.ApplyModifiedProperties();
  87. if (Content.addButton)
  88. {
  89. Undo.RecordObject(target, "Add reference image");
  90. (target as XRReferenceImageLibrary).Add();
  91. EditorUtility.SetDirty(target);
  92. }
  93. }
  94. /// <summary>
  95. /// Generates the GUI for a reference image at index <paramref name="index"/>.
  96. /// </summary>
  97. /// <param name="index">The index of the reference image in the <see cref="XRReferenceImageLibrary"/>.</param>
  98. /// <returns>True if the image should be removed.</returns>
  99. bool ReferenceImageField(int index)
  100. {
  101. var library = target as XRReferenceImageLibrary;
  102. var referenceImageProperty = m_ReferenceImages.GetArrayElementAtIndex(index);
  103. var sizeProperty = referenceImageProperty.FindPropertyRelative("m_Size");
  104. var specifySizeProperty = referenceImageProperty.FindPropertyRelative("m_SpecifySize");
  105. var nameProperty = referenceImageProperty.FindPropertyRelative("m_Name");
  106. var referenceImage = library[index];
  107. var texturePath = AssetDatabase.GUIDToAssetPath(referenceImage.textureGuid.ToString("N"));
  108. var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath);
  109. bool shouldRemove = false;
  110. bool wasTextureUpdated = false;
  111. using (new EditorGUILayout.HorizontalScope())
  112. {
  113. using (var textureCheck = new EditorGUI.ChangeCheckScope())
  114. {
  115. texture = TextureField(texture);
  116. wasTextureUpdated = textureCheck.changed;
  117. }
  118. shouldRemove = Content.removeButton;
  119. }
  120. EditorGUILayout.PropertyField(nameProperty, Content.name);
  121. EditorGUILayout.PropertyField(specifySizeProperty, Content.specifySize);
  122. if (specifySizeProperty.boolValue)
  123. {
  124. using (new EditorGUI.IndentLevelScope())
  125. {
  126. using (new EditorGUI.DisabledScope(true))
  127. {
  128. var imageDimensions = (texture == null) ? Vector2Int.zero : GetTextureSize(texture);
  129. EditorGUILayout.Vector2IntField(Content.sizePixels, imageDimensions);
  130. }
  131. using (var changeCheck = new EditorGUI.ChangeCheckScope())
  132. {
  133. EditorGUILayout.PropertyField(sizeProperty, Content.sizeMeters);
  134. // Prevent dimensions from going below zero.
  135. var size = new Vector2(
  136. Mathf.Max(0f, sizeProperty.vector2Value.x),
  137. Mathf.Max(0f, sizeProperty.vector2Value.y));
  138. if ((sizeProperty.vector2Value.x < 0f) ||
  139. (sizeProperty.vector2Value.y < 0f))
  140. {
  141. sizeProperty.vector2Value = size;
  142. }
  143. if (changeCheck.changed)
  144. {
  145. if (texture == null)
  146. {
  147. // If the texture is null, then we just set whatever the user specifies
  148. sizeProperty.vector2Value = size;
  149. }
  150. else
  151. {
  152. // Otherwise, maintain the aspect ratio
  153. var delta = referenceImage.size - size;
  154. delta = new Vector2(Mathf.Abs(delta.x), Mathf.Abs(delta.y));
  155. // Determine which dimension has changed and compute the unchanged dimension
  156. if (delta.x > delta.y)
  157. {
  158. sizeProperty.vector2Value = SizeFromWidth(texture, size);
  159. }
  160. else if (delta.y > 0f)
  161. {
  162. sizeProperty.vector2Value = SizeFromHeight(texture, size);
  163. }
  164. }
  165. }
  166. else if (wasTextureUpdated && texture != null)
  167. {
  168. // If the texture changed, re-compute width / height
  169. if (size.x == 0f)
  170. {
  171. sizeProperty.vector2Value = SizeFromHeight(texture, size);
  172. }
  173. else
  174. {
  175. sizeProperty.vector2Value = SizeFromWidth(texture, size);
  176. }
  177. }
  178. }
  179. if ((sizeProperty.vector2Value.x <= 0f) || (sizeProperty.vector2Value.y <= 0f))
  180. {
  181. EditorGUILayout.HelpBox("Dimensions must be greater than zero.", MessageType.Warning);
  182. }
  183. }
  184. }
  185. using (new EditorGUI.DisabledScope(texture == null))
  186. using (var changeCheck = new EditorGUI.ChangeCheckScope())
  187. {
  188. bool keepTexture = EditorGUILayout.Toggle(Content.keepTexture, referenceImage.texture != null);
  189. if (changeCheck.changed || wasTextureUpdated)
  190. {
  191. // Auto-populate the name from the texture's name if it is not set already.
  192. if (string.IsNullOrEmpty(nameProperty.stringValue) && texture != null)
  193. {
  194. nameProperty.stringValue = texture.name;
  195. }
  196. // Apply properties for anything that may have been modified, otherwise
  197. // the texture change may be overwritten.
  198. serializedObject.ApplyModifiedProperties();
  199. // Create an undo entry, modify, set dirty
  200. Undo.RecordObject(target, "Update reference image texture");
  201. library.SetTexture(index, texture, keepTexture);
  202. EditorUtility.SetDirty(target);
  203. }
  204. }
  205. return shouldRemove;
  206. }
  207. /// <summary>
  208. /// Computes a new size using the width and aspect ratio from the Texture2D.
  209. /// Width remains the same as before; height is recalculated.
  210. /// </summary>
  211. static Vector2 SizeFromWidth(Texture2D texture, Vector2 size)
  212. {
  213. var textureSize = GetTextureSize(texture);
  214. return new Vector2(size.x, size.x * (float)textureSize.y / (float)textureSize.x);
  215. }
  216. /// <summary>
  217. /// Computes a new size using the height and aspect ratio from the Texture2D.
  218. /// Height remains the same as before; width is recalculated.
  219. /// </summary>
  220. static Vector2 SizeFromHeight(Texture2D texture, Vector2 size)
  221. {
  222. var textureSize = GetTextureSize(texture);
  223. return new Vector2(size.y * (float)textureSize.x / (float)textureSize.y, size.y);
  224. }
  225. static Vector2Int GetTextureSize(Texture2D texture)
  226. {
  227. if (texture == null)
  228. throw new ArgumentNullException("texture");
  229. var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture)) as TextureImporter;
  230. if (textureImporter == null)
  231. {
  232. return new Vector2Int(texture.width, texture.height);
  233. }
  234. else
  235. {
  236. return TextureImporterInternals.GetSourceTextureDimensions(textureImporter);
  237. }
  238. }
  239. static Texture2D TextureField(Texture2D texture)
  240. {
  241. const int k_MaxSideLength = 64;
  242. int width = k_MaxSideLength, height = k_MaxSideLength;
  243. if (texture != null)
  244. {
  245. var textureSize = GetTextureSize(texture);
  246. if (textureSize.x > textureSize.y)
  247. height = width * textureSize.y / textureSize.x;
  248. else
  249. width = height * textureSize.x / textureSize.y;
  250. }
  251. return (Texture2D)EditorGUILayout.ObjectField(
  252. texture,
  253. typeof(Texture2D),
  254. true,
  255. GUILayout.Width(width),
  256. GUILayout.Height(height));
  257. }
  258. }
  259. }