Browse Source

Work on New UI

Josh Engebretson 10 years ago
parent
commit
80b8802b53

+ 26 - 2
Source/Atomic/UI/UI.cpp

@@ -26,6 +26,8 @@ using namespace tb;
 
 
 #include "UIRenderer.h"
 #include "UIRenderer.h"
 #include "UI.h"
 #include "UI.h"
+#include "UIButton.h"
+#include "UITextField.h"
 
 
 namespace tb
 namespace tb
 {
 {
@@ -349,12 +351,34 @@ void UI::HandleScreenMode(StringHash eventType, VariantMap& eventData)
     //SetSize(eventData[P_WIDTH].GetInt(), eventData[P_HEIGHT].GetInt());
     //SetSize(eventData[P_WIDTH].GetInt(), eventData[P_HEIGHT].GetInt());
 }
 }
 
 
-
-
 void UI::HandleUpdate(StringHash eventType, VariantMap& eventData)
 void UI::HandleUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
     TBMessageHandler::ProcessMessages();
     TBMessageHandler::ProcessMessages();
 }
 }
 
 
+UIWidget* UI::WrapWidget(tb::TBWidget* widget)
+{
+    if (widgetWrap_.Contains(widget))
+        return widgetWrap_[widget];
+
+    if (widget->IsOfType<TBButton>())
+    {
+        UIButton* button = new UIButton(context_, false);
+        button->SetWidget(widget);
+        widgetWrap_[widget] = button;
+        return button;
+    }
+
+    if (widget->IsOfType<TBTextField>())
+    {
+        UITextField* textfield = new UITextField(context_, false);
+        textfield->SetWidget(widget);
+        widgetWrap_[widget] = textfield;
+        return textfield;
+    }
+
+    return 0;
+}
+
 
 
 }
 }

+ 5 - 0
Source/Atomic/UI/UI.h

@@ -14,6 +14,7 @@ namespace Atomic
 
 
 class VertexBuffer;
 class VertexBuffer;
 class UIRenderer;
 class UIRenderer;
+class UIWidget;
 
 
 class UI : public Object
 class UI : public Object
 {
 {
@@ -44,6 +45,8 @@ public:
     void AddFont(const String& fontFile, const String &name);
     void AddFont(const String& fontFile, const String &name);
     void SetDefaultFont(const String& name, int size);
     void SetDefaultFont(const String& name, int size);
 
 
+    UIWidget* WrapWidget(tb::TBWidget* widget);
+
 private:
 private:
 
 
     static WeakPtr<Context> readerContext_;
     static WeakPtr<Context> readerContext_;
@@ -64,6 +67,8 @@ private:
 
 
     WeakPtr<Graphics> graphics_;
     WeakPtr<Graphics> graphics_;
 
 
+    HashMap<tb::TBWidget*, UIWidget*> widgetWrap_;
+
     bool inputDisabled_;
     bool inputDisabled_;
     bool keyboardDisabled_;
     bool keyboardDisabled_;
     bool initialized_;
     bool initialized_;

+ 40 - 0
Source/Atomic/UI/UIButton.cpp

@@ -0,0 +1,40 @@
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_widgets_common.h>
+
+#include "UIEvents.h"
+#include "UIButton.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIButton::UIButton(Context* context, bool createWidget) : UIWidget(context, false)
+{
+    if (createWidget)
+    {
+        widget_ = new TBButton();
+        widget_->SetDelegate(this);
+    }
+}
+
+UIButton::~UIButton()
+{
+
+}
+
+bool UIButton::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    if (ev.type == EVENT_TYPE_CLICK && ev.target == widget_)
+    {
+        VariantMap eventData;
+        ConvertEvent(this, ev, eventData);
+        SendEvent(E_WIDGETEVENT, eventData);
+        return true;
+    }
+
+    return false;
+}
+
+}

+ 27 - 0
Source/Atomic/UI/UIButton.h

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

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

