Browse Source

Scale/Rotate Gizmo

Josh Engebretson 10 years ago
parent
commit
952a6a6cff

+ 12 - 0
Data/AtomicEditor/Resources/EditorData/AtomicEditor/editor/ui/maintoolbar.tb.txt

@@ -7,3 +7,15 @@ TBLayout: distribution: gravity
 		@include definitions>menubutton
 		@include definitions>menubutton
 		TBSkinImage: skin: PlayButton
 		TBSkinImage: skin: PlayButton
 		id maintoolbar_play
 		id maintoolbar_play
+	TBButton 
+		@include definitions>menubutton
+		text: "T"
+		id 3d_translate
+	TBButton 
+		@include definitions>menubutton
+		text: "R"
+		id 3d_rotate
+	TBButton 
+		@include definitions>menubutton
+		text: "S"
+		id 3d_scale

+ 118 - 28
Source/AtomicEditor/Source/Editors/SceneEditor3D/Gizmo3D.cpp

@@ -27,10 +27,6 @@ Gizmo3D::Gizmo3D(Context* context) : Object(context)
     gizmoNode_ = new Node(context_);
     gizmoNode_ = new Node(context_);
     gizmo_ = gizmoNode_->CreateComponent<StaticModel>();
     gizmo_ = gizmoNode_->CreateComponent<StaticModel>();
     gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/Axes.mdl"));
     gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/Axes.mdl"));
-    gizmo_->SetMaterial(0, cache->GetResource<Material>("AtomicEditor/Materials/RedUnlit.xml"));
-    gizmo_->SetMaterial(1, cache->GetResource<Material>("AtomicEditor/Materials/GreenUnlit.xml"));
-    gizmo_->SetMaterial(2, cache->GetResource<Material>("AtomicEditor/Materials/BlueUnlit.xml"));
-
 
 
     gizmo_->SetEnabled(false);
     gizmo_->SetEnabled(false);
     gizmo_->SetViewMask(0x80000000); // Editor raycasts use viewmask 0x7fffffff
     gizmo_->SetViewMask(0x80000000); // Editor raycasts use viewmask 0x7fffffff
@@ -42,8 +38,8 @@ Gizmo3D::Gizmo3D(Context* context) : Object(context)
     gizmoAxisY_.lastSelected_ = false;
     gizmoAxisY_.lastSelected_ = false;
     gizmoAxisZ_.lastSelected_ = false;
     gizmoAxisZ_.lastSelected_ = false;
 
 
-    editMode_ = EDIT_MOVE;
-    lastEditMode_ = EDIT_MOVE;
+    editMode_ = EDIT_SELECT;
+    lastEditMode_ = EDIT_SELECT;
 }
 }
 
 
 Gizmo3D::~Gizmo3D()
 Gizmo3D::~Gizmo3D()
@@ -77,7 +73,7 @@ void Gizmo3D::Position()
 
 
     if (editNodes_->Empty() || containsScene)
     if (editNodes_->Empty() || containsScene)
     {
     {
-        //HideGizmo();
+        Hide();
         return;
         return;
     }
     }
 
 
@@ -249,6 +245,94 @@ bool Gizmo3D::MoveEditNodes(Vector3 adjust)
 
 
 }
 }
 
 
