Browse Source

On the fly CSComponent inspector field updates

Josh Engebretson 10 years ago
parent
commit
0cd46944fb

+ 164 - 52
Script/AtomicEditor/ui/frames/inspector/ComponentInspector.ts

@@ -40,6 +40,57 @@ class ComponentInspector extends Atomic.UISection {
 
     }
 
+    addAttr(attr: Atomic.AttributeInfo, before: Atomic.UIWidget = null, after: Atomic.UIWidget = null): Atomic.UILayout {
+
+        if (attr.mode & Atomic.AM_NOEDIT)
+            return null;
+
+        var binding = DataBinding.createBinding(this.component, attr);
+
+        if (!binding)
+            return null;
+
+        var attrLayout = new Atomic.UILayout();
+
+        attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+
+        var name = new Atomic.UITextField();
+        name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
+        name.skinBg = "InspectorTextAttrName";
+        name.layoutParams = this.atlp;
+
+        if (attr.type == Atomic.VAR_VECTOR3 || attr.type == Atomic.VAR_COLOR ||
+            attr.type == Atomic.VAR_QUATERNION) {
+            attrLayout.axis = Atomic.UI_AXIS_Y;
+            attrLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
+            attrLayout.skinBg = "InspectorVectorAttrLayout";
+        }
+
+        var bname = attr.name;
+
+        if (bname == "Is Enabled")
+            bname = "Enabled";
+
+        name.text = bname;
+        name.fontDescription = this.fd;
+
+        attrLayout.addChild(name);
+
+        attrLayout.addChild(binding.widget);
+
+        if (before)
+            this.attrsVerticalLayout.addChildBefore(attrLayout, before);
+        else if (after)
+            this.attrsVerticalLayout.addChildAfter(attrLayout, after);
+        else
+            this.attrsVerticalLayout.addChild(attrLayout);
+
+
+        this.bindings.push(binding);
+
+        return attrLayout;
+    }
+
     inspect(component: Atomic.Component) {
 
         this.component = component;
@@ -57,22 +108,32 @@ class ComponentInspector extends Atomic.UISection {
 
         }
 
+        // For CSComponents append the classname
+        if (component.typeName == "CSComponent") {
+
+            var csc = <AtomicNET.CSComponent>component;
+
+            if (csc.componentClassName) {
+                this.text = "CS - " + csc.componentClassName;
+            }
+        }
+
         // don't expand by default
         this.value = 0;
 
-        var fd = new Atomic.UIFontDescription();
+        var fd = this.fd = new Atomic.UIFontDescription();
         fd.id = "Vera";
         fd.size = 11;
 
-        var nlp = new Atomic.UILayoutParams();
+        var nlp = this.nlp = new Atomic.UILayoutParams();
         nlp.width = 304;
 
         // atttribute name layout param
-        var atlp = new Atomic.UILayoutParams();
+        var atlp = this.atlp = new Atomic.UILayoutParams();
         atlp.width = 100;
 
 
-        var attrsVerticalLayout = new Atomic.UILayout(Atomic.UI_AXIS_Y);
+        var attrsVerticalLayout = this.attrsVerticalLayout = new Atomic.UILayout(Atomic.UI_AXIS_Y);
         attrsVerticalLayout.spacing = 3;
         attrsVerticalLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
         attrsVerticalLayout.layoutSize = Atomic.UI_LAYOUT_SIZE_AVAILABLE;
@@ -82,49 +143,7 @@ class ComponentInspector extends Atomic.UISection {
         var attrs = component.getAttributes();
 
         for (var i in attrs) {
-
-            var attr = <Atomic.AttributeInfo>attrs[i];
-
-            if (attr.mode & Atomic.AM_NOEDIT)
-                continue;
-
-            var binding = DataBinding.createBinding(component, attr);
-
-            if (!binding)
-                continue;
-
-            var attrLayout = new Atomic.UILayout();
-
-            attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
-
-            var name = new Atomic.UITextField();
-            name.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
-            name.skinBg = "InspectorTextAttrName";
-            name.layoutParams = atlp;
-
-            if (attr.type == Atomic.VAR_VECTOR3 || attr.type == Atomic.VAR_COLOR ||
-                attr.type == Atomic.VAR_QUATERNION) {
-                attrLayout.axis = Atomic.UI_AXIS_Y;
-                attrLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
-                attrLayout.skinBg = "InspectorVectorAttrLayout";
-            }
-
-            var bname = attr.name;
-
-            if (bname == "Is Enabled")
-                bname = "Enabled";
-
-            name.text = bname;
-            name.fontDescription = fd;
-
-            attrLayout.addChild(name);
-
-            attrLayout.addChild(binding.widget);
-
-            attrsVerticalLayout.addChild(attrLayout);
-
-            this.bindings.push(binding);
-
+            this.addAttr(attrs[i]);
         }
 
         // custom component UI
@@ -150,6 +169,20 @@ class ComponentInspector extends Atomic.UISection {
             // auto expand CSComponents
             this.value = 1;
             this.addCSComponentUI(attrsVerticalLayout);
+
+            var csc = <AtomicNET.CSComponent>this.component;
+            var currentClassName = csc.componentClassName;
+
+            this.subscribeToEvent(component, "CSComponentClassChanged", (ev: AtomicNET.CSComponentClassChangedEvent) => {
+
+                if (currentClassName != ev.classname) {
+                    //console.log("CSComponent Class Name Changed ", currentClassName, " ", ev.classname);
+                    this.text = "CS - " + ev.classname;
+                    currentClassName = ev.classname;
+                    this.updateDataBindings();
+                }
+
+            });
         }
 
 
@@ -167,7 +200,7 @@ class ComponentInspector extends Atomic.UISection {
         }
 
 
-        var deleteButton = new Atomic.UIButton();
+        var deleteButton = this.deleteButton = new Atomic.UIButton();
         deleteButton.text = "Delete Component";
         deleteButton.fontDescription = fd;
 
@@ -192,6 +225,74 @@ class ComponentInspector extends Atomic.UISection {
 
     }
 
+    updateDataBindings() {
+
+        var newBindings: Array<DataBinding> = new Array();
+        var foundAttr: Array<Atomic.AttributeInfo> = new Array();
+
+        var attrs = this.component.getAttributes();
+
+        // run through current attr bindings looking for ones to preserve
+        for (var i in this.bindings) {
+
+            var binding = this.bindings[i];
+
+            for (var j in attrs) {
+
+                var attr = <Atomic.AttributeInfo>attrs[j];
+
+                if (attr.name == binding.attrInfo.name && attr.type == binding.attrInfo.type) {
+
+                    newBindings.push(binding);
+                    foundAttr.push(attr);
+                    break;
+
+                }
+
+            }
+
+        }
+
+        // remove bindings that no longer exist
+        for (var i in this.bindings) {
+
+            var binding = this.bindings[i];
+
+            if (newBindings.indexOf(binding) == -1) {
+
+                binding.widget.parent.remove();
+
+            }
+
+        }
+
+        // set new bindings, additional bindings may be added below
+        this.bindings = newBindings;
+
+        // add new attr
+        var curAttrLayout:Atomic.UILayout = null;
+        for (var i in attrs) {
+
+            var attr = attrs[i];
+
+            if (foundAttr.indexOf(attr) == -1) {
+
+                if (!curAttrLayout)
+                  curAttrLayout = this.addAttr(attr, this.deleteButton);
+                else
+                  curAttrLayout = this.addAttr(attr, null, curAttrLayout);
+
+            }
+
+        }
+
+        for (var i in this.bindings) {
+            this.bindings[i].setWidgetValueFromObject();
+            this.bindings[i].objectLocked = false;
+        }
+
+    }
+
     // Move these to a mixing class
 
     addPrefabUI(layout: Atomic.UILayout) {
@@ -475,10 +576,10 @@ class ComponentInspector extends Atomic.UISection {
 
                 o.selectButton.onClick = () => {
 
-                  var cscomponent = <AtomicNET.CSComponent> this.component;
-                  if (cscomponent.assemblyFile) {
-                    var selector = new CSComponentClassSelector(o.editField, cscomponent);
-                  }
+                    var cscomponent = <AtomicNET.CSComponent>this.component;
+                    if (cscomponent.assemblyFile) {
+                        var selector = new CSComponentClassSelector(o.editField, cscomponent);
+                    }
                 }
 
                 break;
@@ -489,6 +590,17 @@ class ComponentInspector extends Atomic.UISection {
     component: Atomic.Component;
     bindings: Array<DataBinding> = new Array();
 
+    fd: Atomic.UIFontDescription;
+
+    nlp: Atomic.UILayoutParams;
+
+    // atttribute name layout param
+    atlp: Atomic.UILayoutParams;
+
+    attrsVerticalLayout: Atomic.UILayout;
+
+    deleteButton: Atomic.UIButton;
+
 
 }
 

+ 11 - 0
Script/TypeScript/AtomicWork.d.ts

@@ -209,6 +209,17 @@ declare module Atomic {
 
 }
 
+declare module AtomicNET {
+
+    export interface CSComponentClassChangedEvent {
+
+      cscomponent: CSComponent;
+      classname: string;
+
+    }
+
+}
+
 declare module ToolCore {
 
     export interface ResourceAddedEvent {

+ 27 - 0
Source/Atomic/UI/UIWidget.cpp

@@ -189,6 +189,24 @@ void UIWidget::OnDelete()
     ReleaseRef();
 }
 
+void UIWidget::AddChildAfter(UIWidget* child, UIWidget* otherChild)
+{
+    if (!widget_ || !child || !child->widget_ || !otherChild || !otherChild->widget_)
+        return;
+
+    widget_->AddChildRelative(child->widget_, tb::WIDGET_Z_REL_AFTER, otherChild->widget_);
+
+}
+
+void UIWidget::AddChildBefore(UIWidget* child, UIWidget* otherChild)
+{
+    if (!widget_ || !child || !child->widget_ || !otherChild || !otherChild->widget_)
+        return;
+
+    widget_->AddChildRelative(child->widget_, tb::WIDGET_Z_REL_BEFORE, otherChild->widget_);
+
+}
+
 void UIWidget::AddChild(UIWidget* child)
 {
     if (!widget_ || !child || !child->widget_)
@@ -398,6 +416,15 @@ void UIWidget::SetSkinBg(const String& id)
 
 }
 
+void UIWidget::Remove()
+{
+    if (!widget_ || !widget_->GetParent())
+        return;
+
+    widget_->GetParent()->RemoveChild(widget_);
+
+}
+
 void UIWidget::RemoveChild(UIWidget* child, bool cleanup)
 {
     if (!widget_ || !child)

+ 4 - 0
Source/Atomic/UI/UIWidget.h

@@ -179,6 +179,7 @@ class UIWidget : public Object, public tb::TBWidgetDelegate
     void SetLayoutParams(UILayoutParams* params);
     void SetFontDescription(UIFontDescription* fd);
 
+    void Remove();
     void RemoveChild(UIWidget* child, bool cleanup = true);
 
     void DeleteAllChildren();
@@ -229,6 +230,9 @@ class UIWidget : public Object, public tb::TBWidgetDelegate
 
     virtual void AddChild(UIWidget* child);
 
+    void AddChildAfter(UIWidget* child, UIWidget* otherChild);
+    void AddChildBefore(UIWidget* child, UIWidget* otherChild);
+
     /// Add the child to this widget. See AddChild for adding a child to the top or bottom.
     /// This takes a relative Z and insert the child before or after the given reference widget.
     void AddChildRelative(UIWidget* child, UI_WIDGET_Z_REL z, UIWidget* reference);

+ 15 - 0
Source/AtomicNET/NETCore/CSComponent.cpp

@@ -33,6 +33,7 @@
 #include <Atomic/Scene/Scene.h>
 #include <Atomic/Scene/SceneEvents.h>
 
+#include "NETEvents.h"
 #include "NETVariant.h"
 #include "NETManaged.h"
 #include "CSComponent.h"
@@ -167,6 +168,20 @@ void CSComponent::ApplyFieldValues()
 
 }
 
+void CSComponent::SetComponentClassName(const String& name)
+{
+    componentClassName_ = name;
+
+    if (assemblyFile_ && assemblyFile_->GetClassNames().Contains(name))
+    {
+        using namespace CSComponentClassChanged;
+        VariantMap eventData;
+        eventData[P_CSCOMPONENT] = this;
+        eventData[P_CLASSNAME] = name;
+        SendEvent(E_CSCOMPONENTCLASSCHANGED, eventData);
+    }
+}
+
 void CSComponent::OnNodeSet(Node* node)
 {
     if (node)

+ 1 - 1
Source/AtomicNET/NETCore/CSComponent.h

@@ -76,7 +76,7 @@ public:
     void ApplyFieldValues();
     VariantMap& GetFieldValues() { return fieldValues_; }
 
-    void SetComponentClassName(const String& name) { componentClassName_ = name; }
+    void SetComponentClassName(const String& name);
     const String& GetComponentClassName() const { return componentClassName_; }
 
     virtual ScriptComponentFile* GetComponentFile() { return assemblyFile_; }

+ 37 - 0
Source/AtomicNET/NETCore/NETEvents.h

@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#pragma once
+
+#include <Atomic/Core/Object.h>
+
+namespace Atomic
+{
+
+/// Frame begin event.
+EVENT(E_CSCOMPONENTCLASSCHANGED, CSComponentClassChanged)
+{
+    PARAM(P_CSCOMPONENT, CSComponent);      // CSComponent Ptr
+    PARAM(P_CLASSNAME, Classname);          // String
+}
+
+}