@@ -27,6 +27,22 @@
 namespace Atomic
 namespace Atomic
 {
 {
 
 
+EVENT(E_WIDGETEVENT, WidgetEvent)
+{
+    PARAM(P_TARGET, Target);             // UIWidget pointer
+    PARAM(P_TYPE, Type);                 // EVENT_TYPE enum
+    PARAM(P_X, X);                       // int
+    PARAM(P_Y, Y);                       // int
+    PARAM(P_DELTAX, DeltaX);             // int
+    PARAM(P_DELTAY, DeltaY);             // int
+    PARAM(P_COUNT, Count);               // int
+    PARAM(P_KEY, Key);                   // int
+    PARAM(P_SPECIALKEY, SpecialKey);     // enum SPECIAL_KEY
+    PARAM(P_MODIFIERKEYS, ModifierKeys); // enum MODIFIER_KEYS
+    PARAM(P_ID, ID);                     // unsigned (TBID)
+    PARAM(P_TOUCH, Touch);               // bool
+}
+
 /// Mouse click in the UI.
 /// Mouse click in the UI.
 EVENT(E_UIMOUSECLICK, UIMouseClick)
 EVENT(E_UIMOUSECLICK, UIMouseClick)
 {
 {

+ 32 - 0
Source/Atomic/UI/UITextField.cpp

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

+ 26 - 0
Source/Atomic/UI/UITextField.h

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

+ 32 - 0
Source/Atomic/UI/UIView.cpp

@@ -0,0 +1,32 @@
+
+#include <TurboBadger/tb_widgets.h>
+
+#include "UI.h"
+#include "UIView.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIView::UIView(Context* context) : UIWidget(context, false)
+{
+    widget_ = new TBWidget();
+    widget_->SetDelegate(this);
+
+    UI* ui = GetSubsystem<UI>();
+
+    TBRect rect = ui->GetRootWidget()->GetRect();
+    widget_->SetSize(rect.w, rect.h);
+
+    ui->GetRootWidget()->AddChild(widget_);
+
+}
+
+UIView::~UIView()
+{
+
+}
+
+
+}

+ 25 - 0
Source/Atomic/UI/UIView.h

@@ -0,0 +1,25 @@
+
+#pragma once
+
+#include "UIWidget.h"
+
+namespace Atomic
+{
+
+/// a view off the root widget
+class UIView : public UIWidget
+{
+    OBJECT(UIView)
+
+public:
+
+    UIView(Context* context);
+    virtual ~UIView();
+
+protected:
+
+private:
+
+};
+
+}

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

@@ -0,0 +1,109 @@
+
+//--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 "UIEvents.h"
+#include "UI.h"
+#include "UIWidget.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIWidget::UIWidget(Context* context, bool createWidget) : Object(context),
+    widget_(0)
+{    
+    AddRef();
+
+    if (createWidget)
+    {
+        widget_ = new TBWidget();
+        widget_->SetDelegate(this);
+    }
+}
+
+UIWidget::~UIWidget()
+{
+
+}
+
+bool UIWidget::Load(const String& filename)
+{
+    UI* ui = GetSubsystem<UI>();
+
+    if  (!ui->LoadResourceFile(widget_ , filename))
+        return false;
+
+    return true;
+}
+
+UIWidget* UIWidget::GetWidgetByID(const String& id)
+{
+    if (!widget_)
+        return 0;
+
+    TBWidget* child = widget_->GetWidgetByID(TBID(id.CString()));
+
+    if (!child)
+        return 0;
+
+    UI* ui = GetSubsystem<UI>();
+    return ui->WrapWidget(child);
+}
+
+void UIWidget::SetWidget(tb::TBWidget* widget)
+{
+    widget_ = widget;
+    widget_->SetDelegate(this);
+}
+
+void UIWidget::ConvertEvent(UIWidget* target, const tb::TBWidgetEvent &ev, VariantMap& data)
+{
+    using namespace WidgetEvent;
+    data[P_TARGET] = target;
+    data[P_TYPE] = (unsigned) ev.type;
+    data[P_X] = ev.target_x;
+    data[P_Y] = ev.target_y;
+    data[P_DELTAX] = ev.delta_x;
+    data[P_DELTAY] = ev.delta_y;
+    data[P_COUNT] = ev.count;
+    data[P_KEY] = ev.key;
+    data[P_SPECIALKEY] = (unsigned) ev.special_key;
+    data[P_MODIFIERKEYS] = (unsigned) ev.modifierkeys;
+    data[P_ID] = (unsigned) ev.ref_id;
+    data[P_TOUCH] = (unsigned) ev.touch;
+}
+
+void UIWidget::OnDelete()
+{
+    widget_ = 0;
+    ReleaseRef();
+}
+
+void UIWidget::AddChild(UIWidget* child)
+{
+    if (!widget_ || !child->widget_)
+        return;
+
+    widget_->AddChild(child->widget_);
+}
+
+bool UIWidget::SetText(const String& text)
+{
+    if (!widget_)
+        return false;
+
+    return widget_->SetText(text.CString());
+}
+
+void UIWidget::SetSize(int width, int height)
+{
+    if (!widget_)
+        return;
+
+    widget_->SetSize(width, height);
+}
+
+}

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

@@ -0,0 +1,50 @@
+
+#pragma once
+
+#include <TurboBadger/tb_widgets.h>
+#include "../Core/Object.h"
+
+namespace tb
+{
+class TBWidget;
+}
+
+
+namespace Atomic
+{
+
+/// Wraps a TurboBadger widget
+class UIWidget : public Object, public tb::TBWidgetDelegate
+{
+    friend class UI;
+
+    OBJECT(UIWidget)
+
+public:
+
+    UIWidget(Context* context, bool createWidget = true);
+    virtual ~UIWidget();
+
+    bool Load(const String& filename);
+
+    void SetSize(int width, int height);
+    bool SetText(const String& text);
+
+    UIWidget* GetWidgetByID(const String& id);
+
+    void AddChild(UIWidget* child);
+
+protected:
+
+    void ConvertEvent(UIWidget* target, const tb::TBWidgetEvent &ev, VariantMap& data);
+
+    void SetWidget(tb::TBWidget* widget);
+
+    virtual bool OnEvent(const tb::TBWidgetEvent &ev) { return false; }
+    virtual void OnDelete();
+
+    tb::TBWidget* widget_;
+
+};
+
+}

+ 44 - 0
Source/Atomic/UI/UIWindow.cpp

@@ -0,0 +1,44 @@
+
+#include <TurboBadger/tb_widgets.h>
+#include <TurboBadger/tb_widgets_common.h>
+#include <TurboBadger/tb_window.h>
+
+#include "../IO/Log.h"
+
+#include "UIEvents.h"
+#include "UIWindow.h"
+
+using namespace tb;
+
+namespace Atomic
+{
+
+UIWindow::UIWindow(Context* context, bool createWidget) : UIWidget(context, false)
+{
+    if (createWidget)
+    {
+        widget_ = new TBWindow();
+        widget_->SetDelegate(this);
+    }
+}
+
+void UIWindow::ResizeToFitContent()
+{
+    if (!widget_)
+        return;
+
+    ((TBWindow*)widget_)->ResizeToFitContent();
+
+}
+
+UIWindow::~UIWindow()
+{
+
+}
+
+bool UIWindow::OnEvent(const tb::TBWidgetEvent &ev)
+{
+    return false;
+}
+
+}

+ 29 - 0
Source/Atomic/UI/UIWindow.h

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

+ 1 - 1
Source/AtomicJS/JSBind/modules/UI.json

@@ -2,7 +2,7 @@
 	"name" : "UI",
 	"name" : "UI",
 	"sources" : ["UI"],
 	"sources" : ["UI"],
 	"includes" : ["<Atomic/Graphics/Material.h>", "<Atomic/Scene/Node.h>", "<Atomic/Scene/Scene.h>", "<Atomic/Graphics/Texture2D.h>"],
 	"includes" : ["<Atomic/Graphics/Material.h>", "<Atomic/Scene/Node.h>", "<Atomic/Scene/Scene.h>", "<Atomic/Graphics/Texture2D.h>"],
-	"classes" : [],
+	"classes" : ["UIWidget", "UIView", "UIWindow", "UIButton", "UITextField"],
 	"overloads" : {
 	"overloads" : {
 	}
 	}
 }
 }

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