+bool Gizmo3D::RotateEditNodes(Vector3 adjust)
+{
+    bool moved = false;
+
+    /*
+    if (rotateSnap)
+    {
+        float rotateStepScaled = rotateStep * snapScale;
+        adjust.x = Floor(adjust.x / rotateStepScaled + 0.5) * rotateStepScaled;
+        adjust.y = Floor(adjust.y / rotateStepScaled + 0.5) * rotateStepScaled;
+        adjust.z = Floor(adjust.z / rotateStepScaled + 0.5) * rotateStepScaled;
+    }
+    */
+
+    if (adjust.Length() > M_EPSILON)
+    {
+        moved = true;
+
+        for (uint i = 0; i < editNodes_->Size(); ++i)
+        {
+            Node* node = editNodes_->At(i);
+            Quaternion rotQuat(adjust.x_, adjust.y_, adjust.z_);
+            if (axisMode_ == AXIS_LOCAL && editNodes_->Size() == 1)
+                node->SetRotation(node->GetRotation() * rotQuat);
+            else
+            {
+                Vector3 offset = node->GetWorldPosition() - gizmoAxisX_.axisRay_.origin_;
+                if (node->GetParent() && node->GetParent()->GetWorldRotation() != Quaternion(1, 0, 0, 0))
+                    rotQuat = node->GetParent()->GetWorldRotation().Inverse() * rotQuat * node->GetParent()->GetWorldRotation();
+                node->SetRotation(rotQuat * node->GetRotation());
+                Vector3 newPosition = gizmoAxisX_.axisRay_.origin_ + rotQuat * offset;
+                if (node->GetParent())
+                    newPosition = node->GetParent()->WorldToLocal(newPosition);
+                node->SetPosition(newPosition);
+            }
+        }
+    }
+
+    return moved;
+}
+
+bool Gizmo3D::ScaleEditNodes(Vector3 adjust)
+{
+    bool moved = false;
+
+    if (adjust.Length() > M_EPSILON)
+    {
+        for (uint i = 0; i < editNodes_->Size(); ++i)
+        {
+            Node* node = editNodes_->At(i);
+
+            Vector3 scale = node->GetScale();
+            Vector3 oldScale = scale;
+
+            if (true)//!scaleSnap)
+                scale += adjust;
+            else
+            {
+                /*
+                float scaleStepScaled = scaleStep * snapScale;
+                if (adjust.x != 0)
+                {
+                    scale.x += adjust.x * scaleStepScaled;
+                    scale.x = Floor(scale.x / scaleStepScaled + 0.5) * scaleStepScaled;
+                }
+                if (adjust.y != 0)
+                {
+                    scale.y += adjust.y * scaleStepScaled;
+                    scale.y = Floor(scale.y / scaleStepScaled + 0.5) * scaleStepScaled;
+                }
+                if (adjust.z != 0)
+                {
+                    scale.z += adjust.z * scaleStepScaled;
+                    scale.z = Floor(scale.z / scaleStepScaled + 0.5) * scaleStepScaled;
+                }
+                */
+            }
+
+            if (scale != oldScale)
+                moved = true;
+
+            node->SetScale(scale);
+        }
+    }
+
+    return moved;
+}
+
 void Gizmo3D::Moved()
 void Gizmo3D::Moved()
 {
 {
     gizmoAxisX_.Moved();
     gizmoAxisX_.Moved();
@@ -261,6 +345,8 @@ void Gizmo3D::Drag()
 {
 {
     bool moved = false;
     bool moved = false;
 
 
+    float scale = gizmoNode_->GetScale().x_;
+
     if (editMode_ == EDIT_MOVE)
     if (editMode_ == EDIT_MOVE)
     {
     {
         Vector3 adjust(0, 0, 0);
         Vector3 adjust(0, 0, 0);
@@ -273,39 +359,39 @@ void Gizmo3D::Drag()
 
 
         moved = MoveEditNodes(adjust);
         moved = MoveEditNodes(adjust);
     }
     }
-    /*
-    else if (editMode == EDIT_ROTATE)
+    else if (editMode_ == EDIT_ROTATE)
     {
     {
+        const float rotSensitivity = 50.0;
+
         Vector3 adjust(0, 0, 0);
         Vector3 adjust(0, 0, 0);
-        if (gizmoAxisX.selected)
-            adjust.x = (gizmoAxisX.d - gizmoAxisX.lastD) * rotSensitivity / scale;
-        if (gizmoAxisY.selected)
-            adjust.y = -(gizmoAxisY.d - gizmoAxisY.lastD) * rotSensitivity / scale;
-        if (gizmoAxisZ.selected)
-            adjust.z = (gizmoAxisZ.d - gizmoAxisZ.lastD) * rotSensitivity / scale;
-
-        moved = RotateNodes(adjust);
+        if (gizmoAxisX_.selected_)
+            adjust.x_ = (gizmoAxisX_.d_ - gizmoAxisX_.lastD_) * rotSensitivity / scale;
+        if (gizmoAxisY_.selected_)
+            adjust.y_ = -(gizmoAxisY_.d_ - gizmoAxisY_.lastD_) * rotSensitivity / scale;
+        if (gizmoAxisZ_.selected_)
+            adjust.z_ = (gizmoAxisZ_.d_ - gizmoAxisZ_.lastD_) * rotSensitivity / scale;
+
+        moved = RotateEditNodes(adjust);
     }
     }
-    else if (editMode == EDIT_SCALE)
+    else if (editMode_ == EDIT_SCALE)
     {
     {
         Vector3 adjust(0, 0, 0);
         Vector3 adjust(0, 0, 0);
-        if (gizmoAxisX.selected)
-            adjust += Vector3(1, 0, 0) * (gizmoAxisX.t - gizmoAxisX.lastT);
-        if (gizmoAxisY.selected)
-            adjust += Vector3(0, 1, 0) * (gizmoAxisY.t - gizmoAxisY.lastT);
-        if (gizmoAxisZ.selected)
-            adjust += Vector3(0, 0, 1) * (gizmoAxisZ.t - gizmoAxisZ.lastT);
+        if (gizmoAxisX_.selected_)
+            adjust += Vector3(1, 0, 0) * (gizmoAxisX_.t_ - gizmoAxisX_.lastT_);
+        if (gizmoAxisY_.selected_)
+            adjust += Vector3(0, 1, 0) * (gizmoAxisY_.t_ - gizmoAxisY_.lastT_);
+        if (gizmoAxisZ_.selected_)
+            adjust += Vector3(0, 0, 1) * (gizmoAxisZ_.t_ - gizmoAxisZ_.lastT_);
 
 
         // Special handling for uniform scale: use the unmodified X-axis movement only
         // Special handling for uniform scale: use the unmodified X-axis movement only
-        if (editMode == EDIT_SCALE && gizmoAxisX.selected && gizmoAxisY.selected && gizmoAxisZ.selected)
+        if (editMode_ == EDIT_SCALE && gizmoAxisX_.selected_ && gizmoAxisY_.selected_ && gizmoAxisZ_.selected_)
         {
         {
-            float x = gizmoAxisX.t - gizmoAxisX.lastT;
+            float x = gizmoAxisX_.t_ - gizmoAxisX_.lastT_;
             adjust = Vector3(x, x, x);
             adjust = Vector3(x, x, x);
         }
         }
 
 
-        moved = ScaleNodes(adjust);
+        moved = ScaleEditNodes(adjust);
     }
     }
-    */
 
 
     if (moved)
     if (moved)
     {
     {
@@ -316,6 +402,10 @@ void Gizmo3D::Drag()
 
 
 }
 }
 
 
+void Gizmo3D::SetEditMode(EditMode mode)
+{
+    editMode_ = mode;
+}
 
 
 void Gizmo3D::Hide()
 void Gizmo3D::Hide()
 {
 {

+ 4 - 0
Source/AtomicEditor/Source/Editors/SceneEditor3D/Gizmo3D.h

@@ -106,6 +106,8 @@ public:
 
 
     void SetView(SceneView3D* view3D);
     void SetView(SceneView3D* view3D);
 
 
+    void SetEditMode(EditMode);
+
     void Show();
     void Show();
     void Hide();
     void Hide();
     void Update(Vector<Node*>& editNodes);
     void Update(Vector<Node*>& editNodes);
@@ -121,6 +123,8 @@ private:
     void CalculateGizmoAxes();
     void CalculateGizmoAxes();
 
 
     bool MoveEditNodes(Vector3 adjust);
     bool MoveEditNodes(Vector3 adjust);
+    bool RotateEditNodes(Vector3 adjust);
+    bool ScaleEditNodes(Vector3 adjust);
 
 
     SharedPtr<Node> gizmoNode_;
     SharedPtr<Node> gizmoNode_;
 
 

+ 19 - 0
Source/AtomicEditor/Source/Editors/SceneEditor3D/SceneEditor3D.cpp

@@ -87,6 +87,25 @@ SceneEditor3D::~SceneEditor3D()
 
 
 bool SceneEditor3D::OnEvent(const TBWidgetEvent &ev)
 bool SceneEditor3D::OnEvent(const TBWidgetEvent &ev)
 {
 {
+    if (ev.target)
+    {
+        if (ev.target->GetID() == TBIDC("3d_translate"))
+        {
+            gizmo3D_->SetEditMode(Gizmo3D::EDIT_MOVE);
+            return false;
+        }
+        else if (ev.target->GetID() == TBIDC("3d_rotate"))
+        {
+            gizmo3D_->SetEditMode(Gizmo3D::EDIT_ROTATE);
+            return false;
+        }
+        else if (ev.target->GetID() == TBIDC("3d_scale"))
+        {
+            gizmo3D_->SetEditMode(Gizmo3D::EDIT_SCALE);
+            return false;
+        }
+    }
+
     return false;
     return false;
 }
 }
 
 

+ 40 - 2
Source/AtomicEditor/Source/Editors/SceneEditor3D/SceneView3D.cpp

@@ -1,3 +1,5 @@
+// Portions Copyright (c) 2008-2015 the Urho3D project.
+
 // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
 // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
 // Please see LICENSE.md in repository root for license information
 // Please see LICENSE.md in repository root for license information
 // https://github.com/AtomicGameEngine/AtomicGameEngine
 // https://github.com/AtomicGameEngine/AtomicGameEngine
@@ -12,6 +14,7 @@
 #include <Atomic/Graphics/DebugRenderer.h>
 #include <Atomic/Graphics/DebugRenderer.h>
 #include <Atomic/Graphics/Viewport.h>
 #include <Atomic/Graphics/Viewport.h>
 #include <Atomic/Graphics/Octree.h>
 #include <Atomic/Graphics/Octree.h>
+#include <Atomic/Graphics/Terrain.h>
 
 
 #include <Atomic/Input/Input.h>
 #include <Atomic/Input/Input.h>
 
 
@@ -144,12 +147,47 @@ Ray SceneView3D::GetCameraRay()
                                        float(cpos.y_ - rect.y) /rect.h);
                                        float(cpos.y_ - rect.y) /rect.h);
 }
 }
 
 
+void SceneView3D::DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode)
+{
+    if (drawNode)
+        debug->AddNode(node, 1.0, false);
+
+    // Exception for the scene to avoid bringing the editor to its knees: drawing either the whole hierarchy or the subsystem-
+    // components can have a large performance hit. Also do not draw terrain child nodes due to their large amount
+    // (TerrainPatch component itself draws nothing as debug geometry)
+    if (node != scene_ && !node->GetComponent<Terrain>())
+    {
+        const Vector<SharedPtr<Component> >& components = node->GetComponents();
+
+        for (uint j = 0; j < components.Size(); ++j)
+            components[j]->DrawDebugGeometry(debug, false);
+
+        // To avoid cluttering the view, do not draw the node axes for child nodes
+        for (uint k = 0; k < node->GetNumChildren(); ++k)
+            DrawNodeDebug(node->GetChild(k), debug, false);
+    }
+}
+
+
 void SceneView3D::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
 void SceneView3D::HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData)
 {
 {
+
+    // Visualize the currently selected nodes
+    if (selectedNode_.NotNull())
+    {
+
+    }
+    //for (uint i = 0; i < selectedNodes.length; ++i)
+        DrawNodeDebug(selectedNode_, debugRenderer_);
+
+    // Visualize the currently selected components
+    //for (uint i = 0; i < selectedComponents.length; ++i)
+    //    selectedComponents[i].DrawDebugGeometry(debug, false);
+
     Ray camRay  = GetCameraRay();
     Ray camRay  = GetCameraRay();
 
 
     PODVector<RayQueryResult> result;
     PODVector<RayQueryResult> result;
-    RayOctreeQuery query(result, camRay, RAY_TRIANGLE, camera_->GetFarClip(), DRAWABLE_ANY, DEFAULT_VIEWMASK);
+    RayOctreeQuery query(result, camRay, RAY_TRIANGLE, camera_->GetFarClip(), DRAWABLE_ANY, 0x7fffffff);
     octree_->RaycastSingle(query);
     octree_->RaycastSingle(query);
 
 
     if (query.result_.Size())
     if (query.result_.Size())
@@ -168,7 +206,7 @@ void SceneView3D::HandlePostRenderUpdate(StringHash eventType, VariantMap& event
 
 
 void SceneView3D::SelectNode(Node* node)
 void SceneView3D::SelectNode(Node* node)
 {
 {
-
+    selectedNode_ = node;
 }
 }
 
 
 void SceneView3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
 void SceneView3D::HandleUpdate(StringHash eventType, VariantMap& eventData)

+ 4 - 0
Source/AtomicEditor/Source/Editors/SceneEditor3D/SceneView3D.h

@@ -1,3 +1,5 @@
+// Portions Copyright (c) 2008-2015 the Urho3D project.
+
 // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
 // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
 // Please see LICENSE.md in repository root for license information
 // Please see LICENSE.md in repository root for license information
 // https://github.com/AtomicGameEngine/AtomicGameEngine
 // https://github.com/AtomicGameEngine/AtomicGameEngine
@@ -42,6 +44,8 @@ private:
     void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData);
     void HandleEditorActiveNodeChange(StringHash eventType, VariantMap& eventData);
     void HandleEditorActiveNodeChange(StringHash eventType, VariantMap& eventData);
 
 
+    void DrawNodeDebug(Node* node, DebugRenderer* debug, bool drawNode = true);
+
     void MoveCamera(float timeStep);
     void MoveCamera(float timeStep);
 
 
     WeakPtr<SceneEditor3D> sceneEditor_;
     WeakPtr<SceneEditor3D> sceneEditor_;

+ 11 - 0
Source/AtomicEditor/Source/UI/UIMainToolbar.cpp

@@ -11,6 +11,9 @@
 #include "../AETypes.h"
 #include "../AETypes.h"
 #include "../AEEditor.h"
 #include "../AEEditor.h"
 
 
+#include "UIMainFrame.h"
+#include "UIResourceFrame.h"
+
 using namespace tb;
 using namespace tb;
 
 
 namespace AtomicEditor
 namespace AtomicEditor
@@ -32,6 +35,14 @@ bool MainToolbar::OnEvent(const TBWidgetEvent &ev)
 {
 {
     if (ev.type == EVENT_TYPE_CLICK)
     if (ev.type == EVENT_TYPE_CLICK)
     {
     {
+        if (ev.target->GetID() == TBIDC("3d_translate") ||
+                ev.target->GetID() == TBIDC("3d_rotate") ||
+                ev.target->GetID() == TBIDC("3d_scale") )
+        {
+            ResourceFrame* rframe = GetSubsystem<MainFrame>()->GetResourceFrame();
+            rframe->SendCurrentEditorEvent(ev);
+        }
+
         if (ev.target && ev.target->GetID() == TBIDC("maintoolbar_play"))
         if (ev.target && ev.target->GetID() == TBIDC("maintoolbar_play"))
         {
         {
             if (GetSubsystem<Editor>()->IsPlayingProject())
             if (GetSubsystem<Editor>()->IsPlayingProject())

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

@@ -314,6 +314,17 @@ void ResourceFrame::ShowConsoleWidget(bool show)
 
 
 }
 }
 
 
+void ResourceFrame::SendCurrentEditorEvent(const TBWidgetEvent &ev)
+{
+    TBWidget* widget = tabcontainer_->GetCurrentPageWidget();
+    if (!widget)
+        return;
+
+    if (editorLookup_.Contains(widget))
+        editorLookup_[widget]->OnEvent(ev);
+
+}
+
 void ResourceFrame::NavigateToResource(const String& fullpath, int lineNumber, int tokenPos)
 void ResourceFrame::NavigateToResource(const String& fullpath, int lineNumber, int tokenPos)
 {
 {
     if (!editors_.Contains(fullpath))
     if (!editors_.Contains(fullpath))

+ 2 - 0
Source/AtomicEditor/Source/UI/UIResourceFrame.h

@@ -55,6 +55,8 @@ public:
 
 
     bool OnEvent(const TBWidgetEvent &ev);
     bool OnEvent(const TBWidgetEvent &ev);
 
 
+    void SendCurrentEditorEvent(const TBWidgetEvent &ev);
+
 private:
 private:
 
 
     void HandleFindText(StringHash eventType, VariantMap& eventData);
     void HandleFindText(StringHash eventType, VariantMap& eventData);