Pārlūkot izejas kodu

Scene Editor: Camera frame selection

Josh Engebretson 10 gadi atpakaļ
vecāks
revīzija
9791d8dbdf

+ 110 - 11
Source/AtomicEditor/Editors/SceneEditor3D/SceneView3D.cpp

@@ -57,7 +57,8 @@ SceneView3D ::SceneView3D(Context* context, SceneEditor3D *sceneEditor) :
     pitch_(0.0f),
     pitch_(0.0f),
     mouseLeftDown_(false),
     mouseLeftDown_(false),
     mouseMoved_(false),
     mouseMoved_(false),
-    enabled_(true)
+    enabled_(true),
+    cameraMove_(false)
 {
 {
 
 
     sceneEditor_ = sceneEditor;
     sceneEditor_ = sceneEditor;
@@ -147,6 +148,8 @@ void SceneView3D::MoveCamera(float timeStep)
 
 
     Input* input = GetSubsystem<Input>();
     Input* input = GetSubsystem<Input>();
 
 
+    bool mouseInView = MouseInView();
+
     // Movement speed as world units per second
     // Movement speed as world units per second
     float MOVE_SPEED = 20.0f;
     float MOVE_SPEED = 20.0f;
     // Mouse sensitivity as degrees per pixel
     // Mouse sensitivity as degrees per pixel
@@ -156,7 +159,7 @@ void SceneView3D::MoveCamera(float timeStep)
         MOVE_SPEED *= 3.0f;
         MOVE_SPEED *= 3.0f;
 
 
     // Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees
     // Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees
-    if (input->GetMouseButtonDown(MOUSEB_RIGHT))
+    if (mouseInView && input->GetMouseButtonDown(MOUSEB_RIGHT))
     {
     {
 
 
         SetFocus();
         SetFocus();
@@ -175,39 +178,61 @@ void SceneView3D::MoveCamera(float timeStep)
     bool superdown = input->GetKeyDown(KEY_LGUI) || input->GetKeyDown(KEY_RGUI);
     bool superdown = input->GetKeyDown(KEY_LGUI) || input->GetKeyDown(KEY_RGUI);
 #endif
 #endif
 
 
-    if (!superdown && input->GetMouseButtonDown(MOUSEB_RIGHT)) {
+    if (mouseInView && !superdown && input->GetMouseButtonDown(MOUSEB_RIGHT)) {
 
 
         // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
         // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed
         // Use the Translate() function (default local space) to move relative to the node's orientation.
         // Use the Translate() function (default local space) to move relative to the node's orientation.
-        if (input->GetKeyDown('W'))
+        if (input->GetKeyDown(KEY_W))
         {
         {
             SetFocus();
             SetFocus();
             cameraNode_->Translate(Vector3::FORWARD * MOVE_SPEED * timeStep);
             cameraNode_->Translate(Vector3::FORWARD * MOVE_SPEED * timeStep);
         }
         }
-        if (input->GetKeyDown('S'))
+        if (input->GetKeyDown(KEY_S))
         {
         {
             SetFocus();
             SetFocus();
             cameraNode_->Translate(Vector3::BACK * MOVE_SPEED * timeStep);
             cameraNode_->Translate(Vector3::BACK * MOVE_SPEED * timeStep);
         }
         }
-        if (input->GetKeyDown('A'))
+        if (input->GetKeyDown(KEY_A))
         {   SetFocus();
         {   SetFocus();
             cameraNode_->Translate(Vector3::LEFT * MOVE_SPEED * timeStep);
             cameraNode_->Translate(Vector3::LEFT * MOVE_SPEED * timeStep);
         }
         }
-        if (input->GetKeyDown('D'))
+        if (input->GetKeyDown(KEY_D))
         {
         {
             SetFocus();
             SetFocus();
             cameraNode_->Translate(Vector3::RIGHT * MOVE_SPEED * timeStep);
             cameraNode_->Translate(Vector3::RIGHT * MOVE_SPEED * timeStep);
         }
         }
-        if (input->GetKeyDown('Q'))
+        if (input->GetKeyDown(KEY_Q))
         {
         {
             SetFocus();
             SetFocus();
             cameraNode_->Translate(Vector3::UP * MOVE_SPEED * timeStep);
             cameraNode_->Translate(Vector3::UP * MOVE_SPEED * timeStep);
         }
         }
-        if (input->GetKeyDown('E'))
+        if (input->GetKeyDown(KEY_E))
         {
         {
             SetFocus();
             SetFocus();
             cameraNode_->Translate(Vector3::DOWN * MOVE_SPEED * timeStep);
             cameraNode_->Translate(Vector3::DOWN * MOVE_SPEED * timeStep);
         }
         }
+    }
+    else if (!superdown)
+    {
+        if (input->GetKeyPress(KEY_F))
+        {
+            FrameSelection();
+        }
+    }
+
+    if (cameraMove_)
+    {
+
+        cameraMoveTime_ += timeStep * 3.0f;
+
+        if (cameraMoveTime_ > 1.0f)
+        {
+            cameraMove_ = false;
+            cameraMoveTime_ = 1.0f;
+        }
+
+        Vector3 pos = cameraMoveStart_.Lerp(cameraMoveTarget_, cameraMoveTime_);
+        cameraNode_->SetWorldPosition(pos);
 
 
     }
     }
 }
 }
@@ -416,8 +441,7 @@ void SceneView3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
     // Timestep parameter is same no matter what event is being listened to
     // Timestep parameter is same no matter what event is being listened to
     float timeStep = eventData[Update::P_TIMESTEP].GetFloat();
     float timeStep = eventData[Update::P_TIMESTEP].GetFloat();
 
 
-    if (MouseInView())
-        MoveCamera(timeStep);
+    MoveCamera(timeStep);
 
 
     QueueUpdate();
     QueueUpdate();
 
 
@@ -607,6 +631,81 @@ void SceneView3D::HandleDragEnded(StringHash eventType, VariantMap& eventData)
     dragNode_ = 0;
     dragNode_ = 0;
 }
 }
 
 
