Browse Source

Working on scene editing

Josh Engebretson 10 years ago
parent
commit
bc6a24c458

+ 17 - 0
Data/AtomicEditor/Resources/EditorData/AtomicEditor/editor/ui/hierarchyframe.tb.txt

@@ -0,0 +1,17 @@
+definitions
+	menubutton		
+		lp: height: 20
+		font: name: Vera, size: 11
+TBLayout: distribution: gravity, axis: y, id: hierarchyframe
+	lp: min-width: 220
+	TBLayout: distribution: gravity
+		TBButton
+			@include definitions>menubutton
+			text Create
+			id menu create
+		TBEditField
+			id filter
+			gravity left right
+			placeholder @search
+			type search	
+	TBLayout: distribution: gravity, id: hierarchycontainer, gravity: all

+ 4 - 0
Data/AtomicEditor/Resources/EditorData/AtomicEditor/editor/ui/inspectorframe.tb.txt

@@ -0,0 +1,4 @@
+TBContainer: skin: AEContainer, gravity: all, id: mainframecontainer
+	lp: min-width: 320
+	TBScrollContainer: scroll-mode: auto, id: inspectorcontainerscroll, gravity: all
+		TBLayout: distribution: gravity, id: inspectorcontainer, gravity: all

+ 14 - 1
Data/AtomicEditor/Resources/EditorData/AtomicEditor/editor/ui/mainframe.tb.txt

@@ -40,7 +40,15 @@ TBLayout: distribution: gravity, axis: y
 						TBLayout: gravity: left right
 							TBWidget
 			TBLayout: distribution: gravity, position: top
-				TBLayout: distribution: gravity, id: projectviewcontainer, gravity: top bottom
+				TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom
+					TBEditField: text: "<color #AAAAAA>Project</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+						font: size: 11
+					TBLayout: distribution: gravity, id: projectviewcontainer
+					TBSeparator: gravity: left right, skin: AESeparator
+					TBEditField: text: "<color #AAAAAA>Hierarchy</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+						font: size: 11
+					TBLayout: distribution: gravity, id: hierarchycontainer
+						TBWidget: gravity: top bottom
 				TBLayout: distribution: gravity, axis: y
 					TBLayout: gravity: left right, id: maintoolbarcontainer
 					TBSeparator: gravity: left right, skin: AESeparator
@@ -48,6 +56,11 @@ TBLayout: distribution: gravity, axis: y
 					TBContainer: skin: AEContainer, gravity: left right bottom, id: consolecontainer
 						TBEditField: multiline: 1, styling: 1, gravity: left right, id: consoletext
 							text: "Hello World!"
+				TBLayout: distribution: gravity, axis: y, position: left, gravity: top bottom
+					TBEditField: text: "<color #AAAAAA>Inspector</color>", styling: 1, readonly: 1, adapt-to-content: 1, skin: 0
+						font: size: 11
+					TBLayout: distribution: gravity, id: inspectorcontainer
+
 			TBLayout: distribution: gravity
 				TBContainer: skin: AEContainer, gravity: left right
 					TBLayout: distribution: gravity

+ 2 - 2
Data/AtomicEditor/Resources/EditorData/AtomicEditor/editor/ui/projectframe.tb.txt

@@ -3,7 +3,7 @@ definitions
 		lp: height: 20
 		font: name: Vera, size: 11
 TBLayout: distribution: gravity, axis: y, id: projectframe
-	lp: min-width: 300
+	lp: min-width: 220
 	TBLayout: distribution: gravity
 		TBButton
 			@include definitions>menubutton
@@ -16,7 +16,7 @@ TBLayout: distribution: gravity, axis: y, id: projectframe
 			type search	
 	TBWidget: gravity: all
 		TBLayout: distribution: gravity, id: foldercontainer, gravity: all
-	TBScrollContainer: scroll-mode: y-auto, id: contentcontainerscroll, gravity: all
+	TBScrollContainer: scroll-mode: auto, id: contentcontainerscroll, gravity: all
 		TBLayout: id: contentcontainer, axis: y, position: left
 	
 

BIN
Data/AtomicEditor/Resources/EditorData/AtomicEditor/resources/default_skin/scroll_fg_x.png


BIN
Data/AtomicEditor/Resources/EditorData/AtomicEditor/resources/default_skin/scroll_fg_y.png


+ 11 - 0
Source/AtomicEditor/Source/AEEvents.h

@@ -84,6 +84,17 @@ EVENT(E_EDITORMODAL, EditorModal)
     PARAM(P_MESSAGE, Message);    // for modal errors, error text
 }
 
