InspectorWindow.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Common;
  4. using System.IO;
  5. using BansheeEngine;
  6. namespace BansheeEditor
  7. {
  8. /// <summary>
  9. /// Displays GUI for a <see cref="SceneObject"/> or for a <see cref="Resource"/>. Scene object's transform values
  10. /// are displayed, along with all their components and their fields.
  11. /// </summary>
  12. internal sealed class InspectorWindow : EditorWindow
  13. {
  14. /// <summary>
  15. /// Type of objects displayed in the window.
  16. /// </summary>
  17. private enum InspectorType
  18. {
  19. SceneObject,
  20. Resource,
  21. Multiple,
  22. None
  23. }
  24. /// <summary>
  25. /// Inspector GUI elements for a single <see cref="Component"/> in a <see cref="SceneObject"/>.
  26. /// </summary>
  27. private class InspectorComponent
  28. {
  29. public GUIToggle foldout;
  30. public GUIButton removeBtn;
  31. public GUIPanel panel;
  32. public Inspector inspector;
  33. public bool expanded = true;
  34. public UInt64 instanceId;
  35. }
  36. /// <summary>
  37. /// Inspector GUI elements for a <see cref="Resource"/>
  38. /// </summary>
  39. private class InspectorResource
  40. {
  41. public GUIPanel panel;
  42. public Inspector inspector;
  43. }
  44. private static readonly Color HIGHLIGHT_COLOR = new Color(1.0f, 1.0f, 1.0f, 0.5f);
  45. private const int RESOURCE_TITLE_HEIGHT = 30;
  46. private List<InspectorComponent> inspectorComponents = new List<InspectorComponent>();
  47. private InspectorResource inspectorResource;
  48. private GUIScrollArea inspectorScrollArea;
  49. private GUILayout inspectorLayout;
  50. private GUIPanel highlightPanel;
  51. private GUITexture scrollAreaHighlight;
  52. private SceneObject activeSO;
  53. private GUITextBox soNameInput;
  54. private GUILayout soPrefabLayout;
  55. private bool soHasPrefab;
  56. private GUIFloatField soPosX;
  57. private GUIFloatField soPosY;
  58. private GUIFloatField soPosZ;
  59. private GUIFloatField soRotX;
  60. private GUIFloatField soRotY;
  61. private GUIFloatField soRotZ;
  62. private GUIFloatField soScaleX;
  63. private GUIFloatField soScaleY;
  64. private GUIFloatField soScaleZ;
  65. private Rect2I dropBounds;
  66. private InspectorType currentType = InspectorType.None;
  67. private Resource activeResource;
  68. /// <summary>
  69. /// Opens the inspector window from the menu bar.
  70. /// </summary>
  71. [MenuItem("Windows/Inspector", ButtonModifier.CtrlAlt, ButtonCode.I, 6000)]
  72. private static void OpenInspectorWindow()
  73. {
  74. OpenWindow<InspectorWindow>();
  75. }
  76. /// <summary>
  77. /// Name of the inspector window to display on the window title.
  78. /// </summary>
  79. /// <returns>Name of the inspector window to display on the window title.</returns>
  80. protected override LocString GetDisplayName()
  81. {
  82. return new LocEdString("Inspector");
  83. }
  84. /// <summary>
  85. /// Sets a resource whose GUI is to be displayed in the inspector. Clears any previous contents of the window.
  86. /// </summary>
  87. /// <param name="resourcePath">Resource path relative to the project of the resource to inspect.</param>
  88. private void SetObjectToInspect(String resourcePath)
  89. {
  90. activeResource = ProjectLibrary.Load<Resource>(resourcePath);
  91. if (activeResource == null)
  92. return;
  93. currentType = InspectorType.Resource;
  94. inspectorScrollArea = new GUIScrollArea();
  95. GUI.AddElement(inspectorScrollArea);
  96. inspectorLayout = inspectorScrollArea.Layout;
  97. GUIPanel titlePanel = inspectorLayout.AddPanel();
  98. titlePanel.SetHeight(RESOURCE_TITLE_HEIGHT);
  99. GUILayoutY titleLayout = titlePanel.AddLayoutY();
  100. titleLayout.SetPosition(5, 5);
  101. string name = Path.GetFileNameWithoutExtension(resourcePath);
  102. string type = activeResource.GetType().Name;
  103. LocString title = new LocEdString(name + " (" + type + ")");
  104. GUILabel titleLabel = new GUILabel(title);
  105. titleLayout.AddFlexibleSpace();
  106. GUILayoutX titleLabelLayout = titleLayout.AddLayoutX();
  107. titleLabelLayout.AddElement(titleLabel);
  108. titleLayout.AddFlexibleSpace();
  109. GUIPanel titleBgPanel = titlePanel.AddPanel(1);
  110. GUITexture titleBg = new GUITexture(null, EditorStyles.InspectorTitleBg);
  111. titleBgPanel.AddElement(titleBg);
  112. inspectorLayout.AddSpace(5);
  113. inspectorResource = new InspectorResource();
  114. inspectorResource.panel = inspectorLayout.AddPanel();
  115. inspectorResource.inspector = InspectorUtility.GetInspector(activeResource.GetType());
  116. inspectorResource.inspector.Initialize(this, inspectorResource.panel, activeResource);
  117. inspectorResource.inspector.Refresh();
  118. inspectorLayout.AddFlexibleSpace();
  119. }
  120. /// <summary>
  121. /// Sets a scene object whose GUI is to be displayed in the inspector. Clears any previous contents of the window.
  122. /// </summary>
  123. /// <param name="so">Scene object to inspect.</param>
  124. private void SetObjectToInspect(SceneObject so)
  125. {
  126. if (so == null)
  127. return;
  128. currentType = InspectorType.SceneObject;
  129. activeSO = so;
  130. inspectorScrollArea = new GUIScrollArea();
  131. scrollAreaHighlight = new GUITexture(Builtin.WhiteTexture);
  132. scrollAreaHighlight.SetTint(HIGHLIGHT_COLOR);
  133. GUI.AddElement(inspectorScrollArea);
  134. highlightPanel = GUI.AddPanel(-1);
  135. highlightPanel.AddElement(scrollAreaHighlight);
  136. inspectorLayout = inspectorScrollArea.Layout;
  137. // SceneObject fields
  138. CreateSceneObjectFields();
  139. RefreshSceneObjectFields(true);
  140. // Components
  141. Component[] allComponents = so.GetComponents();
  142. for (int i = 0; i < allComponents.Length; i++)
  143. {
  144. InspectorComponent data = new InspectorComponent();
  145. data.instanceId = allComponents[i].InstanceId;
  146. data.foldout = new GUIToggle(allComponents[i].GetType().Name, EditorStyles.Foldout);
  147. data.removeBtn = new GUIButton(new GUIContent(EditorBuiltin.XBtnIcon), GUIOption.FixedWidth(30));
  148. GUILayoutX titleLayout = inspectorLayout.AddLayoutX();
  149. titleLayout.AddElement(data.foldout);
  150. titleLayout.AddElement(data.removeBtn);
  151. data.panel = inspectorLayout.AddPanel();
  152. data.inspector = InspectorUtility.GetInspector(allComponents[i].GetType());
  153. data.inspector.Initialize(this, data.panel, allComponents[i]);
  154. data.foldout.Value = true;
  155. Type curComponentType = allComponents[i].GetType();
  156. data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
  157. data.removeBtn.OnClick += () => OnComponentRemoveClicked(curComponentType);
  158. inspectorComponents.Add(data);
  159. inspectorComponents[i].inspector.Refresh();
  160. }
  161. inspectorLayout.AddFlexibleSpace();
  162. dropBounds = inspectorScrollArea.Bounds;
  163. scrollAreaHighlight.Bounds = dropBounds;
  164. }
  165. /// <summary>
  166. /// Creates GUI elements required for displaying <see cref="SceneObject"/> fields like name, prefab data and
  167. /// transform (position, rotation, scale). Assumes that necessary inspector scroll area layout has already been
  168. /// created.
  169. /// </summary>
  170. private void CreateSceneObjectFields()
  171. {
  172. GUIPanel sceneObjectPanel = inspectorLayout.AddPanel();
  173. sceneObjectPanel.SetHeight(GetTitleBounds().height);
  174. GUILayoutY sceneObjectLayout = sceneObjectPanel.AddLayoutY();
  175. sceneObjectLayout.SetPosition(5, 5);
  176. GUIPanel sceneObjectBgPanel = sceneObjectPanel.AddPanel(1);
  177. GUILayoutX nameLayout = sceneObjectLayout.AddLayoutX();
  178. GUILabel nameLbl = new GUILabel(new LocEdString("Name"), GUIOption.FixedWidth(50));
  179. soNameInput = new GUITextBox(false, GUIOption.FlexibleWidth(180));
  180. soNameInput.Text = activeSO.Name;
  181. soNameInput.OnChanged += (x) => { if (activeSO != null) activeSO.Name = x; };
  182. nameLayout.AddElement(nameLbl);
  183. nameLayout.AddElement(soNameInput);
  184. nameLayout.AddFlexibleSpace();
  185. soPrefabLayout = sceneObjectLayout.AddLayoutX();
  186. GUILayoutX positionLayout = sceneObjectLayout.AddLayoutX();
  187. GUILabel positionLbl = new GUILabel(new LocEdString("Position"), GUIOption.FixedWidth(50));
  188. soPosX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
  189. soPosY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
  190. soPosZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
  191. soPosX.OnChanged += (x) => OnPositionChanged(0, x);
  192. soPosY.OnChanged += (y) => OnPositionChanged(1, y);
  193. soPosZ.OnChanged += (z) => OnPositionChanged(2, z);
  194. positionLayout.AddElement(positionLbl);
  195. positionLayout.AddElement(soPosX);
  196. positionLayout.AddSpace(10);
  197. positionLayout.AddFlexibleSpace();
  198. positionLayout.AddElement(soPosY);
  199. positionLayout.AddSpace(10);
  200. positionLayout.AddFlexibleSpace();
  201. positionLayout.AddElement(soPosZ);
  202. positionLayout.AddFlexibleSpace();
  203. GUILayoutX rotationLayout = sceneObjectLayout.AddLayoutX();
  204. GUILabel rotationLbl = new GUILabel(new LocEdString("Rotation"), GUIOption.FixedWidth(50));
  205. soRotX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
  206. soRotY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
  207. soRotZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
  208. soRotX.OnChanged += (x) => OnRotationChanged(0, x);
  209. soRotY.OnChanged += (y) => OnRotationChanged(1, y);
  210. soRotZ.OnChanged += (z) => OnRotationChanged(2, z);
  211. rotationLayout.AddElement(rotationLbl);
  212. rotationLayout.AddElement(soRotX);
  213. rotationLayout.AddSpace(10);
  214. rotationLayout.AddFlexibleSpace();
  215. rotationLayout.AddElement(soRotY);
  216. rotationLayout.AddSpace(10);
  217. rotationLayout.AddFlexibleSpace();
  218. rotationLayout.AddElement(soRotZ);
  219. rotationLayout.AddFlexibleSpace();
  220. GUILayoutX scaleLayout = sceneObjectLayout.AddLayoutX();
  221. GUILabel scaleLbl = new GUILabel(new LocEdString("Scale"), GUIOption.FixedWidth(50));
  222. soScaleX = new GUIFloatField(new LocEdString("X"), 10, "", GUIOption.FixedWidth(60));
  223. soScaleY = new GUIFloatField(new LocEdString("Y"), 10, "", GUIOption.FixedWidth(60));
  224. soScaleZ = new GUIFloatField(new LocEdString("Z"), 10, "", GUIOption.FixedWidth(60));
  225. soScaleX.OnChanged += (x) => OnScaleChanged(0, x);
  226. soScaleY.OnChanged += (y) => OnScaleChanged(1, y);
  227. soScaleX.OnChanged += (z) => OnScaleChanged(2, z);
  228. scaleLayout.AddElement(scaleLbl);
  229. scaleLayout.AddElement(soScaleX);
  230. scaleLayout.AddSpace(10);
  231. scaleLayout.AddFlexibleSpace();
  232. scaleLayout.AddElement(soScaleY);
  233. scaleLayout.AddSpace(10);
  234. scaleLayout.AddFlexibleSpace();
  235. scaleLayout.AddElement(soScaleZ);
  236. scaleLayout.AddFlexibleSpace();
  237. sceneObjectLayout.AddFlexibleSpace();
  238. inspectorLayout.AddSpace(5);
  239. GUITexture titleBg = new GUITexture(null, EditorStyles.InspectorTitleBg);
  240. sceneObjectBgPanel.AddElement(titleBg);
  241. }
  242. /// <summary>
  243. /// Updates contents of the scene object specific fields (name, position, rotation, etc.)
  244. /// </summary>
  245. /// <param name="forceUpdate">If true, the GUI elements will be updated regardless of whether a change was
  246. /// detected or not.</param>
  247. private void RefreshSceneObjectFields(bool forceUpdate)
  248. {
  249. if (activeSO == null)
  250. return;
  251. soNameInput.Text = activeSO.Name;
  252. bool hasPrefab = PrefabUtility.IsPrefabInstance(activeSO);
  253. if (soHasPrefab != hasPrefab || forceUpdate)
  254. {
  255. int numChildren = soPrefabLayout.ChildCount;
  256. for (int i = 0; i < numChildren; i++)
  257. soPrefabLayout.GetChild(0).Destroy();
  258. GUILabel prefabLabel =new GUILabel(new LocEdString("Prefab"), GUIOption.FixedWidth(50));
  259. soPrefabLayout.AddElement(prefabLabel);
  260. if (hasPrefab)
  261. {
  262. GUIButton btnApplyPrefab = new GUIButton(new LocEdString("Apply"), GUIOption.FixedWidth(60));
  263. GUIButton btnRevertPrefab = new GUIButton(new LocEdString("Revert"), GUIOption.FixedWidth(60));
  264. GUIButton btnBreakPrefab = new GUIButton(new LocEdString("Break"), GUIOption.FixedWidth(60));
  265. btnApplyPrefab.OnClick += () => PrefabUtility.ApplyPrefab(activeSO);
  266. btnRevertPrefab.OnClick += () => PrefabUtility.RevertPrefab(activeSO);
  267. btnBreakPrefab.OnClick += () => PrefabUtility.BreakPrefab(activeSO);
  268. soPrefabLayout.AddElement(btnApplyPrefab);
  269. soPrefabLayout.AddElement(btnRevertPrefab);
  270. soPrefabLayout.AddElement(btnBreakPrefab);
  271. }
  272. else
  273. {
  274. GUILabel noPrefabLabel = new GUILabel("None");
  275. soPrefabLayout.AddElement(noPrefabLabel);
  276. }
  277. soHasPrefab = hasPrefab;
  278. }
  279. Vector3 position;
  280. Vector3 angles;
  281. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  282. {
  283. position = activeSO.Position;
  284. angles = activeSO.Rotation.ToEuler();
  285. }
  286. else
  287. {
  288. position = activeSO.LocalPosition;
  289. angles = activeSO.LocalRotation.ToEuler();
  290. }
  291. Vector3 scale = activeSO.LocalScale;
  292. soPosX.Value = position.x;
  293. soPosY.Value = position.y;
  294. soPosZ.Value = position.z;
  295. soRotX.Value = angles.x;
  296. soRotY.Value = angles.y;
  297. soRotZ.Value = angles.z;
  298. soScaleX.Value = scale.x;
  299. soScaleY.Value = scale.y;
  300. soScaleZ.Value = scale.z;
  301. }
  302. private void OnInitialize()
  303. {
  304. Selection.OnSelectionChanged += OnSelectionChanged;
  305. OnSelectionChanged(new SceneObject[0], new string[0]);
  306. }
  307. private void OnDestroy()
  308. {
  309. Selection.OnSelectionChanged -= OnSelectionChanged;
  310. }
  311. private void OnEditorUpdate()
  312. {
  313. if (currentType == InspectorType.SceneObject)
  314. {
  315. Component[] allComponents = activeSO.GetComponents();
  316. bool requiresRebuild = allComponents.Length != inspectorComponents.Count;
  317. if (!requiresRebuild)
  318. {
  319. for (int i = 0; i < inspectorComponents.Count; i++)
  320. {
  321. if (inspectorComponents[i].instanceId != allComponents[i].InstanceId)
  322. {
  323. requiresRebuild = true;
  324. break;
  325. }
  326. }
  327. }
  328. if (requiresRebuild)
  329. {
  330. SceneObject so = activeSO;
  331. Clear();
  332. SetObjectToInspect(so);
  333. }
  334. else
  335. {
  336. RefreshSceneObjectFields(false);
  337. for (int i = 0; i < inspectorComponents.Count; i++)
  338. {
  339. inspectorComponents[i].inspector.Refresh();
  340. }
  341. }
  342. }
  343. else if (currentType == InspectorType.Resource)
  344. {
  345. inspectorResource.inspector.Refresh();
  346. }
  347. // Detect drag and drop
  348. bool isDraggingOver = false;
  349. if (activeSO != null && inspectorScrollArea != null)
  350. {
  351. Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
  352. ScriptCode droppedCodeFile = null;
  353. string droppedCodeFileName = "";
  354. if (DragDrop.DragInProgress && DragDrop.Type == DragDropType.Resource)
  355. {
  356. isDraggingOver = dropBounds.Contains(windowPos);
  357. }
  358. else if (DragDrop.DropInProgress && DragDrop.Type == DragDropType.Resource)
  359. {
  360. ResourceDragDropData dragData = DragDrop.Data as ResourceDragDropData;
  361. if (dragData != null)
  362. {
  363. foreach (var resPath in dragData.Paths)
  364. {
  365. LibraryEntry entry = ProjectLibrary.GetEntry(resPath);
  366. FileEntry fileEntry = entry as FileEntry;
  367. if (fileEntry != null)
  368. {
  369. if (fileEntry.ResType == ResourceType.ScriptCode)
  370. {
  371. droppedCodeFile = ProjectLibrary.Load<ScriptCode>(resPath);
  372. droppedCodeFileName = fileEntry.Name;
  373. break;
  374. }
  375. }
  376. }
  377. }
  378. }
  379. if (droppedCodeFile != null)
  380. {
  381. Type droppedComponentType = null;
  382. Type[] droppedTypes = droppedCodeFile.Types;
  383. foreach (var type in droppedTypes)
  384. {
  385. if (type.IsSubclassOf(typeof(Component)))
  386. {
  387. droppedComponentType = type;
  388. break;
  389. }
  390. }
  391. if (droppedComponentType != null)
  392. {
  393. UndoRedo.RecordSO(activeSO, "Added component " + droppedComponentType.Name);
  394. activeSO.AddComponent(droppedComponentType);
  395. }
  396. else
  397. Debug.LogWarning("Cannot find a Component in " + droppedCodeFileName);
  398. }
  399. }
  400. if (scrollAreaHighlight != null)
  401. scrollAreaHighlight.Visible = isDraggingOver;
  402. }
  403. /// <summary>
  404. /// Triggered when the user selects a new resource or a scene object, or deselects everything.
  405. /// </summary>
  406. /// <param name="objects">A set of new scene objects that were selected.</param>
  407. /// <param name="paths">A set of absolute resource paths that were selected.</param>
  408. private void OnSelectionChanged(SceneObject[] objects, string[] paths)
  409. {
  410. Clear();
  411. if (objects.Length == 0 && paths.Length == 0)
  412. {
  413. currentType = InspectorType.None;
  414. inspectorScrollArea = new GUIScrollArea();
  415. GUI.AddElement(inspectorScrollArea);
  416. inspectorLayout = inspectorScrollArea.Layout;
  417. inspectorLayout.AddFlexibleSpace();
  418. GUILayoutX layoutMsg = inspectorLayout.AddLayoutX();
  419. layoutMsg.AddFlexibleSpace();
  420. layoutMsg.AddElement(new GUILabel(new LocEdString("No object selected")));
  421. layoutMsg.AddFlexibleSpace();
  422. inspectorLayout.AddFlexibleSpace();
  423. }
  424. else if ((objects.Length + paths.Length) > 1)
  425. {
  426. currentType = InspectorType.None;
  427. inspectorScrollArea = new GUIScrollArea();
  428. GUI.AddElement(inspectorScrollArea);
  429. inspectorLayout = inspectorScrollArea.Layout;
  430. inspectorLayout.AddFlexibleSpace();
  431. GUILayoutX layoutMsg = inspectorLayout.AddLayoutX();
  432. layoutMsg.AddFlexibleSpace();
  433. layoutMsg.AddElement(new GUILabel(new LocEdString("Multiple objects selected")));
  434. layoutMsg.AddFlexibleSpace();
  435. inspectorLayout.AddFlexibleSpace();
  436. }
  437. else if (objects.Length == 1)
  438. {
  439. SetObjectToInspect(objects[0]);
  440. }
  441. else if (paths.Length == 1)
  442. {
  443. SetObjectToInspect(paths[0]);
  444. }
  445. }
  446. /// <summary>
  447. /// Triggered when the user closes or expands a component foldout, making the component fields visible or hidden.
  448. /// </summary>
  449. /// <param name="inspectorData">Contains GUI data for the component that was toggled.</param>
  450. /// <param name="expanded">Determines whether to display or hide component contents.</param>
  451. private void OnComponentFoldoutToggled(InspectorComponent inspectorData, bool expanded)
  452. {
  453. inspectorData.expanded = expanded;
  454. inspectorData.inspector.SetVisible(expanded);
  455. }
  456. /// <summary>
  457. /// Triggered when the user clicks the component remove button. Removes that component from the active scene object.
  458. /// </summary>
  459. /// <param name="componentType">Type of the component to remove.</param>
  460. private void OnComponentRemoveClicked(Type componentType)
  461. {
  462. if (activeSO != null)
  463. {
  464. UndoRedo.RecordSO(activeSO, "Removed component " + componentType.Name);
  465. activeSO.RemoveComponent(componentType);
  466. }
  467. }
  468. /// <summary>
  469. /// Destroys all inspector GUI elements.
  470. /// </summary>
  471. internal void Clear()
  472. {
  473. for (int i = 0; i < inspectorComponents.Count; i++)
  474. {
  475. inspectorComponents[i].foldout.Destroy();
  476. inspectorComponents[i].removeBtn.Destroy();
  477. inspectorComponents[i].inspector.Destroy();
  478. }
  479. inspectorComponents.Clear();
  480. if (inspectorResource != null)
  481. {
  482. inspectorResource.inspector.Destroy();
  483. inspectorResource = null;
  484. }
  485. if (inspectorScrollArea != null)
  486. {
  487. inspectorScrollArea.Destroy();
  488. inspectorScrollArea = null;
  489. }
  490. if (scrollAreaHighlight != null)
  491. {
  492. scrollAreaHighlight.Destroy();
  493. scrollAreaHighlight = null;
  494. }
  495. if (highlightPanel != null)
  496. {
  497. highlightPanel.Destroy();
  498. highlightPanel = null;
  499. }
  500. activeSO = null;
  501. soNameInput = null;
  502. soPrefabLayout = null;
  503. soHasPrefab = false;
  504. soPosX = null;
  505. soPosY = null;
  506. soPosZ = null;
  507. soRotX = null;
  508. soRotY = null;
  509. soRotZ = null;
  510. soScaleX = null;
  511. soScaleY = null;
  512. soScaleZ = null;
  513. dropBounds = new Rect2I();
  514. activeResource = null;
  515. currentType = InspectorType.None;
  516. }
  517. /// <summary>
  518. /// Returns the size of the title bar area that is displayed for <see cref="SceneObject"/> specific fields.
  519. /// </summary>
  520. /// <returns>Area of the title bar, relative to the window.</returns>
  521. private Rect2I GetTitleBounds()
  522. {
  523. return new Rect2I(0, 0, Width, 115);
  524. }
  525. /// <summary>
  526. /// Triggered when the position value in the currently active <see cref="SceneObject"/> changes. Updates the
  527. /// necessary GUI elements.
  528. /// </summary>
  529. /// <param name="idx">Index of the coordinate that was changed.</param>
  530. /// <param name="value">New value of the field.</param>
  531. private void OnPositionChanged(int idx, float value)
  532. {
  533. if (activeSO == null)
  534. return;
  535. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  536. {
  537. Vector3 position = activeSO.Position;
  538. position[idx] = value;
  539. activeSO.Position = position;
  540. }
  541. else
  542. {
  543. Vector3 position = activeSO.LocalPosition;
  544. position[idx] = value;
  545. activeSO.LocalPosition = position;
  546. }
  547. }
  548. /// <summary>
  549. /// Triggered when the rotation value in the currently active <see cref="SceneObject"/> changes. Updates the
  550. /// necessary GUI elements.
  551. /// </summary>
  552. /// <param name="idx">Index of the euler angle that was changed (0 - X, 1 - Y, 2 - Z).</param>
  553. /// <param name="value">New value of the field.</param>
  554. private void OnRotationChanged(int idx, float value)
  555. {
  556. if (activeSO == null)
  557. return;
  558. if (EditorApplication.ActiveCoordinateMode == HandleCoordinateMode.World)
  559. {
  560. Vector3 angles = activeSO.Rotation.ToEuler();
  561. angles[idx] = value;
  562. activeSO.Rotation = Quaternion.FromEuler(angles);
  563. }
  564. else
  565. {
  566. Vector3 angles = activeSO.LocalRotation.ToEuler();
  567. angles[idx] = value;
  568. activeSO.LocalRotation = Quaternion.FromEuler(angles);
  569. }
  570. }
  571. /// <summary>
  572. /// Triggered when the scale value in the currently active <see cref="SceneObject"/> changes. Updates the
  573. /// necessary GUI elements.
  574. /// </summary>
  575. /// <param name="idx">Index of the coordinate that was changed.</param>
  576. /// <param name="value">New value of the field.</param>
  577. private void OnScaleChanged(int idx, float value)
  578. {
  579. if (activeSO == null)
  580. return;
  581. Vector3 scale = activeSO.LocalScale;
  582. scale[idx] = value;
  583. activeSO.LocalScale = scale;
  584. }
  585. /// <inheritdoc/>
  586. protected override void WindowResized(int width, int height)
  587. {
  588. base.WindowResized(width, height);
  589. if(inspectorScrollArea != null)
  590. dropBounds = inspectorScrollArea.Bounds;
  591. if (scrollAreaHighlight != null)
  592. scrollAreaHighlight.Bounds = dropBounds;
  593. }
  594. }
  595. }