NRTrackableImageEditor.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal.NREditor
  10. {
  11. using System.Collections.Generic;
  12. using UnityEngine;
  13. using UnityEditor;
  14. /// <summary> Editor for nr trackable image. </summary>
  15. [CanEditMultipleObjects, CustomEditor(typeof(NRTrackableImageBehaviour))]
  16. public class NRTrackableImageEditor : Editor
  17. {
  18. /// <summary> The serialized object. </summary>
  19. private NRSerializedImageTarget m_SerializedObj;
  20. /// <summary> The database. </summary>
  21. private static NRTrackingImageDatabase m_Database;
  22. /// <summary> Name of the images. </summary>
  23. private static string[] m_ImagesName;
  24. /// <summary> imageIndex; </summary>
  25. private int m_PreSelectOption = -1;
  26. /// <summary> Executes the 'enable' action. </summary>
  27. private void OnEnable()
  28. {
  29. NRTrackableImageBehaviour itb = (NRTrackableImageBehaviour)target;
  30. m_SerializedObj = new NRSerializedImageTarget(serializedObject);
  31. m_Database = GameObject.FindObjectOfType<NRSessionBehaviour>().SessionConfig.TrackingImageDatabase;
  32. if (m_Database == null) return;
  33. m_ImagesName = new string[m_Database.Count];
  34. EditorDatabase(itb, m_SerializedObj);
  35. }
  36. /// <summary> <para>Implement this function to make a custom inspector.</para> </summary>
  37. public override void OnInspectorGUI()
  38. {
  39. base.OnInspectorGUI();
  40. DrawInspectorGUI();
  41. serializedObject.ApplyModifiedProperties();
  42. }
  43. /// <summary> Draw inspector graphical user interface. </summary>
  44. private void DrawInspectorGUI()
  45. {
  46. if (m_Database == null)
  47. {
  48. NRDebugger.Error("NRKernalSessionConfig.TrackingImageDatabase is null");
  49. return;
  50. }
  51. EditorGUI.BeginDisabledGroup(true);
  52. EditorGUILayout.Popup("Database", 0, new string[] { m_Database.name });
  53. EditorGUI.EndDisabledGroup();
  54. for (int i = 0; i < m_ImagesName.Length; i++)
  55. {
  56. m_ImagesName[i] = m_Database[i].Name;
  57. }
  58. m_SerializedObj.DatabaseIndex = EditorGUILayout.Popup("Image Target", m_SerializedObj.DatabaseIndex, m_ImagesName);
  59. if (m_SerializedObj.DatabaseIndex != m_PreSelectOption)
  60. {
  61. m_PreSelectOption = m_SerializedObj.DatabaseIndex;
  62. // todo logic
  63. m_SerializedObj.Width = m_Database[m_SerializedObj.DatabaseIndex].Width;
  64. m_SerializedObj.Height = m_Database[m_SerializedObj.DatabaseIndex].Width;//Height;
  65. UpdateProperties(m_SerializedObj);
  66. }
  67. if (base.serializedObject.isEditingMultipleObjects)
  68. {
  69. m_SerializedObj.SerializedObject.ApplyModifiedPropertiesWithoutUndo();
  70. Object[] targetObjs = m_SerializedObj.SerializedObject.targetObjects;
  71. for (int i = 0; i < targetObjs.Length; i++)
  72. {
  73. UpdateAppearance(m_SerializedObj);
  74. }
  75. }
  76. else
  77. {
  78. UpdateAppearance(m_SerializedObj);
  79. }
  80. EditorGUI.BeginDisabledGroup(true);
  81. EditorGUILayout.PropertyField(m_SerializedObj.WidthProperty, new GUIContent("Width"), new GUILayoutOption[0]);
  82. EditorGUILayout.PropertyField(m_SerializedObj.HeightProperty, new GUIContent("Height"), new GUILayoutOption[0]);
  83. EditorGUI.EndDisabledGroup();
  84. }
  85. /// <summary> Editor database. </summary>
  86. /// <param name="itb"> The itb.</param>
  87. /// <param name="serializedObj"> The serialized object.</param>
  88. public void EditorDatabase(NRTrackableImageBehaviour itb, NRSerializedImageTarget serializedObj)
  89. {
  90. if (!NREditorSceneManager.Instance.SceneInitialized)
  91. {
  92. NREditorSceneManager.Instance.InitScene();
  93. }
  94. if (!EditorApplication.isPlaying)
  95. {
  96. CheckMesh(serializedObj);
  97. }
  98. }
  99. /// <summary> Updates the properties described by sit. </summary>
  100. /// <param name="sit"> The sit.</param>
  101. private void UpdateProperties(NRSerializedImageTarget sit)
  102. {
  103. NRTrackableImageBehaviour itb = ((NRTrackableImageBehaviour)target);
  104. itb.TrackableName = m_ImagesName[m_SerializedObj.DatabaseIndex];
  105. itb.DatabaseIndex = m_SerializedObj.DatabaseIndex;
  106. }
  107. /// <summary> Updates the appearance described by serializedImageTarget. </summary>
  108. /// <param name="serializedImageTarget"> The serialized image target.</param>
  109. private static void UpdateAppearance(NRSerializedImageTarget serializedImageTarget)
  110. {
  111. UpdateAspectRatio(serializedImageTarget);
  112. UpdateScale(serializedImageTarget);
  113. UpdateMaterial(serializedImageTarget);
  114. }
  115. /// <summary> Updates the aspect ratio described by it. </summary>
  116. /// <param name="it"> The iterator.</param>
  117. internal static void UpdateAspectRatio(NRSerializedImageTarget it)
  118. {
  119. Vector2 size = new Vector2(it.Width, it.Height);
  120. it.AspectRatio = size.y / size.x;
  121. using (List<NRTrackableImageBehaviour>.Enumerator enumerator = it.GetBehaviours().GetEnumerator())
  122. {
  123. while (enumerator.MoveNext())
  124. {
  125. UpdateMesh(enumerator.Current.gameObject, it.AspectRatio);
  126. }
  127. }
  128. }
  129. /// <summary> Updates the scale described by it. </summary>
  130. /// <param name="it"> The iterator.</param>
  131. internal static void UpdateScale(NRSerializedImageTarget it)
  132. {
  133. Vector2 size = new Vector2(it.Width, it.Height);
  134. foreach (NRTrackableImageBehaviour item in it.GetBehaviours())
  135. {
  136. if (it.AspectRatio <= 1f) // AspectRatio => y/x
  137. {
  138. item.transform.localScale = new Vector3(size.x, size.x, size.x) * 0.001f;
  139. }
  140. else
  141. {
  142. item.transform.localScale = new Vector3(size.y, size.y, size.y) * 0.001f;
  143. }
  144. }
  145. }
  146. /// <summary> Updates the material described by sit. </summary>
  147. /// <param name="sit"> The sit.</param>
  148. internal static void UpdateMaterial(NRSerializedImageTarget sit)
  149. {
  150. Material mat = sit.GetMaterial();
  151. Material loadMat = LoadMat();
  152. if (mat == null || mat == loadMat)
  153. {
  154. mat = new Material(loadMat);
  155. }
  156. string name = m_ImagesName[sit.DatabaseIndex];
  157. Texture2D texture = m_Database[sit.DatabaseIndex].Texture;
  158. mat.mainTexture = texture;
  159. mat.mainTextureScale = new Vector2(1f, 1f);
  160. mat.name = name + "Material";
  161. sit.SetMaterial(mat);
  162. }
  163. /// <summary> Updates the mesh. </summary>
  164. /// <param name="itObj"> The iterator object.</param>
  165. /// <param name="aspectRatio"> The aspect ratio.</param>
  166. internal static void UpdateMesh(GameObject itObj, float aspectRatio)
  167. {
  168. MeshFilter meshFilter = itObj.GetComponent<MeshFilter>();
  169. if (meshFilter == null)
  170. {
  171. meshFilter = itObj.AddComponent<MeshFilter>();
  172. }
  173. Vector3 v1, v2, v3, v4;
  174. if (aspectRatio <= 1)
  175. {
  176. v1 = new Vector3(-0.5f, 0f, -aspectRatio * 0.5f);
  177. v2 = new Vector3(-0.5f, 0f, aspectRatio * 0.5f);
  178. v3 = new Vector3(0.5f, 0f, -aspectRatio * 0.5f);
  179. v4 = new Vector3(0.5f, 0f, aspectRatio * 0.5f);
  180. }
  181. else
  182. {
  183. float f = 1 / aspectRatio;
  184. v1 = new Vector3(-f * 0.5f, 0f, -0.5f);
  185. v2 = new Vector3(-f * 0.5f, 0f, 0.5f);
  186. v3 = new Vector3(f * 0.5f, 0f, -0.5f);
  187. v4 = new Vector3(f * 0.5f, 0f, 0.5f);
  188. }
  189. Mesh mesh = meshFilter.sharedMesh ?? new Mesh();
  190. mesh.vertices = new Vector3[] { v1, v2, v3, v4 };
  191. mesh.triangles = new int[] { 0, 1, 2, 2, 1, 3 };
  192. mesh.normals = new Vector3[mesh.vertices.Length];
  193. mesh.uv = new Vector2[] { new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(1f, 0f), new Vector2(1f, 1f) };
  194. mesh.RecalculateNormals();
  195. meshFilter.sharedMesh = mesh;
  196. if (!itObj.GetComponent<MeshRenderer>())
  197. {
  198. itObj.AddComponent<MeshRenderer>();
  199. }
  200. NREditorSceneManager.Instance.UnloadUnusedAssets();
  201. }
  202. /// <summary> Check mesh. </summary>
  203. /// <param name="serializedImageTarget"> The serialized image target.</param>
  204. private void CheckMesh(NRSerializedImageTarget serializedImageTarget)
  205. {
  206. using (List<NRTrackableImageBehaviour>.Enumerator enumerator = serializedImageTarget.GetBehaviours().GetEnumerator())
  207. {
  208. while (enumerator.MoveNext())
  209. {
  210. GameObject go = enumerator.Current.gameObject;
  211. MeshFilter mf = go.GetComponent<MeshFilter>();
  212. if ((mf == null || mf.sharedMesh == null) && serializedImageTarget.AspectRatioProperty.hasMultipleDifferentValues)
  213. {
  214. UpdateMesh(go, serializedImageTarget.AspectRatio);
  215. }
  216. }
  217. }
  218. if (!serializedImageTarget.TrackableNameProperty.hasMultipleDifferentValues)
  219. {
  220. UpdateMaterial(serializedImageTarget);
  221. }
  222. }
  223. /// <summary> Loads the matrix. </summary>
  224. /// <returns> The matrix. </returns>
  225. private static Material LoadMat()
  226. {
  227. string text = "Assets/NRSDK/Emulator/Materials/DefaultTarget.mat";
  228. Material mat = AssetDatabase.LoadAssetAtPath<Material>(text);
  229. if (mat == null)
  230. {
  231. NRDebugger.Error("Could not find reference material at " + text + " please reimport Unity package.");
  232. }
  233. return mat;
  234. }
  235. }
  236. }