Browse Source

Working on model animation UI

Josh Engebretson 10 years ago
parent
commit
882e8e2e34

+ 2 - 0
Script/AtomicEditor/tsconfig.json

@@ -24,10 +24,12 @@
         "./ui/ResourceFrame.ts",
         "./ui/ScriptWidget.ts",
         "./ui/UIEvents.ts",
+        "./ui/inspector/ArrayEditWidget.ts",
         "./ui/inspector/ComponentInspector.ts",
         "./ui/inspector/CreateComponentButton.ts",
         "./ui/inspector/DataBinding.ts",
         "./ui/inspector/InspectorFrame.ts",
+        "./ui/inspector/InspectorUtils.ts",
         "./ui/inspector/InspectorWidget.ts",
         "./ui/inspector/MaterialInspector.ts",
         "./ui/inspector/ModelInspector.ts",

+ 2 - 0
Script/AtomicEditor/ui/ResourceFrame.ts

@@ -111,6 +111,8 @@ class ResourceFrame extends ScriptWidget {
         var editor = <Editor.ResourceEditor> data.editor;
         var navigate = <boolean> data.navigateToAvailableResource;
 
+        editor.unsubscribeFromAllEvents();
+
         // remove from lookup
         delete this.editors[editor.fullPath];
 

+ 82 - 0
Script/AtomicEditor/ui/inspector/ArrayEditWidget.ts

@@ -0,0 +1,82 @@
+
+import InspectorUtils = require("./InspectorUtils");
+
+class ArrayEditWidget extends Atomic.UILayout {
+
+    constructor(title:string) {
+
+        super();
+
+        var nlp = new Atomic.UILayoutParams();
+        nlp.width = 310;
+
+        this.spacing = 4;
+
+        this.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+        this.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
+        this.layoutParams = nlp;
+        this.axis = Atomic.UI_AXIS_Y;
+
+        this.gravity = Atomic.UI_GRAVITY_ALL;
+
+        var countEdit = InspectorUtils.createAttrEditField(title, this);
+
+        InspectorUtils.createSeparator(this);
+
+        this.countEditField = <Atomic.UIEditField> countEdit.getWidget("editfield");
+
+        this.subscribeToEvent(this.countEditField, "WidgetEvent", (data) => this.handleCountWidgetEvent(data));
+        this.subscribeToEvent(this.countEditField, "WidgetFocusChanged", (data) => this.handleCountWidgetFocusChanged(data));
+
+    }
+
+    handleCountWidgetFocusChanged(ev) {
+
+        if (ev.focused) {
+
+            this.countRestore = this.countEditField.text;
+
+        } else {
+
+            this.countEditField.text = this.countRestore;
+
+        }
+
+    }
+
+    handleCountWidgetEvent(ev: Atomic.UIWidgetEvent) {
+
+        if (ev.type == Atomic.UI_EVENT_TYPE_KEY_UP) {
+
+            if (ev.key == Atomic.KEY_RETURN) {
+
+                if (this.countRestore != this.countEditField.text) {
+
+                    this.countRestore = this.countEditField.text;
+
+                    if (this.onCountChanged) {
+
+                      this.onCountChanged(Number(this.countRestore));
+
+                    }
+
+                }
+
+            }
+
+        }
+
+        if (ev.type == Atomic.UI_EVENT_TYPE_CHANGED) {
+
+        }
+
+    }
+
+    onCountChanged: (count:number) => void;
+
+    countRestore: string;
+    countEditField: Atomic.UIEditField;
+
+}
+
+export = ArrayEditWidget;

+ 1 - 3
Script/AtomicEditor/ui/inspector/InspectorFrame.ts

@@ -9,15 +9,13 @@ import MaterialInspector = require("./MaterialInspector");
 import ModelInspector = require("./ModelInspector");
 import NodeInspector = require("./NodeInspector");
 
-var UI = Atomic.UI;
-
 class InspectorFrame extends ScriptWidget {
 
     constructor() {
 
         super();
 
-        this.gravity = UI.GRAVITY_TOP_BOTTOM;
+        this.gravity = Atomic.UI_GRAVITY_TOP_BOTTOM;
 
         this.load("AtomicEditor/editor/ui/inspectorframe.tb.txt");
 

+ 75 - 0
Script/AtomicEditor/ui/inspector/InspectorUtils.ts

@@ -0,0 +1,75 @@
+
+class InspectorUtils {
+
+  static init() {
+
+    var fd = InspectorUtils.attrFontDesc = new Atomic.UIFontDescription();
+    fd.id = "Vera";
+    fd.size = 11;
+
+    // must not be void dor static initializer
+    return null;
+
+  }
+
+  static createSeparator(parent:Atomic.UIWidget):Atomic.UISeparator {
+
+    var sep = new Atomic.UISeparator();
+
+    sep.gravity = Atomic.UI_GRAVITY_LEFT_RIGHT;
+    sep.skinBg = "AESeparator";
+
+    parent.addChild(sep);
+    return sep;
+
+  }
+
+  static createAttrName(name:string):Atomic.UITextField {
+
+    var nameField = new Atomic.UITextField();
+    nameField.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
+    nameField.skinBg = "InspectorTextAttrName";
+    nameField.text = name;
+    nameField.fontDescription = InspectorUtils.attrFontDesc;
+    return nameField;
+  }
+
+  static createEditField():Atomic.UIEditField {
+
+    var edit = new Atomic.UIEditField();
+    edit.id = "editfield";
+    edit.textAlign = Atomic.UI_TEXT_ALIGN_LEFT;
+    edit.skinBg = "TBAttrEditorField";
+    edit.fontDescription = InspectorUtils.attrFontDesc;
+    var lp = new Atomic.UILayoutParams();
+    lp.width = 140;
+    edit.layoutParams = lp;
+
+    return edit;
+
+  }
+
+  static createAttrEditField(name:string, parent:Atomic.UIWidget):Atomic.UIEditField {
+
+    var attrLayout = new Atomic.UILayout();
+    attrLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+
+    var _name = InspectorUtils.createAttrName(name);
+    attrLayout.addChild(_name);
+
+    var edit = InspectorUtils.createEditField();
+
+    attrLayout.addChild(edit);
+    parent.addChild(attrLayout);
+
+    return edit;
+
+  }
+
+  // "static constructor"
+  private static _init = InspectorUtils.init();
+  private static attrFontDesc:Atomic.UIFontDescription;
+
+}
+
+export = InspectorUtils;

+ 0 - 1
Script/AtomicEditor/ui/inspector/InspectorWidget.ts

@@ -103,7 +103,6 @@ class InspectorWidget extends ScriptWidget {
 
     }
 
-
     createAttrEditField(name:string, parent:Atomic.UIWidget):Atomic.UIEditField {
 
       var attrLayout = new Atomic.UILayout();

+ 42 - 8
Script/AtomicEditor/ui/inspector/ModelInspector.ts

@@ -1,6 +1,8 @@
 
 
 import InspectorWidget = require("./InspectorWidget");
+import ArrayEditWidget = require("./ArrayEditWidget");
+import InspectorUtils = require("./InspectorUtils");
 
 class ModelInspector extends InspectorWidget {
 
@@ -19,8 +21,6 @@ class ModelInspector extends InspectorWidget {
     onApply() {
 
         this.importer.scale = Number(this.scaleEdit.text);
-        //this.importer.startTime = Number(this.startTimeEdit.text);
-        //this.importer.endTime = Number(this.endTimeEdit.text);
 
         this.importer.importAnimations = this.importAnimationBox.value ? true : false;
 
@@ -49,24 +49,58 @@ class ModelInspector extends InspectorWidget {
         this.importAnimationBox = this.createAttrCheckBox("Import Animations", animationLayout);
         this.importAnimationBox.value = this.importer.importAnimations ? 1 : 0;
 
-        this.startTimeEdit = this.createAttrEditField("Start Time", animationLayout);
-        //this.startTimeEdit.text = this.importer.startTime.toString();
+        this.importAnimationArray = new ArrayEditWidget("Animation Count");
+        animationLayout.addChild(this.importAnimationArray);
 
-        this.endTimeEdit = this.createAttrEditField("End Time", animationLayout);
-        //this.endTimeEdit.text = this.importer.endTime.toString();
+        this.importAnimationArray.onCountChanged = (count) => this.onAnimationCountChanged(count);
+
+        var nlp = new Atomic.UILayoutParams();
+        nlp.width = 310;
+
+        var animLayout = this.animationInfoLayout = new Atomic.UILayout();
+
+        animLayout.spacing = 4;
+
+        animLayout.layoutDistribution = Atomic.UI_LAYOUT_DISTRIBUTION_GRAVITY;
+        animLayout.layoutPosition = Atomic.UI_LAYOUT_POSITION_LEFT_TOP;
+        animLayout.layoutParams = nlp;
+        animLayout.axis = Atomic.UI_AXIS_Y;
+        animLayout.gravity = Atomic.UI_GRAVITY_ALL;
+
+        animationLayout.addChild(animLayout);
 
         // apply button
         rootLayout.addChild(this.createApplyButton());
 
     }
 
+    onAnimationCountChanged(count:number) {
+
+      var layout = this.animationInfoLayout;
+      layout.deleteAllChildren();
+
+      for (var i = 0; i < count; i++) {
+
+        var name = InspectorUtils.createAttrName("Animation " + i.toString() + ":");
+        layout.addChild(name);
+
+        InspectorUtils.createAttrEditField("Name", layout);
+        InspectorUtils.createAttrEditField("Start", layout);
+        InspectorUtils.createAttrEditField("End", layout);
+
+        InspectorUtils.createSeparator(layout);
+
+      }
+
+    }
+
     // model
     scaleEdit: Atomic.UIEditField;
 
     // animation
-    startTimeEdit: Atomic.UIEditField;
-    endTimeEdit: Atomic.UIEditField;
     importAnimationBox: Atomic.UICheckBox;
+    importAnimationArray: ArrayEditWidget;
+    animationInfoLayout: Atomic.UILayout;
 
     asset: ToolCore.Asset;
     importer: ToolCore.ModelImporter;

+ 8 - 0
Script/TypeScript/Atomic.d.ts

@@ -7274,6 +7274,13 @@ declare module Atomic {
 
    }
 
+   export class UISeparator extends UIWidget {
+
+      constructor(createWidget?: boolean);
+
+
+   }
+
    export class UISkinImage extends UIWidget {
 
       constructor(bitmapID: string, createWidget?: boolean);
@@ -7368,6 +7375,7 @@ declare module Atomic {
       setValue(value: number): void;
       getValue(): number;
       setFocus(): void;
+      onFocusChanged(focused: boolean): void;
       setState(state: number, on: boolean): void;
       getState(state: number): boolean;
       setVisibility(visibility: UI_WIDGET_VISIBILITY): void;

+ 10 - 0
Source/Atomic/UI/UI.cpp

@@ -52,6 +52,7 @@ using namespace tb;
 #include "UISection.h"
 #include "UIInlineSelect.h"
 #include "UIScrollContainer.h"
+#include "UISeparator.h"
 
 namespace tb
 {
@@ -494,6 +495,15 @@ UIWidget* UI::WrapWidget(tb::TBWidget* widget)
         return section;
     }
 
+    if (widget->IsOfType<TBSeparator>())
+    {
+        UISeparator* sep = new UISeparator(context_, false);
+        sep->SetWidget(widget);
+        widgetWrap_[widget] = sep;
+        return sep;
+    }
+
+
     if (widget->IsOfType<TBContainer>())
     {
         UIContainer* container = new UIContainer(context_, false);

+ 1 - 1
Source/Atomic/UI/UIEditField.cpp

@@ -74,7 +74,7 @@ void UIEditField::SetTextAlign(TEXT_ALIGN align)
 
 bool UIEditField::OnEvent(const tb::TBWidgetEvent &ev)
 {
-    return false;
+    return UIWidget::OnEvent(ev);
 }
 
 }

+ 7 - 0
Source/Atomic/UI/UIEvents.h

@@ -53,6 +53,13 @@ EVENT(E_WIDGETLOADED, WidgetLoaded)
     PARAM(P_WIDGET, Widget);             // UIWidget pointer
 }
 
+EVENT(E_WIDGETFOCUSCHANGED, WidgetFocusChanged)
+{
+    PARAM(P_WIDGET, Widget);             // UIWidget pointer
+    PARAM(P_FOCUSED, Focused);             // bool
+}
+
+
 EVENT(E_WIDGETDELETED, WidgetDeleted)
 {
     PARAM(P_WIDGET, Widget);             // UIWidget pointer

+ 36 - 0
Source/Atomic/UI/UISeparator.cpp

@@ -0,0 +1,36 @@
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_widgets_common.h>
+
+#include <Atomic/IO/Log.h>
+
+#include "UIEvents.h"
+#include "UI.h"
+#include "UISeparator.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UISeparator::UISeparator(Context* context, bool createWidget) : UIWidget(context, false)
+{
+    if (createWidget)
+    {
+        widget_ = new TBSeparator();
+        widget_->SetDelegate(this);
+        GetSubsystem<UI>()->WrapWidget(this, widget_);
+    }
+}
+
+UISeparator::~UISeparator()
+{
+
+}
+
+bool UISeparator::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    return UIWidget::OnEvent(ev);
+}
+
+}

+ 28 - 0
Source/Atomic/UI/UISeparator.h

@@ -0,0 +1,28 @@
+
+
+#pragma once
+
+#include "UIWidget.h"
+
+namespace Atomic
+{
+
+class UISeparator : public UIWidget
+{
+    OBJECT(UISeparator)
+
+public:
+
+    UISeparator(Context* context, bool createWidget = true);
+    virtual ~UISeparator();
+
+protected:
+
+    virtual bool OnEvent(const tb::TBWidgetEvent &ev);
+
+private:
+
+};
+
+}
+

+ 42 - 2
Source/Atomic/UI/UIWidget.cpp

@@ -2,6 +2,7 @@
 //--player --editor-resource-paths "/Users/josh/Dev/atomic/AtomicGameEngine/Data/AtomicPlayer/Resources/CoreData!/Users/josh/Dev/atomic/AtomicGameEngine/Data/AtomicPlayer/Resources/PlayerData!/Users/josh/Dev/atomic/AtomicExamples/UIExample/Resources"
 
 #include "../IO/Log.h"
+#include "../Input/InputEvents.h"
 
 #include "UIEvents.h"
 #include "UI.h"
@@ -88,6 +89,20 @@ void UIWidget::SetWidget(tb::TBWidget* widget)
     widget_->SetDelegate(this);
 }
 
+/*
+enum SPECIAL_KEY
+{
+    TB_KEY_UNDEFINED = 0,
+    TB_KEY_UP, TB_KEY_DOWN, TB_KEY_LEFT, TB_KEY_RIGHT,
+    TB_KEY_PAGE_UP, TB_KEY_PAGE_DOWN, TB_KEY_HOME, TB_KEY_END,
+    TB_KEY_TAB, TB_KEY_BACKSPACE, TB_KEY_INSERT, TB_KEY_DELETE,
+    TB_KEY_ENTER, TB_KEY_ESC,
+    TB_KEY_F1, TB_KEY_F2, TB_KEY_F3, TB_KEY_F4, TB_KEY_F5, TB_KEY_F6,
+    TB_KEY_F7, TB_KEY_F8, TB_KEY_F9, TB_KEY_F10, TB_KEY_F11, TB_KEY_F12
+};
+*/
+
+
 void UIWidget::ConvertEvent(UIWidget *handler, UIWidget* target, const tb::TBWidgetEvent &ev, VariantMap& data)
 {
     UI* ui = GetSubsystem<UI>();
@@ -96,6 +111,20 @@ void UIWidget::ConvertEvent(UIWidget *handler, UIWidget* target, const tb::TBWid
 
     ui->GetTBIDString(ev.ref_id, refid);
 
+    int key = ev.key;
+
+    if (ev.special_key)
+    {
+        switch (ev.special_key)
+        {
+        case TB_KEY_ENTER:
+            key = KEY_RETURN;
+            break;
+        default:
+            break;
+        }
+    }
+
     using namespace WidgetEvent;
     data[P_HANDLER] = handler;
     data[P_TARGET] = target;
@@ -105,7 +134,7 @@ void UIWidget::ConvertEvent(UIWidget *handler, UIWidget* target, const tb::TBWid
     data[P_DELTAX] = ev.delta_x;
     data[P_DELTAY] = ev.delta_y;
     data[P_COUNT] = ev.count;
-    data[P_KEY] = ev.key;
+    data[P_KEY] = key;
     data[P_SPECIALKEY] = (unsigned) ev.special_key;
     data[P_MODIFIERKEYS] = (unsigned) ev.modifierkeys;
     data[P_REFID] = refid;
@@ -510,11 +539,22 @@ UIView* UIWidget::GetView()
     return 0;
 }
 
+void UIWidget::OnFocusChanged(bool focused)
+{
+    using namespace WidgetFocusChanged;
+
+    VariantMap eventData;
+    eventData[P_WIDGET] = this;
+    eventData[P_FOCUSED] = focused;
+    SendEvent(E_WIDGETFOCUSCHANGED, eventData);
+
+}
+
 bool UIWidget::OnEvent(const tb::TBWidgetEvent &ev)
 {
     UI* ui = GetSubsystem<UI>();
 
-    if (ev.type == EVENT_TYPE_CHANGED)
+    if (ev.type == EVENT_TYPE_CHANGED || ev.type == EVENT_TYPE_KEY_UP)
     {
         if (!ev.target || ui->IsWidgetWrapped(ev.target))
         {

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

@@ -150,6 +150,7 @@ class UIWidget : public Object, public tb::TBWidgetDelegate
     double GetValue();
 
     void SetFocus();
+    void OnFocusChanged(bool focused);
 
     void SetState(/*WIDGET_STATE*/ unsigned state, bool on);
     bool GetState(/*WIDGET_STATE*/ unsigned state);

+ 1 - 0
Source/AtomicJS/Javascript/JSUI.cpp

@@ -57,6 +57,7 @@ JSUI::JSUI(Context* context) : Object(context),
     uiTypes_["UIInlineSelect"] = true;
     uiTypes_["UITextureWidget"] = true;
     uiTypes_["UIScrollContainer"] = true;
+    uiTypes_["UISeparator"] = true;
 
 }
 

+ 1 - 1
Source/AtomicJS/Packages/Atomic/UI.json

@@ -9,7 +9,7 @@
 								"UISelectList", "UIListView", "UIMessageWindow", "UILayoutParams", "UIFontDescription",
 								"UISkinImage", "UITabContainer", "UISceneView", "UIPreferredSize", "UIDragObject",
 								"UIContainer", "UISection", "UIInlineSelect", "UITextureWidget",
-								"UIScrollContainer"],
+								"UIScrollContainer", "UISeparator"],
 	"overloads" : {
 	}
 }

+ 13 - 3
Source/ThirdParty/TurboBadger/tb_editfield.cpp

@@ -202,19 +202,25 @@ bool TBEditField::OnEvent(const TBWidgetEvent &ev)
 	if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_scrollbar_x)
 	{
 		m_style_edit.SetScrollPos(m_scrollbar_x.GetValue(), m_style_edit.scroll_y);
-		OnScroll(m_scrollbar_x.GetValue(), m_style_edit.scroll_y);
+        OnScroll(m_scrollbar_x.GetValue(), m_style_edit.scroll_y);
+        TBWidget::OnEvent(ev);
 		return true;
 	}
 	else if (ev.type == EVENT_TYPE_CHANGED && ev.target == &m_scrollbar_y)
 	{
 		m_style_edit.SetScrollPos(m_style_edit.scroll_x, m_scrollbar_y.GetValue());
-		OnScroll(m_style_edit.scroll_x, m_scrollbar_y.GetValue());
+        OnScroll(m_style_edit.scroll_x, m_scrollbar_y.GetValue());
+        TBWidget::OnEvent(ev);
 		return true;
 	}
+    else if (ev.type == EVENT_TYPE_CHANGED)
+    {
+        TBWidget::OnEvent(ev);
+    }
 	else if (ev.type == EVENT_TYPE_WHEEL && ev.modifierkeys == TB_MODIFIER_NONE)
 	{
 		int old_val = m_scrollbar_y.GetValue();
-		m_scrollbar_y.SetValue(old_val + ev.delta_y * TBSystem::GetPixelsPerLine());
+        m_scrollbar_y.SetValue(old_val + ev.delta_y * TBSystem::GetPixelsPerLine());
 		return m_scrollbar_y.GetValue() != old_val;
 	}
 	else if (ev.type == EVENT_TYPE_POINTER_DOWN && ev.target == this)
@@ -242,10 +248,12 @@ bool TBEditField::OnEvent(const TBWidgetEvent &ev)
 	}
 	else if (ev.type == EVENT_TYPE_KEY_DOWN)
 	{
+        TBWidget::OnEvent(ev);
 		return m_style_edit.KeyDown(ev.key, ev.special_key, ev.modifierkeys);
 	}
 	else if (ev.type == EVENT_TYPE_KEY_UP)
 	{
+        TBWidget::OnEvent(ev);
 		return true;
 	}
 	else if ((ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == TBIDC("popupmenu")) ||
@@ -348,6 +356,8 @@ void TBEditField::OnFontChanged()
 void TBEditField::OnFocusChanged(bool focused)
 {
 	m_style_edit.Focus(focused);
+
+    TBWidget::OnFocusChanged(focused);
 }
 
 void TBEditField::OnResized(int old_w, int old_h)

+ 2 - 2
Source/ThirdParty/TurboBadger/tb_widgets.h

@@ -348,7 +348,7 @@ class TBWidgetDelegate
 {
 public:
     virtual bool OnEvent(const TBWidgetEvent &ev) = 0;
-
+    virtual void OnFocusChanged(bool focused) = 0;
     virtual void OnDelete() = 0;
 };
 
@@ -676,7 +676,7 @@ public:
 	virtual void OnFontChanged() {}
 
 	/** Called when the focus has changed. */
-	virtual void OnFocusChanged(bool focused) {}
+    virtual void OnFocusChanged(bool focused) { if (m_delegate) return m_delegate->OnFocusChanged(focused); }
 
 	/** Called when the visibility has changed.
 		Note: This is not called when combined visibility change, so it may change visibility