InspectorWindow.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. using System;
  2. using System.Collections.Generic;
  3. using BansheeEngine;
  4. namespace BansheeEditor
  5. {
  6. internal sealed class InspectorWindow : EditorWindow
  7. {
  8. private class InspectorData
  9. {
  10. public GUIComponentFoldout foldout;
  11. public GUIPanel panel;
  12. public Inspector inspector;
  13. public bool expanded = true;
  14. }
  15. private List<InspectorData> inspectorData = new List<InspectorData>();
  16. private GUIScrollArea inspectorScrollArea;
  17. private GUILayout inspectorLayout;
  18. private SceneObject activeSO;
  19. private GUITextBox soNameInput;
  20. private GUILayout soPrefabLayout;
  21. private bool soHasPrefab;
  22. private GUIFloatField soPosX;
  23. private GUIFloatField soPosY;
  24. private GUIFloatField soPosZ;
  25. private GUIFloatField soRotX;
  26. private GUIFloatField soRotY;
  27. private GUIFloatField soRotZ;
  28. private GUIFloatField soScaleX;
  29. private GUIFloatField soScaleY;
  30. private GUIFloatField soScaleZ;
  31. [MenuItem("Windows/Inspector", ButtonModifier.CtrlAlt, ButtonCode.I)]
  32. private static void OpenInspectorWindow()
  33. {
  34. OpenWindow<InspectorWindow>();
  35. }
  36. protected override LocString GetDisplayName()
  37. {
  38. return "Inspector";
  39. }
  40. internal void SetObjectToInspect(SceneObject so)
  41. {
  42. Clear();
  43. activeSO = so;
  44. if (activeSO == null)
  45. return;
  46. inspectorScrollArea = new GUIScrollArea();
  47. GUI.AddElement(inspectorScrollArea);
  48. inspectorLayout = inspectorScrollArea.Layout;
  49. // SceneObject fields
  50. CreateSceneObjectFields();
  51. RefreshSceneObjectFields(true);
  52. // Components
  53. Component[] allComponents = so.GetComponents();
  54. for (int i = 0; i < allComponents.Length; i++)
  55. {
  56. InspectorData data = new InspectorData();
  57. data.foldout = new GUIComponentFoldout(allComponents[i].GetType().Name);
  58. inspectorLayout.AddElement(data.foldout);
  59. data.panel = inspectorLayout.AddPanel();
  60. data.inspector = GetInspector(allComponents[i].GetType());
  61. data.inspector.Initialize(this, data.panel, allComponents[i]);
  62. data.foldout.SetExpanded(true);
  63. data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
  64. inspectorData.Add(data);
  65. inspectorData[i].inspector.Refresh();
  66. }
  67. inspectorLayout.AddFlexibleSpace();
  68. }
  69. private void OnComponentFoldoutToggled(InspectorData inspectorData, bool expanded)
  70. {
  71. inspectorData.expanded = expanded;
  72. inspectorData.inspector.SetVisible(expanded);
  73. }
  74. private void CreateSceneObjectFields()
  75. {
  76. GUIPanel sceneObjectPanel = inspectorLayout.AddPanel();
  77. GUILayoutY sceneObjectLayout = sceneObjectPanel.AddLayoutY();
  78. GUILayoutX nameLayout = sceneObjectLayout.AddLayoutX();
  79. GUILabel nameLbl = new GUILabel("Name", GUIOption.FixedWidth(70));
  80. soNameInput = new GUITextBox(false, GUIOption.FlexibleWidth(200));
  81. soNameInput.Text = activeSO.Name;
  82. soNameInput.OnChanged += (x) => { if (activeSO != null) activeSO.Name = x; };
  83. nameLayout.AddElement(nameLbl);
  84. nameLayout.AddElement(soNameInput);
  85. nameLayout.AddFlexibleSpace();
  86. soPrefabLayout = sceneObjectLayout.AddLayoutX();
  87. GUILayoutX positionLayout = sceneObjectLayout.AddLayoutX();
  88. GUILabel positionLbl = new GUILabel("Position", GUIOption.FixedWidth(70));
  89. soPosX = new GUIFloatField(new GUIContent("X"), 10, "", GUIOption.FlexibleWidth(50));
  90. soPosY = new GUIFloatField(new GUIContent("Y"), 10, "", GUIOption.FlexibleWidth(50));
  91. soPosZ = new GUIFloatField(new GUIContent("Z"), 10, "", GUIOption.FlexibleWidth(50));
  92. soPosX.OnChanged += (x) => OnPositionChanged(0, x);
  93. soPosY.OnChanged += (y) => OnPositionChanged(1, y);
  94. soPosZ.OnChanged += (z) => OnPositionChanged(2, z);
  95. positionLayout.AddElement(positionLbl);
  96. positionLayout.AddElement(soPosX);
  97. positionLayout.AddSpace(10);
  98. positionLayout.AddElement(soPosY);
  99. positionLayout.AddSpace(10);
  100. positionLayout.AddElement(soPosZ);
  101. positionLayout.AddFlexibleSpace();
  102. GUILayoutX rotationLayout = sceneObjectLayout.AddLayoutX();
  103. GUILabel rotationLbl = new GUILabel("Rotation", GUIOption.FixedWidth(70));
  104. soRotX = new GUIFloatField(new GUIContent("X"), 10, "", GUIOption.FlexibleWidth(50));
  105. soRotY = new GUIFloatField(new GUIContent("Y"), 10, "", GUIOption.FlexibleWidth(50));
  106. soRotZ = new GUIFloatField(new GUIContent("Z"), 10, "", GUIOption.FlexibleWidth(50));
  107. soRotX.OnChanged += (x) => OnRotationChanged(0, x);
  108. soRotY.OnChanged += (y) => OnRotationChanged(1, y);
  109. soRotZ.OnChanged += (z) => OnRotationChanged(2, z);
  110. rotationLayout.AddElement(rotationLbl);
  111. rotationLayout.AddElement(soRotX);
  112. rotationLayout.AddSpace(10);
  113. rotationLayout.AddElement(soRotY);
  114. rotationLayout.AddSpace(10);
  115. rotationLayout.AddElement(soRotZ);
  116. rotationLayout.AddFlexibleSpace();
  117. GUILayoutX scaleLayout = sceneObjectLayout.AddLayoutX();
  118. GUILabel scaleLbl = new GUILabel("Scale", GUIOption.FixedWidth(70));
  119. soScaleX = new GUIFloatField(new GUIContent("X"), 10, "", GUIOption.FlexibleWidth(50));
  120. soScaleY = new GUIFloatField(new GUIContent("Y"), 10, "", GUIOption.FlexibleWidth(50));
  121. soScaleZ = new GUIFloatField(new GUIContent("Z"), 10, "", GUIOption.FlexibleWidth(50));
  122. soScaleX.OnChanged += (x) => OnScaleChanged(0, x);
  123. soScaleY.OnChanged += (y) => OnScaleChanged(1, y);
  124. soScaleX.OnChanged += (z) => OnScaleChanged(2, z);
  125. scaleLayout.AddElement(scaleLbl);
  126. scaleLayout.AddElement(soScaleX);
  127. scaleLayout.AddSpace(10);
  128. scaleLayout.AddElement(soScaleY);
  129. scaleLayout.AddSpace(10);
  130. scaleLayout.AddElement(soScaleZ);
  131. scaleLayout.AddFlexibleSpace();
  132. }
  133. private void RefreshSceneObjectFields(bool forceUpdate)
  134. {
  135. if (activeSO == null)
  136. return;
  137. soNameInput.Text = activeSO.Name;
  138. bool hasPrefab = PrefabUtility.HasPrefabLink(activeSO);
  139. if (soHasPrefab != hasPrefab || forceUpdate)
  140. {
  141. int numChildren = soPrefabLayout.GetNumChildren();
  142. for (int i = 0; i < numChildren; i++)
  143. soPrefabLayout.GetChild(0).Destroy();
  144. GUILabel prefabLabel =new GUILabel("Prefab", GUIOption.FixedWidth(70));
  145. soPrefabLayout.AddElement(prefabLabel);
  146. //if (hasPrefab) // TODO - Disabled check for preview purposes
  147. {
  148. GUIButton btnApplyPrefab = new GUIButton("Apply");
  149. GUIButton btnRevertPrefab = new GUIButton("Revert");
  150. GUIButton btnBreakPrefab = new GUIButton("Break");
  151. btnApplyPrefab.OnClick += () => PrefabUtility.ApplyPrefab(activeSO);
  152. btnRevertPrefab.OnClick += () => PrefabUtility.RevertPrefab(activeSO);
  153. btnBreakPrefab.OnClick += () => PrefabUtility.BreakPrefab(activeSO);
  154. soPrefabLayout.AddElement(btnApplyPrefab);
  155. soPrefabLayout.AddElement(btnRevertPrefab);
  156. soPrefabLayout.AddElement(btnBreakPrefab);
  157. }
  158. //else
  159. //{
  160. // GUILabel noPrefabLabel = new GUILabel("None");
  161. // soPrefabLayout.AddElement(noPrefabLabel);
  162. //}
  163. soHasPrefab = hasPrefab;
  164. }
  165. Vector3 position;
  166. Vector3 angles;
  167. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  168. {
  169. position = activeSO.Position;
  170. angles = activeSO.Rotation.ToEuler();
  171. }
  172. else
  173. {
  174. position = activeSO.LocalPosition;
  175. angles = activeSO.LocalRotation.ToEuler();
  176. }
  177. Vector3 scale = activeSO.LocalScale;
  178. soPosX.Value = position.x;
  179. soPosY.Value = position.y;
  180. soPosZ.Value = position.z;
  181. soRotX.Value = angles.x;
  182. soRotY.Value = angles.y;
  183. soRotZ.Value = angles.z;
  184. soScaleX.Value = scale.x;
  185. soScaleY.Value = scale.y;
  186. soScaleZ.Value = scale.z;
  187. }
  188. private void OnEditorUpdate()
  189. {
  190. RefreshSceneObjectFields(false);
  191. for (int i = 0; i < inspectorData.Count; i++)
  192. {
  193. inspectorData[i].inspector.Refresh();
  194. }
  195. }
  196. internal void Destroy()
  197. {
  198. Clear();
  199. }
  200. internal void Clear()
  201. {
  202. for (int i = 0; i < inspectorData.Count; i++)
  203. {
  204. inspectorData[i].foldout.Destroy();
  205. inspectorData[i].inspector.Destroy();
  206. }
  207. inspectorData.Clear();
  208. if (inspectorScrollArea != null)
  209. {
  210. inspectorScrollArea.Destroy();
  211. inspectorScrollArea = null;
  212. }
  213. activeSO = null;
  214. soNameInput = null;
  215. soPrefabLayout = null;
  216. soHasPrefab = false;
  217. soPosX = null;
  218. soPosY = null;
  219. soPosZ = null;
  220. soRotX = null;
  221. soRotY = null;
  222. soRotZ = null;
  223. soScaleX = null;
  224. soScaleY = null;
  225. soScaleZ = null;
  226. }
  227. private void OnPositionChanged(int idx, float value)
  228. {
  229. if (activeSO == null)
  230. return;
  231. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  232. {
  233. Vector3 position = activeSO.Position;
  234. position[idx] = value;
  235. activeSO.Position = position;
  236. }
  237. else
  238. {
  239. Vector3 position = activeSO.LocalPosition;
  240. position[idx] = value;
  241. activeSO.LocalPosition = position;
  242. }
  243. }
  244. private void OnRotationChanged(int idx, float value)
  245. {
  246. if (activeSO == null)
  247. return;
  248. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  249. {
  250. Vector3 angles = activeSO.Rotation.ToEuler();
  251. angles[idx] = value;
  252. activeSO.Rotation = Quaternion.FromEuler(angles);
  253. }
  254. else
  255. {
  256. Vector3 angles = activeSO.LocalRotation.ToEuler();
  257. angles[idx] = value;
  258. activeSO.LocalRotation = Quaternion.FromEuler(angles);
  259. Debug.Log("ROTATION CHANGED: " + idx + " - " + value + " - " + angles + " - " + activeSO.LocalRotation + " - " + activeSO.LocalRotation.ToEuler());
  260. Quaternion dbg = Quaternion.FromEuler(angles);
  261. Debug.Log("LOCAL CHECK: " + angles + " - " + dbg + " - " + dbg.ToEuler());
  262. }
  263. }
  264. private void OnScaleChanged(int idx, float value)
  265. {
  266. if (activeSO == null)
  267. return;
  268. Vector3 scale = activeSO.LocalScale;
  269. scale[idx] = value;
  270. activeSO.LocalScale = scale;
  271. }
  272. private Inspector GetInspector(Type type)
  273. {
  274. // TODO - Check if type has a custom inspector
  275. // and return the custom inspector, otherwise create a generic one
  276. return new GenericInspector();
  277. }
  278. }
  279. }