+EVENT(E_EDITORACTIVESCENECHANGE, EditorActiveSceneChange)
+{
+    PARAM(P_SCENE, Scene);      // Scene*
+}
+
+EVENT(E_EDITORACTIVENODECHANGE, EditorActiveNodeChange)
+{
+    PARAM(P_NODE, Node);      // Node*
+}
+
+
 EVENT(E_PLAYERERROR, PlayerError)
 {
     PARAM(P_TEXT, Text);      // string

+ 15 - 28
Source/AtomicEditor/Source/Editors/SceneResourceEditor.cpp

@@ -12,7 +12,8 @@
 
 #include <Atomic/Physics/PhysicsWorld.h>
 
-#include "../AEEditor.h"
+#include "AEEditor.h"
+#include "AEEvents.h"
 
 #include <Atomic/Input/Input.h>
 #include "SceneResourceEditor.h"
@@ -43,36 +44,17 @@ SceneResourceEditor ::SceneResourceEditor(Context* context, const String &fullpa
     scene_ = new Scene(context_);
     SharedPtr<File> xmlFile = cache->GetFile(fullpath);
 
-    if (GetExtension(fullpath) == ".xml")
+    if (GetExtension(fullpath) == ".scene")
         scene_->LoadXML(*xmlFile);
     else
         scene_->Load(*xmlFile);
 
-    // TODO: Fix this properly, currently simulates immediately
-    PhysicsWorld* physics = scene_->GetComponent<PhysicsWorld>();
-    if (physics)
-        scene_->RemoveComponent(physics);
+    scene_->SetUpdateEnabled(false);
 
     cameraNode_ = scene_->CreateChild("Camera");
     camera_ = cameraNode_->CreateComponent<Camera>();
 
-    if (fullpath_.Contains("CompartmentScene"))
-    {
-        pitch_ = 19.4f;
-        yaw_ = -228.6f;
-        cameraNode_->SetPosition(Vector3(-42.66f, 6.68f, 9.34f));
-    }
-    else
-    {
-        pitch_ = 26.8f;
-        yaw_ = 121.4f;
-        cameraNode_->SetPosition(Vector3(-135.81f, 76.56f, 16.42f));
-    }
-
-
-    // in a view3D_ procsky renders wrong (inversed?)
-    //Node* skyNode = scene_->CreateChild("ProcSky", LOCAL );
-    //skyNode->CreateComponent<ProcSky>();
+    cameraNode_->SetPosition(Vector3(0, 0, -10));
 
     layout_->AddChild(view3DContainer_);
 
@@ -82,15 +64,20 @@ SceneResourceEditor ::SceneResourceEditor(Context* context, const String &fullpa
     view3D_->SetView(scene_, camera_);
     view3D_->SetAutoUpdate(false);
 
-    GetSubsystem<TBUI>()->AddChild(view3D_);
+    GetSubsystem<UI>()->GetRoot()->AddChild(view3D_);
 
     SubscribeToEvent(E_UPDATE, HANDLER(SceneResourceEditor, HandleUpdate));
 
+    // TODO: generate this event properly
+    VariantMap eventData;
+    eventData[EditorActiveSceneChange::P_SCENE] = scene_;
+    SendEvent(E_EDITORACTIVESCENECHANGE, eventData);
+
 }
 
 SceneResourceEditor::~SceneResourceEditor()
 {
-
+    GetSubsystem<UI>()->GetRoot()->RemoveChild(view3D_);
 }
 
 bool SceneResourceEditor::OnEvent(const TBWidgetEvent &ev)
@@ -136,7 +123,7 @@ void SceneResourceEditor::MoveCamera(float timeStep)
 }
 
 void SceneResourceEditor::HandleUpdate(StringHash eventType, VariantMap& eventData)
-{    
+{
 
     if ((layout_->GetVisibility() != WIDGET_VISIBILITY_VISIBLE) || GetSubsystem<Editor>()->IsPlayingProject())
     {
@@ -183,9 +170,9 @@ void SceneResourceEditor::HandleUpdate(StringHash eventType, VariantMap& eventDa
 
     if (dirty)
     {
+
         view3D_->SetPosition(rect.x, rect.y);
-        view3D_->SetWidth(rect.w);
-        view3D_->SetHeight(rect.h);
+        view3D_->SetSize(rect.w, rect.h);
     }
 
     view3D_->QueueUpdate();

+ 133 - 0
Source/AtomicEditor/Source/UI/UIHierarchyFrame.cpp

@@ -0,0 +1,133 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include "AtomicEditor.h"
+
+#include <TurboBadger/tb_select.h>
+
+#include <Atomic/Core/Context.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/Resource/ResourceEvents.h>
+
+#include <Atomic/UI/TBUI.h>
+
+#include "AEEditor.h"
+#include "AEEvents.h"
+
+#include "UIListView.h"
+#include "UIHierarchyFrame.h"
+
+#include "UI/Modal/UIModalOps.h"
+
+using namespace tb;
+
+namespace AtomicEditor
+{
+
+HierarchyFrame::HierarchyFrame(Context* context) :
+    AEWidget(context)
+{
+    TBUI* tbui = GetSubsystem<TBUI>();
+    tbui->LoadResourceFile(delegate_, "AtomicEditor/editor/ui/hierarchyframe.tb.txt");
+
+    delegate_->SetID(TBIDC("projectframe_delegate"));
+
+    delegate_->SetGravity(WIDGET_GRAVITY_TOP_BOTTOM);
+
+    // folders
+    TBLayout* hierarchycontainer = delegate_->GetWidgetByIDAndType<TBLayout>(TBIDC("hierarchycontainer"));
+    assert(hierarchycontainer);
+
+    hierarchyList_ = new ListView(context_, "hierarchyList_");
+    hierarchyList_->GetRootList()->SetGravity(WIDGET_GRAVITY_ALL);
+
+    TBWidgetDelegate* hierarchyListWD = hierarchyList_->GetWidgetDelegate();
+
+    hierarchyListWD->SetID(TBIDC("hierarchyList_delegate"));
+
+    hierarchyListWD->SetGravity(WIDGET_GRAVITY_ALL);
+
+    hierarchycontainer->AddChild(hierarchyListWD);
+
+    SubscribeToEvent(E_EDITORACTIVESCENECHANGE, HANDLER(HierarchyFrame, HandleEditorActiveSceneChange));
+
+}
+
+HierarchyFrame::~HierarchyFrame()
+{
+
+}
+
+void HierarchyFrame::RecursiveAddNode(ListViewItem* parent, Node* node)
+{
+
+    String name = node->GetName();
+    if (!name.Length())
+        name = "(Anonymous)";
+
+    ListViewItem* child = parent->AddChild(name.CString(), "Folder.icon", TBID(uint32(node->GetID())));
+
+    for (unsigned i = 0; i < node->GetNumChildren(); i++)
+        RecursiveAddNode(child, node->GetChild(i));
+}
+
+
+void HierarchyFrame::RefreshHierarchyList()
+{
+    hierarchyList_->DeleteAllItems();
+
+    if (scene_.Null())
+        return;
+
+    ListViewItem* parent = hierarchyList_->AddItem("Scene", "Folder.icon", TBID(uint32(scene_->GetID())));
+
+    for (unsigned i = 0; i < scene_->GetNumChildren(); i++)
+        RecursiveAddNode(parent, scene_->GetChild(i));
+
+    hierarchyList_->GetRootList()->SetValue(0);
+    hierarchyList_->GetItem(0)->SetExpanded(true);
+
+}
+
+bool HierarchyFrame::OnEvent(const TBWidgetEvent &ev)
+{
+    if (ev.type == EVENT_TYPE_CLICK)
+    {
+        if (scene_.NotNull())
+        {
+            if (ev.target->GetID() == TBIDC("hierarchyList_"))
+            {
+                unsigned id = ev.ref_id;
+                Node* node = scene_->GetNode(id);
+                if (node)
+                {
+                    VariantMap neventData;
+                    neventData[EditorActiveNodeChange::P_NODE] = node;
+                    SendEvent(E_EDITORACTIVENODECHANGE, neventData);
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+void HierarchyFrame::HandleEditorActiveSceneChange(StringHash eventType, VariantMap& eventData)
+{
+    Scene* scene = (Scene*) (eventData[EditorActiveSceneChange::P_SCENE].GetPtr());
+
+    scene_ = scene;
+    if (scene_)
+    {
+        RefreshHierarchyList();
+    }
+
+    VariantMap neventData;
+    neventData[EditorActiveNodeChange::P_NODE] = scene_;
+    SendEvent(E_EDITORACTIVENODECHANGE, neventData);
+
+}
+
+}

+ 51 - 0
Source/AtomicEditor/Source/UI/UIHierarchyFrame.h

@@ -0,0 +1,51 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include "AEWidget.h"
+#include "UIMenubar.h"
+
+#include <Atomic/Scene/Scene.h>
+
+using namespace Atomic;
+
+namespace tb
+{
+    class TBLayout;
+    class TBMenuWindow;
+}
+
+namespace AtomicEditor
+{
+
+class ListView;
+class ListViewItem;
+
+class HierarchyFrame : public AEWidget
+{
+
+    OBJECT(HierarchyFrame);
+
+public:
+    /// Construct.
+    HierarchyFrame(Context* context);
+    /// Destruct.
+    virtual ~HierarchyFrame();
+
+    void RefreshHierarchyList();
+
+    bool OnEvent(const TBWidgetEvent &ev);
+
+private:
+    void HandleEditorActiveSceneChange(StringHash eventType, VariantMap& eventData);
+
+    void RecursiveAddNode(ListViewItem* parent, Node* node);
+
+    SharedPtr<ListView> hierarchyList_;
+
+    SharedPtr<Scene> scene_;
+};
+
+}

+ 507 - 0
Source/AtomicEditor/Source/UI/UIInspectorFrame.cpp

@@ -0,0 +1,507 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#include "AtomicEditor.h"
+
+#include <TurboBadger/tb_select.h>
+#include <TurboBadger/tb_editfield.h>
+#include <TurboBadger/tb_inline_select.h>
+
+#include <Atomic/Core/Context.h>
+#include <Atomic/IO/Log.h>
+#include <Atomic/IO/FileSystem.h>
+#include <Atomic/Resource/ResourceEvents.h>
+
+#include <Atomic/Scene/Component.h>
+
+#include <Atomic/UI/TBUI.h>
+
+#include "AEEditor.h"
+#include "AEEvents.h"
+
+#include "UIListView.h"
+#include "UIInspectorFrame.h"
+
+#include "UI/Modal/UIModalOps.h"
+
+using namespace tb;
+
+namespace AtomicEditor
+{
+
+InspectorFrame::InspectorFrame(Context* context) :
+    AEWidget(context)
+  , refreshing_(false)
+{
+    TBUI* tbui = GetSubsystem<TBUI>();
+    tbui->LoadResourceFile(delegate_, "AtomicEditor/editor/ui/inspectorframe.tb.txt");
+
+    delegate_->SetID(TBIDC("projectframe_delegate"));
+
+    delegate_->SetGravity(WIDGET_GRAVITY_TOP_BOTTOM);
+
+    inspectorContainer_ = delegate_->GetWidgetByIDAndType<TBLayout>(TBIDC("inspectorcontainer"));
+    assert(inspectorContainer_);
+
+    SubscribeToEvent(E_EDITORACTIVENODECHANGE, HANDLER(InspectorFrame, HandleEditorActiveNodeChange));
+
+    CreateTransformLayout();
+
+}
+
+InspectorFrame::~InspectorFrame()
+{
+    if (transformLayout_->GetParent())
+        transformLayout_->GetParent()->RemoveChild(transformLayout_);
+
+    transformLayout_->Die();
+
+}
+
+void InspectorFrame::Clear()
+{
+
+}
+
+TBLayout* InspectorFrame::CreateComponentLayout(Component* component)
+{
+    TBLayout* componentLayout = new TBLayout(AXIS_Y);
+    componentLayout->SetLayoutPosition(LAYOUT_POSITION_LEFT_TOP);
+
+    TBFontDescription fd;
+    fd.SetID(TBIDC("Vera"));
+    fd.SetSize(11);
+
+    TBTextField* name = new TBTextField();
+    name->SetFontDescription(fd);
+    name->SetText(component->GetTypeName().CString());
+    componentLayout->AddChild(name);
+
+    const Vector<AttributeInfo>* attr = component->GetAttributes();
+
+    if (attr)
+    {
+        for (unsigned i = 0; i < attr->Size(); i++)
+        {
+            TBLayout* attrLayout = new TBLayout();
+            attrLayout->SetLayoutDistribution(LAYOUT_DISTRIBUTION_GRAVITY);
+
+            const AttributeInfo& info = attr->At(i);
+            TBTextField* attrName = new TBTextField();
+            attrName->SetFontDescription(fd);
+
+            String name = info.name_;
+            if (name == "Is Enabled")
+                name = "Enabled";
+
+            attrName->SetText(name.CString());
+
+            attrLayout->AddChild(attrName);
+
+            TBWidget* widget = NULL;
+
+            if (info.enumNames_)
+            {
+                TBButton* button = new TBButton();
+                widget = button;
+                int value = component->GetAttribute(i).GetInt();
+                button->SetText(info.enumNames_[value]);
+            }
+
+            if (info.type_ == VAR_BOOL)
+            {
+                TBCheckBox* box = new TBCheckBox();
+                widget = box;
+                box->SetValue(component->GetAttribute(i).GetBool() ? 1 : 0);
+            }
+
+            if (info.type_ == VAR_FLOAT)
+            {
+                TBEditField* editField = new TBEditField();
+                editField->SetFontDescription(fd);
+                widget = editField;
+                editField->SetEditType(EDIT_TYPE_NUMBER);
+                editField->SetText(ToString("%f", component->GetAttribute(i).GetFloat()).CString());
+            }
+
+            if (info.type_ == VAR_COLOR)
+            {
+                TBLayout* colorLayout = new TBLayout();
+
+                LayoutParams lp;
+                lp.SetWidth(32);
+
+                TBEditField* red = new TBEditField();
+                TBEditField* green = new TBEditField();
+                TBEditField* blue = new TBEditField();
+                TBEditField* alpha = new TBEditField();
+
+                red->SetEditType(EDIT_TYPE_NUMBER);
+                green->SetEditType(EDIT_TYPE_NUMBER);
+                blue->SetEditType(EDIT_TYPE_NUMBER);
+                alpha->SetEditType(EDIT_TYPE_NUMBER);
+
+                red->SetLayoutParams(lp);
+                green->SetLayoutParams(lp);
+                blue->SetLayoutParams(lp);
+                alpha->SetLayoutParams(lp);
+
+                red->SetFontDescription(fd);
+                green->SetFontDescription(fd);
+                blue->SetFontDescription(fd);
+                alpha->SetFontDescription(fd);
+
+                Color color = component->GetAttribute(i).GetColor();
+
+                red->SetText(ToString("%f", color.r_).CString());
+                green->SetText(ToString("%f", color.g_).CString());
+                blue->SetText(ToString("%f", color.b_).CString());
+                alpha->SetText(ToString("%f", color.a_).CString());
+
+                colorLayout->AddChild(red);
+                colorLayout->AddChild(green);
+                colorLayout->AddChild(blue);
+                colorLayout->AddChild(alpha);
+
+                widget = colorLayout;
+
+            }
+
+            if (widget)
+            {
+
+                attrLayout->AddChild(widget);
+
+                DataBinding binding;
+                binding.widget = widget;
+                binding.component = component;
+                binding.attrIndex = i;
+                dataBindings_.Push(binding);
+            }
+
+            componentLayout->AddChild(attrLayout);
+        }
+    }
+
+    return componentLayout;
+}
+
+bool InspectorFrame::OnEvent(const TBWidgetEvent &ev)
+{
+    if (ev.type == EVENT_TYPE_KEY_DOWN)
+    {
+        for (unsigned i = 0; i < dataBindings_.Size(); i++)
+        {
+            const DataBinding& binding = dataBindings_[i];
+
+            if (binding.widget == ev.target || binding.widget->IsAncestorOf(ev.target))
+            {
+                const AttributeInfo& info = binding.component->GetAttributes()->At(binding.attrIndex);
+                return true;
+            }
+        }
+    }
+
+    if (ev.type == EVENT_TYPE_CHANGED)
+    {
+        if (refreshing_)
+            return true;
+
+        for (unsigned i = 0; i < dataBindings_.Size(); i++)
+        {
+            const DataBinding& binding = dataBindings_[i];
+
+            if (binding.widget == ev.target || binding.widget->IsAncestorOf(ev.target))
+            {
+                const AttributeInfo& info = binding.component->GetAttributes()->At(binding.attrIndex);
+
+                if (info.type_ == VAR_FLOAT)
+                {
+                    TBEditField* edit = (TBEditField*) ev.target;
+                    float v = ToFloat(edit->GetText());
+                    binding.component->SetAttribute(binding.attrIndex, Variant(v));
+
+                }
+                else if (info.type_ == VAR_COLOR)
+                {
+                    Color c = binding.component->GetAttribute(binding.attrIndex).GetColor();
+
+                    if (ev.target == binding.widget->GetChildFromIndex(0))
+                    {
+                        TBEditField* red = (TBEditField*) ev.target;
+                        c.r_ = ToFloat(red->GetText());
+                    }
+                    else if (ev.target == binding.widget->GetChildFromIndex(1))
+                    {
+                        TBEditField* green = (TBEditField*) ev.target;
+                        c.g_ = ToFloat(green->GetText());
+                    }
+                    else if (ev.target == binding.widget->GetChildFromIndex(2))
+                    {
+                        TBEditField* blue = (TBEditField*) ev.target;
+                        c.b_ = ToFloat(blue->GetText());
+                    }
+
+                    binding.component->SetAttribute(binding.attrIndex, Variant(c));
+
+                }
+
+                return true;
+
+            }
+        }
+
+        return true;
+    }
+
+    if (ev.type == EVENT_TYPE_CLICK)
+    {
+        if (ev.target->GetID() == TBIDC("enum popup"))
+        {
+            int value = (int) (ev.ref_id & 0xFFFF);
+            int bindingIdx = (int) (ev.ref_id >> 16);
+
+            const DataBinding& binding = dataBindings_[bindingIdx];
+            Variant v(value);
+            binding.component->SetAttribute(binding.attrIndex, v);
+            const AttributeInfo& info = binding.component->GetAttributes()->At(binding.attrIndex);
+            binding.widget->SetText(info.enumNames_[value]);
+
+        }
+        else
+        {
+            for (unsigned i = 0; i < dataBindings_.Size(); i++)
+            {
+                const DataBinding& binding = dataBindings_[i];
+
+                if (binding.widget == ev.target)
+                {
+                    const AttributeInfo& info = binding.component->GetAttributes()->At(binding.attrIndex);
+
+                    if (info.type_ == VAR_BOOL)
+                    {
+                        TBCheckBox* box = (TBCheckBox *) binding.widget;
+                        Variant v(box->GetValue() ? true : false);
+                        binding.component->SetAttribute(binding.attrIndex, v);
+                    }
+                    else if (info.enumNames_)
+                    {
+                        TBMenuWindow *menu = new TBMenuWindow(ev.target, TBIDC("enum popup"));
+                        TBGenericStringItemSource* source = menu->GetList()->GetDefaultSource();
+                        const char** enumPtr = info.enumNames_;
+                        unsigned v = i << 16;
+                        while (*enumPtr)
+                        {
+                            source->AddItem(new TBGenericStringItem(*enumPtr, TBID(v++)));
+                            enumPtr++;
+                        }
+                        menu->Show(source, TBPopupAlignment());
+
+                    }
+
+                }
+            }
+        }
+
+    }
+
+    return false;
+}
+
+void InspectorFrame::CreateTransformLayout()
+{
+    // transform
+
+    TBFontDescription fd;
+    fd.SetID(TBIDC("Vera"));
+    fd.SetSize(11);
+
+    transformLayout_ = new TBLayout(AXIS_Y);
+    transformLayout_->SetLayoutPosition(LAYOUT_POSITION_LEFT_TOP);
+
+    // POSITION
+    TBTextField* posText = new TBTextField();
+    posText->SetText("Position");
+    posText->SetFontDescription(fd);
+    transformLayout_->AddChild(posText);
+
+    TBLayout* positionLayout = new TBLayout();
+    positionLayout->SetSpacing(0);
+
+    posXSelect_ = new TBInlineSelect();
+    posXSelect_->SetFontDescription(fd);
+    posXSelect_->SetLimits(-10000000, 10000000);
+    positionLayout->AddChild(posXSelect_);
+
+    posYSelect_ = new TBInlineSelect();
+    posYSelect_->SetFontDescription(fd);
+    posYSelect_->SetLimits(-10000000, 10000000);
+    positionLayout->AddChild(posYSelect_);
+
+    posZSelect_ = new TBInlineSelect();
+    posZSelect_->SetFontDescription(fd);
+    posZSelect_->SetLimits(-10000000, 10000000);
+    positionLayout->AddChild(posZSelect_);
+
+    transformLayout_->AddChild(positionLayout);
+
+    // ROTATION
+    TBTextField* rotText = new TBTextField();
+    rotText->SetText("Rotation");
+    rotText->SetFontDescription(fd);
+    transformLayout_->AddChild(rotText);
+
+    TBLayout* rotLayout = new TBLayout();
+    rotLayout->SetSpacing(0);
+
+    rotXSelect_ = new TBInlineSelect();
+    rotXSelect_->SetFontDescription(fd);
+    rotXSelect_->SetLimits(-10000000, 10000000);
+    rotLayout->AddChild(rotXSelect_);
+
+    rotYSelect_ = new TBInlineSelect();
+    rotYSelect_->SetFontDescription(fd);
+    rotYSelect_->SetLimits(-10000000, 10000000);
+    rotLayout->AddChild(rotYSelect_);
+
+    rotZSelect_ = new TBInlineSelect();
+    rotZSelect_->SetFontDescription(fd);
+    rotZSelect_->SetLimits(-10000000, 10000000);
+    rotLayout->AddChild(rotZSelect_);
+
+    transformLayout_->AddChild(rotLayout);
+
+    // SCALE
+    TBTextField* scaleText = new TBTextField();
+    scaleText->SetText("Scale");
+    scaleText->SetFontDescription(fd);
+    transformLayout_->AddChild(scaleText);
+
+    TBLayout* scaleLayout = new TBLayout();
+    scaleLayout->SetSpacing(0);
+
+    scaleXSelect_ = new TBInlineSelect();
+    scaleXSelect_->SetFontDescription(fd);
+    scaleXSelect_->SetLimits(-10000000, 10000000);
+    scaleLayout->AddChild(scaleXSelect_);
+
+    scaleYSelect_ = new TBInlineSelect();
+    scaleYSelect_->SetFontDescription(fd);
+    scaleYSelect_->SetLimits(-10000000, 10000000);
+    scaleLayout->AddChild(scaleYSelect_);
+
+    scaleZSelect_ = new TBInlineSelect();
+    scaleZSelect_->SetFontDescription(fd);
+    scaleZSelect_->SetLimits(-10000000, 10000000);
+    scaleLayout->AddChild(scaleZSelect_);
+
+    transformLayout_->AddChild(scaleLayout);
+
+}
+
+void InspectorFrame::RefreshTransform()
+{
+    if (node_.Null())
+        return;
+
+    refreshing_ = true;
+
+    Vector3 pos = node_->GetPosition();
+    Vector3 scale = node_->GetScale();
+    Vector3 rot = node_->GetRotation().EulerAngles();
+
+    posXSelect_->SetValue(pos.x_);
+    posYSelect_->SetValue(pos.y_);
+    posZSelect_->SetValue(pos.z_);
+    rotXSelect_->SetValue(rot.x_);
+    rotYSelect_->SetValue(rot.y_);
+    rotZSelect_->SetValue(rot.z_);
+    scaleXSelect_->SetValue(scale.x_);
+    scaleYSelect_->SetValue(scale.y_);
+    scaleZSelect_->SetValue(scale.x_);
+
+    refreshing_ = false;
+
+}
+
+void InspectorFrame::InspectNode(Node* node)
+{
+    if (node_ == node)
+        return;
+
+    refreshing_ = true;
+
+    node_ = node;
+
+    if (transformLayout_->GetParent())
+        transformLayout_->GetParent()->RemoveChild(transformLayout_);
+
+    inspectorContainer_->DeleteAllChildren();
+    dataBindings_.Clear();
+
+    if (!node_)
+    {
+        refreshing_ = false;
+        return;
+    }
+    else
+    {
+        TBFontDescription fd;
+        fd.SetID(TBIDC("Vera"));
+        fd.SetSize(11);
+
+        TBLayout* nodeLayout = new TBLayout(AXIS_Y);
+        nodeLayout->SetLayoutPosition(LAYOUT_POSITION_LEFT_TOP);
+
+        // enabled and name
+        TBLayout* nameLayout = new TBLayout();
+        TBCheckBox* checkBox = new TBCheckBox();
+        TBEditField* nameField = new TBEditField();
+        String name = node->GetName();
+        if (!name.Length())
+            name = "(Anonymous)";
+
+        nameField->SetText(name.CString());
+        nameField->SetGravity(WIDGET_GRAVITY_LEFT_RIGHT);
+        nameLayout->AddChild(checkBox);
+        nameLayout->AddChild(nameField);
+        nodeLayout->AddChild(nameLayout);
+
+        nodeLayout->AddChild(transformLayout_);
+
+        TBSeparator* sep = new TBSeparator();
+        sep->SetGravity(WIDGET_GRAVITY_LEFT_RIGHT);
+        sep->SetSkinBg("AESeparator");
+        nodeLayout->AddChild(sep);
+
+        const Vector<SharedPtr<Component> > components = node->GetComponents();
+        for (unsigned i = 0; i < components.Size(); i++)
+        {
+            Component* c = components[i];
+            TBLayout* clayout = CreateComponentLayout(c);
+            nodeLayout->AddChild(clayout);
+
+            TBSeparator* sep = new TBSeparator();
+            sep->SetGravity(WIDGET_GRAVITY_LEFT_RIGHT);
+            sep->SetSkinBg("AESeparator");
+            nodeLayout->AddChild(sep);
+        }
+
+        inspectorContainer_->AddChild(nodeLayout);
+
+        RefreshTransform();
+    }
+
+    refreshing_ = false;
+
+}
+
+void InspectorFrame::HandleEditorActiveNodeChange(StringHash eventType, VariantMap& eventData)
+{
+    Node* node = (Node*) (eventData[EditorActiveNodeChange::P_NODE].GetPtr());
+
+    InspectNode(node);
+}
+
+}

+ 81 - 0
Source/AtomicEditor/Source/UI/UIInspectorFrame.h

@@ -0,0 +1,81 @@
+// Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
+// Please see LICENSE.md in repository root for license information
+// https://github.com/AtomicGameEngine/AtomicGameEngine
+
+#pragma once
+
+#include "AEWidget.h"
+#include "UIMenubar.h"
+
+#include <Atomic/Scene/Scene.h>
+
+using namespace Atomic;
+
+namespace tb
+{
+    class TBLayout;
+    class TBMenuWindow;
+    class TBInlineSelect;
+}
+
+namespace AtomicEditor
+{
+
+class ListView;
+class ListViewItem;
+
+class InspectorFrame : public AEWidget
+{
+
+    OBJECT(InspectorFrame);
+
+public:
+    /// Construct.
+    InspectorFrame(Context* context);
+    /// Destruct.
+    virtual ~InspectorFrame();
+
+    bool OnEvent(const TBWidgetEvent &ev);
+
+private:
+
+    struct DataBinding
+    {
+        TBWidget* widget;
+        Component* component;
+        unsigned attrIndex;
+    };
+
+    void Clear();
+
+    void InspectNode(Node* node);
+
+    void CreateTransformLayout();
+
+    TBLayout* CreateComponentLayout(Component *component);
+    void RefreshTransform();
+
+    void HandleEditorActiveNodeChange(StringHash eventType, VariantMap& eventData);
+
+    TBLayout* inspectorContainer_;
+
+    TBLayout* transformLayout_;
+    TBInlineSelect* posXSelect_;
+    TBInlineSelect* posYSelect_;
+    TBInlineSelect* posZSelect_;
+    TBInlineSelect* rotXSelect_;
+    TBInlineSelect* rotYSelect_;
+    TBInlineSelect* rotZSelect_;
+    TBInlineSelect* scaleXSelect_;
+    TBInlineSelect* scaleYSelect_;
+    TBInlineSelect* scaleZSelect_;
+
+    Vector<DataBinding> dataBindings_;
+
+    bool refreshing_;
+
+    SharedPtr<Node> node_;
+
+};
+
+}

+ 11 - 1
Source/AtomicEditor/Source/UI/UIListView.cpp

@@ -55,10 +55,15 @@ ListViewItemWidget::ListViewItemWidget(ListViewItem *item, ListViewItemSource *s
         GetContentRoot()->AddChild(skinImage);
     }
 
+    TBFontDescription fd;
+    fd.SetID(TBIDC("Vera"));
+    fd.SetSize(11);
+
     TBTextField* tfield = new TBTextField();
     tfield->SetIgnoreInput(true);
     tfield->SetSkinBg(TBIDC("Folder"));
     tfield->SetText(item->str);
+    tfield->SetFontDescription(fd);
 
     SetSkinBg(TBIDC("TBSelectItem"));
     GetContentRoot()->AddChild(tfield);
@@ -68,6 +73,11 @@ ListViewItemWidget::ListViewItemWidget(ListViewItem *item, ListViewItemSource *s
 
 bool ListViewItemWidget::OnEvent(const TBWidgetEvent &ev)
 {
+    if (ev.type == EVENT_TYPE_WHEEL)
+    {
+        return false;
+    }
+
     // get clicks this way, not sure we want to
     if (ev.type == EVENT_TYPE_CLICK && ev.target->GetID() == item_->id)
     {
@@ -114,7 +124,7 @@ ListView::ListView(Context* context, const TBID& id) :
 {
     rootList_ = new TBSelectList();
     rootList_->SetID(id);
-    //rootList_->GetScrollContainer()->SetScrollMode(SCROLL_MODE_X_AUTO_Y_AUTO);
+
 
     // dummy filter so filter is called
     rootList_->SetFilter(" ");

+ 23 - 1
Source/AtomicEditor/Source/UI/UIMainFrame.cpp

@@ -19,6 +19,8 @@
 #include "UIMainFrame.h"
 #include "UIMainToolbar.h"
 #include "UIProjectFrame.h"
+#include "UIHierarchyFrame.h"
+#include "UIInspectorFrame.h"
 #include "UIPlayerWidget.h"
 #include "UIResourceFrame.h"
 #include "UIWelcomeFrame.h"
@@ -40,7 +42,6 @@
 
 #include "Tools/External/AEExternalTooling.h"
 
-
 using namespace tb;
 
 namespace AtomicEditor
@@ -83,6 +84,27 @@ MainFrame::MainFrame(Context* context) :
     wd->SetSize(rect.w, rect.h);
     projectviewcontainer->AddChild(wd);
 
+    hierarchyframe_ = new HierarchyFrame(context_);
+    TBLayout* hierarchycontainer = delegate_->GetWidgetByIDAndType<TBLayout>(TBIDC("hierarchycontainer"));
+    assert(hierarchycontainer);
+
+    // better way to do this? projectviewcontainer isn't a layout
+    wd = hierarchyframe_->GetWidgetDelegate();
+    rect = hierarchycontainer->GetRect();
+    wd->SetSize(rect.w, rect.h);
+    hierarchycontainer->AddChild(wd);
+
+    inspectorframe_ = new InspectorFrame(context_);
+    TBLayout* inspectorcontainer = delegate_->GetWidgetByIDAndType<TBLayout>(TBIDC("inspectorcontainer"));
+    assert(inspectorcontainer);
+
+    // better way to do this? inspectorcontainer isn't a layout
+    wd = inspectorframe_->GetWidgetDelegate();
+    rect = inspectorcontainer->GetRect();
+    wd->SetSize(rect.w, rect.h);
+    inspectorcontainer->AddChild(wd);
+
+
     resourceviewcontainer_ = delegate_->GetWidgetByIDAndType<TBLayout>(TBIDC("resourceviewcontainer"));
     assert(resourceviewcontainer_);
     rect = resourceviewcontainer_->GetRect();

+ 5 - 0
Source/AtomicEditor/Source/UI/UIMainFrame.h

@@ -24,6 +24,8 @@ namespace AtomicEditor
 {
 
 class ProjectFrame;
+class HierarchyFrame;
+class InspectorFrame;
 class ResourceFrame;
 class FindTextWidget;
 class MainToolbar;
@@ -55,6 +57,7 @@ public:
     bool OnEvent(const TBWidgetEvent &ev);
 
     ProjectFrame* GetProjectFrame();
+    HierarchyFrame* GetHierarchyFrame();
     ResourceFrame* GetResourceFrame();
     WelcomeFrame* GetWelcomeFrame();
     FindTextWidget* GetFindTextWidget();
@@ -95,6 +98,8 @@ private:
     TBSkinImage* platformIndicator_;
 
     SharedPtr<ProjectFrame> projectframe_;
+    SharedPtr<HierarchyFrame> hierarchyframe_;
+    SharedPtr<InspectorFrame> inspectorframe_;
     SharedPtr<ResourceFrame> resourceframe_;
     SharedPtr<FindTextWidget> findtextwidget_;
     SharedPtr<MainToolbar> maintoolbar_;

+ 22 - 2
Source/AtomicEditor/Source/UI/UIProjectFrame.cpp

@@ -255,12 +255,22 @@ TBLayout* ProjectFrame::CreateButtonLayout(const String& fullpath, const String&
     blayout->AddChild(spacer);
 
     TBButton* button = new TBButton();
+
+    LayoutParams lp;
+    lp.SetHeight(20);
+
+    TBFontDescription fd;
+    fd.SetID(TBIDC("Vera"));
+    fd.SetSize(11);
+
     button->SetGravity(WIDGET_GRAVITY_LEFT);
     TBSkinImage* image = new TBSkinImage(bitmapID);
-    image->SetRect(TBRect(0, 0, 16, 16));
+    image->SetRect(TBRect(0, 0, 12, 12));
     image->SetGravity(WIDGET_GRAVITY_RIGHT);
     blayout->AddChild(image);
     button->SetID(TBIDC(fullpath.CString()));
+    button->SetLayoutParams(lp);
+    button->SetFontDescription(fd);
     button->SetText(text.CString());
     button->SetSkinBg(TBIDC("TBButton.flat"));
     blayout->AddChild(button);
@@ -289,11 +299,21 @@ void ProjectFrame::RefreshContent(const String& fullpath)
 
     if (fullpath != project->GetResourcePath())
     {
+        LayoutParams lp;
+        lp.SetHeight(20);
+
+        TBFontDescription fd;
+        fd.SetID(TBIDC("Vera"));
+        fd.SetSize(11);
+
         TBButton* button = new TBButton();
         button->SetGravity(WIDGET_GRAVITY_LEFT);
-        button->SetText("..");
+        button->SetText("..                     ");
         button->SetID(TBIDC(".."));
         button->SetSkinBg(TBIDC("TBButton.flat"));
+        button->SetLayoutParams(lp);
+        button->SetFontDescription(fd);
+
         container->AddChild(button);
     }
 

+ 5 - 0
Source/AtomicEditor/Source/UI/UIResourceFrame.cpp

@@ -118,6 +118,11 @@ void ResourceFrame::EditResource(const String& fullpath)
         JSResourceEditor* jse = new JSResourceEditor(context_, fullpath, tabcontainer_);
         editor = jse;
     }
+    else if (ext == ".scene")
+    {
+        SceneResourceEditor* sre = new SceneResourceEditor(context_, fullpath, tabcontainer_);
+        editor = sre;
+    }
     else if (ext == ".xml" || ext == ".txt")
     {
         //SceneResourceEditor* sre = new SceneResourceEditor(context_, fullpath, tabcontainer_);

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

@@ -55,8 +55,8 @@ enum EVENT_TYPE {
 	EVENT_TYPE_POINTER_DOWN,
 	EVENT_TYPE_POINTER_UP,
 	EVENT_TYPE_POINTER_MOVE,
-        EVENT_TYPE_RIGHT_POINTER_DOWN,
-        EVENT_TYPE_RIGHT_POINTER_UP,
+    EVENT_TYPE_RIGHT_POINTER_DOWN,
+    EVENT_TYPE_RIGHT_POINTER_UP,
 	EVENT_TYPE_WHEEL,
 
 	/** Invoked after changing text in a TBTextField, changing selected item