| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430 |
- // Portions Copyright (c) 2008-2015 the Urho3D project.
- // 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 <Atomic/Graphics/Model.h>
- #include <Atomic/Graphics/Material.h>
- #include <Atomic/Graphics/Octree.h>
- #include <Atomic/Resource/ResourceCache.h>
- #include <Atomic/UI/UI.h>
- #include <Atomic/Input/Input.h>
- #include "Gizmo3D.h"
- namespace AtomicEditor
- {
- Gizmo3D::Gizmo3D(Context* context) : Object(context)
- {
- ResourceCache* cache = GetSubsystem<ResourceCache>();
- gizmoNode_ = new Node(context_);
- gizmo_ = gizmoNode_->CreateComponent<StaticModel>();
- gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/Axes.mdl"));
- gizmo_->SetEnabled(false);
- gizmo_->SetViewMask(0x80000000); // Editor raycasts use viewmask 0x7fffffff
- gizmo_->SetOccludee(false);
- axisMode_ = AXIS_LOCAL;
- gizmoAxisX_.lastSelected_ = false;
- gizmoAxisY_.lastSelected_ = false;
- gizmoAxisZ_.lastSelected_ = false;
- editMode_ = EDIT_SELECT;
- lastEditMode_ = EDIT_SELECT;
- }
- Gizmo3D::~Gizmo3D()
- {
- }
- void Gizmo3D::SetView(SceneView3D* view3D)
- {
- view3D_ = view3D;
- scene_ = view3D->GetScene();
- camera_ = view3D->GetCameraNode()->GetComponent<Camera>();
- assert(camera_.NotNull());
- }
- void Gizmo3D::Position()
- {
- Vector3 center(0, 0, 0);
- bool containsScene = false;
- for (unsigned i = 0; i < editNodes_->Size(); ++i)
- {
- // Scene's transform should not be edited, so hide gizmo if it is included
- if (editNodes_->At(i) == scene_)
- {
- containsScene = true;
- break;
- }
- center += editNodes_->At(i)->GetWorldPosition();
- }
- if (editNodes_->Empty() || containsScene)
- {
- Hide();
- return;
- }
- center /= editNodes_->Size();
- gizmoNode_->SetPosition(center);
- if (axisMode_ == AXIS_WORLD || editNodes_->Size() > 1)
- gizmoNode_->SetRotation(Quaternion());
- else
- gizmoNode_->SetRotation(editNodes_->At(0)->GetWorldRotation());
- ResourceCache* cache = GetSubsystem<ResourceCache>();
- if (editMode_ != lastEditMode_)
- {
- switch (editMode_)
- {
- case EDIT_MOVE:
- gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/Axes.mdl"));
- break;
- case EDIT_ROTATE:
- gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/RotateAxes.mdl"));
- break;
- case EDIT_SCALE:
- gizmo_->SetModel(cache->GetResource<Model>("AtomicEditor/Models/ScaleAxes.mdl"));
- break;
- default:
- break;
- }
- lastEditMode_ = editMode_;
- }
- bool orbiting = false;
- if ((editMode_ != EDIT_SELECT && !orbiting) && !gizmo_->IsEnabled())
- Show();
- else if ((editMode_ == EDIT_SELECT || orbiting) && gizmo_->IsEnabled())
- Hide();
- if (gizmo_->IsEnabled())
- {
- float scale = 0.1f / camera_->GetZoom();
- if (camera_->IsOrthographic())
- scale *= camera_->GetOrthoSize();
- else
- scale *= (camera_->GetView() * gizmoNode_->GetPosition()).z_;
- gizmoNode_->SetScale(Vector3(scale, scale, scale));
- }
- }
- void Gizmo3D::Update(Vector<Node *> &editNodes)
- {
- editNodes_ = &editNodes;
- Use();
- Position();
- }
- void Gizmo3D::CalculateGizmoAxes()
- {
- gizmoAxisX_.axisRay_ = Ray(gizmoNode_->GetPosition(), gizmoNode_->GetRotation() * Vector3(1, 0, 0));
- gizmoAxisY_.axisRay_ = Ray(gizmoNode_->GetPosition(), gizmoNode_->GetRotation() * Vector3(0, 1, 0));
- gizmoAxisZ_.axisRay_ = Ray(gizmoNode_->GetPosition(), gizmoNode_->GetRotation() * Vector3(0, 0, 1));
- }
- void Gizmo3D::Use()
- {
- if (gizmo_.Null() || !gizmo_->IsEnabled() || editMode_ == EDIT_SELECT)
- {
- //StoreGizmoEditActions();
- //previousGizmoDrag = false;
- return;
- }
- ResourceCache* cache = GetSubsystem<ResourceCache>();
- Input* input = GetSubsystem<Input>();
- Ray cameraRay = view3D_->GetCameraRay();
- float scale = gizmoNode_->GetScale().x_;
- // Recalculate axes only when not left-dragging
- bool drag = input->GetMouseButtonDown(MOUSEB_LEFT);
- if (!drag)
- CalculateGizmoAxes();
- gizmoAxisX_.Update(cameraRay, scale, drag, camera_->GetNode());
- gizmoAxisY_.Update(cameraRay, scale, drag, camera_->GetNode());
- gizmoAxisZ_.Update(cameraRay, scale, drag, camera_->GetNode());
- if (gizmoAxisX_.selected_ != gizmoAxisX_.lastSelected_)
- {
- gizmo_->SetMaterial(0, cache->GetResource<Material>(
- gizmoAxisX_.selected_ ?
- "AtomicEditor/Materials/BrightRedUnlit.xml" : "AtomicEditor/Materials/RedUnlit.xml"));
- gizmoAxisX_.lastSelected_ = gizmoAxisX_.selected_;
- }
- if (gizmoAxisY_.selected_ != gizmoAxisY_.lastSelected_)
- {
- gizmo_->SetMaterial(1, cache->GetResource<Material>(
- gizmoAxisY_.selected_ ?
- "AtomicEditor/Materials/BrightGreenUnlit.xml" : "AtomicEditor/Materials/GreenUnlit.xml"));
- gizmoAxisY_.lastSelected_ = gizmoAxisY_.selected_;
- }
- if (gizmoAxisZ_.selected_ != gizmoAxisZ_.lastSelected_)
- {
- gizmo_->SetMaterial(2, cache->GetResource<Material>(
- gizmoAxisZ_.selected_ ?
- "AtomicEditor/Materials/BrightBlueUnlit.xml" : "AtomicEditor/Materials/BlueUnlit.xml"));
- gizmoAxisZ_.lastSelected_ = gizmoAxisZ_.selected_;
- }
- if (drag)
- Drag();
- }
- bool Gizmo3D::MoveEditNodes(Vector3 adjust)
- {
- bool moved = false;
- if (adjust.Length() > M_EPSILON)
- {
- for (unsigned i = 0; i < editNodes_->Size(); ++i)
- {
- /*
- if (moveSnap)
- {
- float moveStepScaled = moveStep * snapScale;
- adjust.x = Floor(adjust.x / moveStepScaled + 0.5) * moveStepScaled;
- adjust.y = Floor(adjust.y / moveStepScaled + 0.5) * moveStepScaled;
- adjust.z = Floor(adjust.z / moveStepScaled + 0.5) * moveStepScaled;
- }
- */
- Node* node = editNodes_->At(i);
- Vector3 nodeAdjust = adjust;
- if (axisMode_ == AXIS_LOCAL && editNodes_->Size() == 1)
- nodeAdjust = node->GetWorldRotation() * nodeAdjust;
- Vector3 worldPos = node->GetWorldPosition();
- Vector3 oldPos = node->GetPosition();
- worldPos += nodeAdjust;
- if (!node->GetParent())
- node->SetPosition(worldPos);
- else
- node->SetPosition(node->GetParent()->WorldToLocal(worldPos));
- if (node->GetPosition() != oldPos)
- moved = true;
- }
- }
- return moved;
- }
- 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 (unsigned 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 (unsigned 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()
- {
- gizmoAxisX_.Moved();
- gizmoAxisY_.Moved();
- gizmoAxisZ_.Moved();
- }
- void Gizmo3D::Drag()
- {
- bool moved = false;
- float scale = gizmoNode_->GetScale().x_;
- if (editMode_ == EDIT_MOVE)
- {
- 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_);
- moved = MoveEditNodes(adjust);
- }
- else if (editMode_ == EDIT_ROTATE)
- {
- const float rotSensitivity = 50.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 = RotateEditNodes(adjust);
- }
- else if (editMode_ == EDIT_SCALE)
- {
- 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_);
- // Special handling for uniform scale: use the unmodified X-axis movement only
- if (editMode_ == EDIT_SCALE && gizmoAxisX_.selected_ && gizmoAxisY_.selected_ && gizmoAxisZ_.selected_)
- {
- float x = gizmoAxisX_.t_ - gizmoAxisX_.lastT_;
- adjust = Vector3(x, x, x);
- }
- moved = ScaleEditNodes(adjust);
- }
- if (moved)
- {
- Moved();
- //UpdateNodeAttributes();
- //needGizmoUndo = true;
- }
- }
- void Gizmo3D::SetEditMode(EditMode mode)
- {
- editMode_ = mode;
- }
- void Gizmo3D::Hide()
- {
- gizmo_->SetEnabled(false);
- }
- void Gizmo3D::Show()
- {
- if (scene_.Null())
- return;
- gizmo_->SetEnabled(true);
- Octree* octree = scene_->GetComponent<Octree>();
- if (!octree)
- return;
- octree->AddManualDrawable(gizmo_);
- }
- }
|