@@ -0,0 +1,65 @@
+#include <TurboBadger/tb_widgets.h>
+
+#include <Atomic/UI/UIEvents.h>
+#include <Atomic/UI/UIWidget.h>
+#include "JSVM.h"
+#include "JSUI.h"
+
+namespace Atomic
+{
+
+JSUI::JSUI(Context* context) : Object(context)
+{
+    ctx_ = JSVM::GetJSVM(nullptr)->GetJSContext();
+    SubscribeToEvent(E_WIDGETEVENT, HANDLER(JSUI, HandleWidgetEvent));
+}
+
+JSUI::~JSUI()
+{
+
+}
+
+void JSUI::HandleWidgetEvent(StringHash eventType, VariantMap& eventData)
+{
+    using namespace WidgetEvent;
+
+    UIWidget* widget = static_cast<UIWidget*>(eventData[P_TARGET].GetPtr());
+    if (!widget)
+        return;
+
+    void* heapptr = widget->JSGetHeapPtr();
+
+    if (!heapptr)
+        return;
+
+    tb::EVENT_TYPE type = (tb::EVENT_TYPE) eventData[P_TYPE].GetUInt();
+
+    if (type == tb::EVENT_TYPE_CLICK)
+    {
+        int top = duk_get_top(ctx_);
+        duk_push_heapptr(ctx_, heapptr);
+        duk_get_prop_string(ctx_, -1, "onClick");
+        if (duk_is_callable(ctx_, -1)) {
+            duk_call(ctx_, 0);
+        }
+        duk_pop_n(ctx_, 2);
+        assert(top == duk_get_top(ctx_));
+        return;
+    }
+
+    eventData[P_TYPE];
+    eventData[P_X];
+    eventData[P_Y];
+    eventData[P_DELTAX];
+    eventData[P_DELTAY];
+    eventData[P_COUNT];
+    eventData[P_KEY];
+    eventData[P_SPECIALKEY];
+    eventData[P_MODIFIERKEYS];
+    eventData[P_ID];
+    eventData[P_TOUCH];
+
+
+}
+
+}