+void SceneView3D::FrameSelection()
+{
+    // TODO: Adjust once multiple selection is in
+    if (selectedNode_.Null())
+        return;
+
+    // Get all the drawables, which define the bounding box of the selection
+    PODVector<Drawable*> drawables;
+    selectedNode_->GetDerivedComponents<Drawable>(drawables);
+
+    if (!drawables.Size())
+        return;
 
 
+    // Calculate the combined bounding box of all drawables
+    BoundingBox bbox;
+    for (unsigned i = 0; i < drawables.Size(); i++  )
+    {
+        Drawable* drawable = drawables[i];
+        bbox.Merge(drawable->GetWorldBoundingBox());
+    }
+
+    if (bbox.Size().x_ < .01f || bbox.Size().y_ < .01f || bbox.Size().z_ < .01f)
+        return;
+
+    // Generate vertices for all 8 corners
+    Vector3 vertices[8];
+    vertices[0] = bbox.min_;
+    vertices[1] = Vector3(bbox.max_.x_, bbox.min_.y_, bbox.min_.z_);
+    vertices[2] = Vector3(bbox.min_.x_, bbox.max_.y_, bbox.min_.z_);
+    vertices[3] = Vector3(bbox.max_.x_, bbox.max_.y_, bbox.min_.z_);
+    vertices[4] = Vector3(bbox.min_.x_, bbox.min_.y_, bbox.max_.z_);
+    vertices[5] = Vector3(bbox.max_.x_, bbox.min_.y_, bbox.max_.z_);
+    vertices[6] = Vector3(bbox.min_.x_, bbox.max_.y_, bbox.max_.z_);
+    vertices[7] = bbox.max_;
+
+    cameraMoveStart_ = cameraNode_->GetWorldPosition();
+
+    // Calculate screen rect which will be used to accept projected position
+    int vwidth = viewport_->GetWidth();
+    int vheight = viewport_->GetHeight();
+    Rect screenRect(vwidth/6, vheight/6, vwidth - vwidth/6, vheight - vheight/6);
+
+    // given the target selection's world position, offset by the camera node's world direction
+    // keep backing up until bounding box is entirely contained in the target screen rect
+    float factor = .01f;
+    while (true)
+    {
+        // We don't rotate the camera during framing, otherwise this would be jarring
+        Vector3 dir = cameraNode_->GetWorldDirection();
+        dir *= factor;
+        Vector3 dest = selectedNode_->GetWorldPosition() - dir;
+        cameraNode_->SetWorldPosition(dest);
+
+        unsigned i;
+        for (i = 0; i < 8; i++)
+        {
+            IntVector2 screenPoint = viewport_->WorldToScreenPoint(vertices[i]);
+            if (!screenRect.IsInside(Vector2(screenPoint.x_, screenPoint.y_)))
+                break;
+        }
+
+        if (i == 8)
+        {
+            cameraMoveTarget_ = dest;
+            cameraMoveTime_ = 0.0f;
+            cameraMove_ = true;
+            break;
+        }
+
+        factor += 0.01f;
+    }
+
+    cameraNode_->SetWorldPosition(cameraMoveStart_);
+
+
+}
 
 
 }
 }

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

@@ -22,6 +22,7 @@ class Node;
 class Camera;
 class Camera;
 class DebugRenderer;
 class DebugRenderer;
 class Octree;
 class Octree;
+class SmoothedTransform;
 }
 }
 
 
 namespace AtomicEditor
 namespace AtomicEditor
@@ -46,6 +47,8 @@ public:
     void SetPitch(float pitch) { pitch_ = pitch; }
     void SetPitch(float pitch) { pitch_ = pitch; }
     void SetYaw(float yaw) { yaw_ = yaw; }
     void SetYaw(float yaw) { yaw_ = yaw; }
 
 
+    void FrameSelection();
+
     void Enable();
     void Enable();
     void Disable();
     void Disable();
     bool IsEnabled() { return enabled_; }
     bool IsEnabled() { return enabled_; }
@@ -84,6 +87,11 @@ private:
 
 
     bool enabled_;
     bool enabled_;
 
 
+    bool cameraMove_;
+    float cameraMoveTime_;
+    Vector3 cameraMoveStart_;
+    Vector3 cameraMoveTarget_;
+
     SharedPtr<Camera> camera_;
     SharedPtr<Camera> camera_;
     SharedPtr<DebugRenderer> debugRenderer_;
     SharedPtr<DebugRenderer> debugRenderer_;
     SharedPtr<Octree> octree_;
     SharedPtr<Octree> octree_;