NodeInspector.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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. this.isPrefab = this.detectPrefab(node);
  73. var fd = new Atomic.UIFontDescription();
  74. fd.id = "Vera";
  75. fd.size = 11;
  76. var nlp = new Atomic.UILayoutParams();
  77. nlp.width = 304;
  78. var nodeLayout = this.nodeLayout = new Atomic.UILayout();
  79. nodeLayout.spacing = 4;
  80. nodeLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
  81. nodeLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
  82. nodeLayout.layoutParams = nlp;
  83. nodeLayout.axis = Atomic.UI_AXIS_Y;
  84. // node attr layout
  85. var nodeSection = new Atomic.UISection();
  86. nodeSection.text = "Node";
  87. nodeSection.value = 1;
  88. nodeLayout.addChild(nodeSection);
  89. var attrsVerticalLayout = new Atomic.UILayout(Atomic.UI_AXIS_Y);
  90. attrsVerticalLayout.spacing = 3;
  91. attrsVerticalLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
  92. attrsVerticalLayout.layoutSize = Atomic.UI_LAYOUT_SIZE_AVAILABLE;
  93. nodeSection.contentRoot.addChild(attrsVerticalLayout);
  94. var attrs = node.getAttributes();
  95. for (var i in attrs) {
  96. var attr = <Atomic.AttributeInfo> attrs[i];
  97. if (attr.mode & Atomic.AM_NOEDIT)
  98. continue;
  99. var binding = DataBinding.createBinding(node, attr);
  100. if (!binding)
  101. continue;
  102. var attrLayout = new Atomic.UILayout();
  103. attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
  104. var name = new Atomic.UITextField();
  105. name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
  106. name.skinBg = "InspectorTextAttrName";
  107. if (attr.type == Atomic.VAR_VECTOR3 || attr.type == Atomic.VAR_COLOR ||
  108. attr.type == Atomic.VAR_QUATERNION) {
  109. attrLayout.axis = Atomic.UI_AXIS_Y;
  110. attrLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
  111. attrLayout.skinBg = "InspectorVectorAttrLayout";
  112. }
  113. var bname = attr.name;
  114. if (bname == "Is Enabled")
  115. bname = "Enabled";
  116. name.text = bname;
  117. name.fontDescription = fd;
  118. attrLayout.addChild(name);
  119. attrLayout.addChild(binding.widget);
  120. attrsVerticalLayout.addChild(attrLayout);
  121. this.bindings.push(binding);
  122. }
  123. // PREFAB
  124. if (this.isPrefab) {
  125. var name = new Atomic.UITextField();
  126. name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
  127. name.skinBg = "InspectorTextAttrName";
  128. name.text = "Prefab"
  129. name.fontDescription = fd;
  130. var prefabLayout = new Atomic.UILayout();
  131. prefabLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
  132. var saveButton = new Atomic.UIButton();
  133. saveButton.text = "Save";
  134. saveButton.fontDescription = fd;
  135. saveButton.onClick = () => {
  136. var prefabComponent = this.getPrefabComponent(this.node);
  137. if (prefabComponent) {
  138. prefabComponent.savePrefab();
  139. this.sendEvent("EditorActiveNodeChange", { node: this.node });
  140. return true;
  141. }
  142. }
  143. var undoButton = new Atomic.UIButton();
  144. undoButton.text = "Undo";
  145. undoButton.fontDescription = fd;
  146. undoButton.onClick = () => {
  147. var prefabComponent = this.getPrefabComponent(this.node);
  148. if (prefabComponent) {
  149. prefabComponent.undoPrefab();
  150. this.sendEvent("EditorActiveNodeChange", { node: this.node });
  151. return true;
  152. }
  153. }
  154. var breakButton = new Atomic.UIButton();
  155. breakButton.text = "Break";
  156. breakButton.fontDescription = fd;
  157. breakButton.onClick = () => {
  158. var prefabComponent = this.getPrefabComponent(this.node);
  159. if (prefabComponent) {
  160. prefabComponent.breakPrefab();
  161. return true;
  162. }
  163. }
  164. prefabLayout.addChild(name);
  165. prefabLayout.addChild(saveButton);
  166. prefabLayout.addChild(undoButton);
  167. prefabLayout.addChild(breakButton);
  168. attrsVerticalLayout.addChild(prefabLayout);
  169. }
  170. // COMPONENTS
  171. var components = node.getComponents();
  172. for (var i in components) {
  173. var component = components[i];
  174. //if (component.isTemporary())
  175. // continue;
  176. var ci = new ComponentInspector();
  177. ci.inspect(component);
  178. nodeLayout.addChild(ci);
  179. }
  180. this.addChild(nodeLayout);
  181. var button = new CreateComponentButton(node);
  182. nodeLayout.addChild(button);
  183. for (var i in this.bindings) {
  184. this.bindings[i].setWidgetValueFromObject();
  185. this.bindings[i].objectLocked = false;
  186. }
  187. }
  188. isPrefab: boolean;
  189. node: Atomic.Node;
  190. nodeLayout: Atomic.UILayout;
  191. bindings: Array<DataBinding>;
  192. gizmoMoved = false;
  193. updateDelta = 0;
  194. }
  195. export = NodeInspector;