+ 28 - 0
Source/AtomicJS/Javascript/JSUI.h

@@ -0,0 +1,28 @@
+
+#pragma once
+
+#include <Duktape/duktape.h>
+#include <Atomic/Core/Object.h>
+
+namespace Atomic
+{
+
+class JSUI : public Object
+{
+    OBJECT(JSUI)
+
+public:
+
+    JSUI(Context* context);
+    virtual ~JSUI();
+
+private:
+
+    duk_context* ctx_;
+
+    void HandleWidgetEvent(StringHash eventType, VariantMap& eventData);
+
+
+};
+
+}

+ 3 - 0
Source/AtomicJS/Javascript/JSVM.cpp

@@ -17,6 +17,7 @@
 #include "JSEvents.h"
 #include "JSEvents.h"
 #include "JSVM.h"
 #include "JSVM.h"
 #include "JSAtomic.h"
 #include "JSAtomic.h"
+#include "JSUI.h"
 
 
 namespace Atomic
 namespace Atomic
 {
 {
@@ -63,6 +64,8 @@ void JSVM::InitJSContext()
 
 
     InitComponents();
     InitComponents();
 
 
+    ui_ = new JSUI(context_);
+
     // handle this elsewhere?
     // handle this elsewhere?
     SubscribeToEvents();
     SubscribeToEvents();
 
 

+ 4 - 3
Source/AtomicJS/Javascript/JSVM.h

@@ -18,6 +18,7 @@ namespace Atomic
 {
 {
 
 
 class JSFile;
 class JSFile;
+class JSUI;
 
 
 class ATOMIC_API JSVM : public Object
 class ATOMIC_API JSVM : public Object
 {
 {
@@ -35,8 +36,8 @@ public:
 
 
     // Resources/Scripts/*.js
     // Resources/Scripts/*.js
     bool ExecuteScript(const String& scriptPath);
     bool ExecuteScript(const String& scriptPath);
-    // Resources/Script/main.js
 
 
+    // Resources/Script/main.js
     // Catches not requiring AtomicGame, etc
     // Catches not requiring AtomicGame, etc
     bool ExecuteMain();
     bool ExecuteMain();
 
 
@@ -148,8 +149,6 @@ private:
 
 
 #endif
 #endif
 
 
-    List<Object*> jsObjects_;
-
     float gcTime_;
     float gcTime_;
 
 
     String moduleSearchPath_;
     String moduleSearchPath_;
@@ -157,6 +156,8 @@ private:
 
 
     String errorString_;
     String errorString_;
 
 
+    SharedPtr<JSUI> ui_;
+
     static JSVM* instance_;
     static JSVM* instance_;
 
 
 };
 };

+ 5 - 1
Source/ThirdParty/TurboBadger/tb_widgets.cpp

@@ -70,7 +70,8 @@ TBWidget::TBWidget()
 	, m_gravity(WIDGET_GRAVITY_DEFAULT)
 	, m_gravity(WIDGET_GRAVITY_DEFAULT)
 	, m_layout_params(nullptr)
 	, m_layout_params(nullptr)
 	, m_scroller(nullptr)
 	, m_scroller(nullptr)
-	, m_long_click_timer(nullptr)
+    , m_long_click_timer(nullptr)
+    , m_delegate(nullptr)
 	, m_packed_init(0)
 	, m_packed_init(0)
 {
 {
 #ifdef TB_RUNTIME_DEBUG_INFO
 #ifdef TB_RUNTIME_DEBUG_INFO
@@ -91,6 +92,9 @@ TBWidget::~TBWidget()
 	if (this == focused_widget)
 	if (this == focused_widget)
 		focused_widget = nullptr;
 		focused_widget = nullptr;
 
 
+    if (m_delegate)
+        m_delegate->OnDelete();
+
 	TBWidgetListener::InvokeWidgetDelete(this);
 	TBWidgetListener::InvokeWidgetDelete(this);
 	DeleteAllChildren();
 	DeleteAllChildren();
 
 

+ 13 - 1
Source/ThirdParty/TurboBadger/tb_widgets.h

@@ -343,6 +343,14 @@ enum WIDGET_HIT_STATUS {
 	WIDGET_HIT_STATUS_HIT_NO_CHILDREN		///< The widget was hit, no children should be hit.
 	WIDGET_HIT_STATUS_HIT_NO_CHILDREN		///< The widget was hit, no children should be hit.
 };
 };
 
 
+class TBWidgetDelegate
+{
+public:
+    virtual bool OnEvent(const TBWidgetEvent &ev) = 0;
+
+    virtual void OnDelete() = 0;
+};
+
 /** The base TBWidget class.
 /** The base TBWidget class.
 	Make a subclass to implement UI controls.
 	Make a subclass to implement UI controls.
 	Each widget has a background skin (no skin specified by default) which will be used to
 	Each widget has a background skin (no skin specified by default) which will be used to
@@ -600,6 +608,9 @@ public:
 		events are going through this widget (See GetEventDestination()) */
 		events are going through this widget (See GetEventDestination()) */
 	bool IsEventDestinationFor(TBWidget *other_widget) const;
 	bool IsEventDestinationFor(TBWidget *other_widget) const;
 
 
+    TBWidgetDelegate* GetDelegate() {return m_delegate; }
+    void SetDelegate(TBWidgetDelegate* delegate) { m_delegate = delegate; }
+
 	// == Callbacks ==============================================
 	// == Callbacks ==============================================
 
 
 	/** Add a listener to this widget. It should be removed again with
 	/** Add a listener to this widget. It should be removed again with
@@ -611,7 +622,7 @@ public:
 	/** Callback for handling events.
 	/** Callback for handling events.
 		Return true if the event is handled and should not
 		Return true if the event is handled and should not
 		continue to be handled by any parent widgets. */
 		continue to be handled by any parent widgets. */
-	virtual bool OnEvent(const TBWidgetEvent &ev) { return false; }
+    virtual bool OnEvent(const TBWidgetEvent &ev) { if (m_delegate) return m_delegate->OnEvent(ev); return false; }
 
 
 	/** Callback for doing anything that might be needed before paint.
 	/** Callback for doing anything that might be needed before paint.
 		F.ex Updating invalid layout, formatting text etc. */
 		F.ex Updating invalid layout, formatting text etc. */
@@ -994,6 +1005,7 @@ private:
 	LayoutParams *m_layout_params;	///< Layout params, or nullptr.
 	LayoutParams *m_layout_params;	///< Layout params, or nullptr.
 	TBScroller *m_scroller;
 	TBScroller *m_scroller;
 	TBLongClickTimer *m_long_click_timer;
 	TBLongClickTimer *m_long_click_timer;
+    TBWidgetDelegate* m_delegate;
 	union {
 	union {
 		struct {
 		struct {
 			uint16 is_group_root : 1;
 			uint16 is_group_root : 1;