NodeInspector.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. import ScriptWidget = require("ui/ScriptWidget");
  8. import ComponentInspector = require("./ComponentInspector");
  9. import DataBinding = require("./DataBinding");
  10. import CreateComponentButton = require("./CreateComponentButton");
  11. class NodeInspector extends ScriptWidget {
  12. constructor() {
  13. super();
  14. this.subscribeToEvent(this, "WidgetEvent", (ev) => this.handleWidgetEvent(ev));
  15. this.subscribeToEvent("GizmoMoved", (ev) => this.handleGizmoModed(ev));
  16. this.subscribeToEvent("Update", (ev) => this.handleUpdate(ev));
  17. }
  18. handleUpdate(ev) {
  19. // to keep from spamming UI update we have a little delta on the gizmo updates
  20. if (!this.node) {
  21. this.gizmoMoved = false;
  22. return;
  23. }
  24. if (this.gizmoMoved) {
  25. if (this.updateDelta > 1.0) {
  26. this.updateDelta = 0.0;
  27. }
  28. else {
  29. this.updateDelta -= ev.timeStep;
  30. }
  31. if (this.updateDelta <= 0) {
  32. for (var i in this.bindings) {
  33. this.bindings[i].setWidgetValueFromObject();
  34. }
  35. this.gizmoMoved = false;
  36. this.updateDelta = 0;
  37. }
  38. }
  39. }
  40. handleGizmoModed(ev) {
  41. if (!this.node) return;
  42. this.gizmoMoved = true;
  43. this.updateDelta += .3;
  44. }
  45. handleWidgetEvent(ev: Atomic.UIWidgetEvent) {
  46. var handled = false;
  47. for (var i = 0; i < this.bindings.length; i++) {
  48. if (this.bindings[i].handleWidgetEvent(ev)) {
  49. handled = true;
  50. }
  51. }
  52. // return handled
  53. return handled;
  54. }
  55. getPrefabComponent(node: Atomic.Node): Atomic.PrefabComponent {
  56. if (node.getComponent("PrefabComponent"))
  57. return <Atomic.PrefabComponent> node.getComponent("PrefabComponent");
  58. if (node.parent)
  59. return this.getPrefabComponent(node.parent);
  60. return null;
  61. }
  62. detectPrefab(node: Atomic.Node): boolean {
  63. if (node.getComponent("PrefabComponent"))
  64. return true;
  65. if (node.parent)
  66. return this.detectPrefab(node.parent);
  67. return false;
  68. }
  69. inspect(node: Atomic.Node) {
  70. this.bindings = new Array();
  71. this.node = node;
  72. node.scene.sendEvent("SceneEditSerializable", { serializable: node, operation: 0});
  73. this.subscribeToEvent(node, "SceneEditSerializableUndoRedo", (data) => this.handleSceneEditSerializableUndoRedoEvent(data));
  74. this.isPrefab = this.detectPrefab(node);
  75. var fd = new Atomic.UIFontDescription();
  76. fd.id = "Vera";
  77. fd.size = 11;
  78. var nlp = new Atomic.UILayoutParams();
  79. nlp.width = 304;
  80. var nodeLayout = this.nodeLayout = new Atomic.UILayout();
  81. nodeLayout.spacing = 4;
  82. nodeLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
  83. nodeLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
  84. nodeLayout.layoutParams = nlp;
  85. nodeLayout.axis = Atomic.UI_AXIS_Y;
  86. // node attr layout
  87. var nodeSection = new Atomic.UISection();
  88. nodeSection.text = "Node";
  89. nodeSection.value = 1;
  90. nodeLayout.addChild(nodeSection);
  91. var attrsVerticalLayout = new Atomic.UILayout(Atomic.UI_AXIS_Y);
  92. attrsVerticalLayout.spacing = 3;
  93. attrsVerticalLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
  94. attrsVerticalLayout.layoutSize = Atomic.UI_LAYOUT_SIZE_AVAILABLE;
  95. nodeSection.contentRoot.addChild(attrsVerticalLayout);
  96. var attrs = node.getAttributes();
  97. for (var i in attrs) {
  98. var attr = <Atomic.AttributeInfo> attrs[i];
  99. if (attr.mode & Atomic.AM_NOEDIT)
  100. continue;
  101. var binding = DataBinding.createBinding(node, attr);
  102. if (!binding)
  103. continue;
  104. var attrLayout = new Atomic.UILayout();
  105. attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
  106. var name = new Atomic.UITextField();
  107. name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
  108. name.skinBg = "InspectorTextAttrName";
  109. if (attr.type == Atomic.VAR_VECTOR3 || attr.type == Atomic.VAR_COLOR ||
  110. attr.type == Atomic.VAR_QUATERNION) {
  111. attrLayout.axis = Atomic.UI_AXIS_Y;
  112. attrLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
  113. attrLayout.skinBg = "InspectorVectorAttrLayout";
  114. }
  115. var bname = attr.name;
  116. if (bname == "Is Enabled")
  117. bname = "Enabled";
  118. name.text = bname;
  119. name.fontDescription = fd;
  120. attrLayout.addChild(name);
  121. attrLayout.addChild(binding.widget);
  122. attrsVerticalLayout.addChild(attrLayout);
  123. this.bindings.push(binding);
  124. }
  125. // PREFAB
  126. if (this.isPrefab) {
  127. var name = new Atomic.UITextField();
  128. name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
  129. name.skinBg = "InspectorTextAttrName";
  130. name.text = "Prefab"
  131. name.fontDescription = fd;
  132. var prefabLayout = new Atomic.UILayout();
  133. prefabLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
  134. var saveButton = new Atomic.UIButton();
  135. saveButton.text = "Save";
  136. saveButton.fontDescription = fd;
  137. saveButton.onClick = () => {
  138. var prefabComponent = this.getPrefabComponent(this.node);
  139. if (prefabComponent) {
  140. prefabComponent.savePrefab();
  141. this.sendEvent("EditorActiveNodeChange", { node: this.node });
  142. return true;
  143. }
  144. }
  145. var undoButton = new Atomic.UIButton();
  146. undoButton.text = "Undo";
  147. undoButton.fontDescription = fd;
  148. undoButton.onClick = () => {
  149. var prefabComponent = this.getPrefabComponent(this.node);
  150. if (prefabComponent) {
  151. prefabComponent.undoPrefab();
  152. this.sendEvent("EditorActiveNodeChange", { node: this.node });
  153. return true;
  154. }
  155. }
  156. var breakButton = new Atomic.UIButton();
  157. breakButton.text = "Break";
  158. breakButton.fontDescription = fd;
  159. breakButton.onClick = () => {
  160. var prefabComponent = this.getPrefabComponent(this.node);
  161. if (prefabComponent) {
  162. prefabComponent.breakPrefab();
  163. return true;
  164. }
  165. }
  166. prefabLayout.addChild(name);
  167. prefabLayout.addChild(saveButton);
  168. prefabLayout.addChild(undoButton);
  169. prefabLayout.addChild(breakButton);
  170. attrsVerticalLayout.addChild(prefabLayout);
  171. }
  172. // COMPONENTS
  173. var components = node.getComponents();
  174. for (var i in components) {
  175. var component = components[i];
  176. //if (component.isTemporary())
  177. // continue;
  178. var ci = new ComponentInspector();
  179. ci.inspect(component);
  180. nodeLayout.addChild(ci);
  181. }
  182. this.addChild(nodeLayout);
  183. var button = new CreateComponentButton(node);
  184. nodeLayout.addChild(button);
  185. for (var i in this.bindings) {
  186. this.bindings[i].setWidgetValueFromObject();
  187. this.bindings[i].objectLocked = false;
  188. }
  189. }
  190. handleSceneEditSerializableUndoRedoEvent(ev) {
  191. for (var i in this.bindings) {
  192. this.bindings[i].objectLocked = true;
  193. this.bindings[i].setWidgetValueFromObject();
  194. this.bindings[i].objectLocked = false;
  195. }
  196. }
  197. isPrefab: boolean;
  198. node: Atomic.Node;
  199. nodeLayout: Atomic.UILayout;
  200. bindings: Array<DataBinding>;
  201. gizmoMoved = false;
  202. updateDelta = 0;
  203. }
  204. export = NodeInspector;