NodeInspector.ts 7.5 KB

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