diff --git a/Documents/EditorUserGuide.md b/Documents/EditorUserGuide.md new file mode 100644 index 00000000..f54c68fb --- /dev/null +++ b/Documents/EditorUserGuide.md @@ -0,0 +1,31 @@ +## Editor User Guide + +Document will use some short names to keep clean and tidy: + +* Mouse Left Button -> MLB + +* Mouse Middle Button -> MMB + +* Mouse Right Button -> MRB + + + +Viewport is a generic name for different kinds of views, including SceneView, GameView... + +Here is viewport camera operations in the Editor. + +* Zoom + + * Scroll mouse wheel vertically + + * Keep pressing MLB and move mouse vertically + +* FOV Zoom + + * Not support : user case? + +* Panning + + * Keep pressing MMB and move. + + * Keep pressing MLB and MRB at the same time and move. diff --git a/Documents/TerrainUserGuide.md b/Documents/TerrainUserGuide.md deleted file mode 100644 index eb7fe2e3..00000000 --- a/Documents/TerrainUserGuide.md +++ /dev/null @@ -1,18 +0,0 @@ -# Terrain User Guide -This document outlines the basic usage of the terrain generator found in the editor where user may provide various terrain parameters and then click "Update Terrain" to generate the resources needed to render the terrain. - -## Terrain Mesh -Currently terrain mesh will be composed of quads where each contain 4 vertices and two triangles. Each vertex contain position and UV coordinates that can be tailed. See the parameter section for details on to control this. - -## Terrain Parameters -In the editor, user can edit the following parameters that affects the way terrain mesh and associated textures are created: -1. Sector Count X - the number of sectors in the X-axis direction. Must be at least 1. A sector is a single draw call with vertices and indices. -2. Sector Count Z - the number of sectors in the Z-axis direction. Must be at least 1. A sector is a single draw call with vertices and indices. -3. Quads Count X - the number of quads in the X-axis direction. Must be at least 1. Each quad is composed of two triangles and 4 vertices. -4. Quads Count Z - the number of quads in the Z-axis direction. Must be at least 1. Each quad is composed of two triangles and 4 vertices. -5. Quads Length X - the length between each vertices in the X-axis direction. Must be at least 1. Note each integer unit will contain an elevation value. -5. Quads Length X - the length between each vertices in the Z-axis direction. Must be at least 1. Note each integer unit will contain an elevation value. -6. Min Elevation - the minimum elevation of the terrain. This can be negative but must be smaller than Max Elevation. -7. Max Elevation - the maximum elevation of the terrain. This can be negative but must be larger than Min Elevation. -8. Power - a smoothing factor used to raise the elevation by a specific power. Note this is applied before min/max elevation is calculated. -9. Octaves - Each octave contain a seed, frequency and weight. Seed is used for random number generation that feeds into Simplex2D noise at given 2D position (x, z). Frequency is used to determine how "spiky" the noise generation is. The higher the number, the more "spiky" it is. The lower the number the more smooth the terrain will be but with larget bumps. This number should be powers of 2 such as 4, 8, 16, 32 etc. Finally weight tells the generator how to combine multiple octaves. \ No newline at end of file diff --git a/Engine/Source/Editor/Camera/ViewportCameraController.cpp b/Engine/Source/Editor/Camera/ViewportCameraController.cpp index 0b44a2f2..5659f544 100644 --- a/Engine/Source/Editor/Camera/ViewportCameraController.cpp +++ b/Engine/Source/Editor/Camera/ViewportCameraController.cpp @@ -14,24 +14,11 @@ namespace engine { -ViewportCameraController::ViewportCameraController( - const SceneWorld* pSceneWorld, - float sensitivity, - float movement_speed) - : ViewportCameraController(pSceneWorld, sensitivity, sensitivity, movement_speed) -{ -} - -ViewportCameraController::ViewportCameraController( - const SceneWorld* pSceneWorld, - float horizontal_sensitivity, - float vertical_sensitivity, - float movement_speed) - : m_pSceneWorld(pSceneWorld) - , m_horizontalSensitivity(horizontal_sensitivity) - , m_verticalSensitivity(vertical_sensitivity) - , m_movementSpeed(movement_speed) - , m_initialMovemenSpeed(movement_speed) +ViewportCameraController::ViewportCameraController(const SceneWorld* pSceneWorld, float horizontal_sensitivity, float vertical_sensitivity, float movement_speed) : + m_pSceneWorld(pSceneWorld), + m_horizontalSensitivity(horizontal_sensitivity), + m_verticalSensitivity(vertical_sensitivity), + m_movementSpeed(movement_speed) { assert(pSceneWorld); } @@ -53,14 +40,18 @@ bool ViewportCameraController::IsZooming() const bool ViewportCameraController::IsPanning() const { - return ImGui::IsMouseDown(ImGuiMouseButton_Middle); + if (ImGui::IsMouseDown(ImGuiMouseButton_Middle)) + { + return !ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsMouseDown(ImGuiMouseButton_Right); + } + + return ImGui::IsMouseDown(ImGuiMouseButton_Left) && ImGui::IsMouseDown(ImGuiMouseButton_Right); } bool ViewportCameraController::IsTurning() const { if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) { - // Offset Y is used to zoom in/out when left mouse button down. return Input::Get().GetMousePositionOffsetX() != 0.0f; } @@ -100,11 +91,28 @@ void ViewportCameraController::OnMouseUp() void ViewportCameraController::OnMouseMove(float x, float y) { bool dirty = false; - if (IsZooming()) + do { - Zoom(y); - dirty = true; - } + if (IsPanning()) + { + Panning(x, y); + dirty = true; + // While panning, should not do other opertions at the same time. + break; + } + + if (IsZooming()) + { + Zoom(-y); + dirty = true; + } + + if (IsTurning()) + { + Turning(x, y); + dirty = true; + } + } while (false); if (dirty) { @@ -127,6 +135,24 @@ void ViewportCameraController::OnMouseWheel(float y) } } +void ViewportCameraController::Zoom(float delta) +{ + float scaleDelta = delta * m_movementSpeed; + m_distanceFromLookAt -= scaleDelta; + m_eye = m_eye + m_lookAt * scaleDelta; +} + +void ViewportCameraController::Panning(float x, float y) +{ + MoveLeft(x); + m_eye = m_eye + m_up * y; +} + +void ViewportCameraController::Turning(float x, float y) +{ + +} + void ViewportCameraController::Update(float deltaTime) { if (IsInAnimation()) @@ -135,6 +161,11 @@ void ViewportCameraController::Update(float deltaTime) return; } + if (IsInControl()) + { + CameraToController(); + } + float offsetX = static_cast(Input::Get().GetMousePositionOffsetX()); float offsetY = static_cast(Input::Get().GetMousePositionOffsetY()); if (offsetX != 0.0f || offsetY != 0.0f) @@ -248,8 +279,8 @@ void ViewportCameraController::CameraToController() void ViewportCameraController::ControllerToCamera() { cd::Vec3f eye = m_eye; - cd::Vec3f lookAt = m_lookAt; - cd::Vec3f up = m_up; + cd::Vec3f lookAt = m_lookAt.Normalize(); + cd::Vec3f up = m_up.Normalize(); if (m_isTracking) { @@ -282,9 +313,10 @@ void ViewportCameraController::ControllerToCamera() TransformComponent* pTransformComponent = GetMainCameraTransformComponent(); pTransformComponent->GetTransform().SetTranslation(eye); - cd::Vec3f rotationAxis = cd::Vec3f(0.0f, 0.0f,1.0f).Cross(lookAt).Normalize(); + cd::Vec3f rotationAxis = cd::Vec3f(0.0f, 0.0f, 1.0f).Cross(lookAt); float rotationAngle = std::acos(cd::Vec3f(0.0f, 0.0f, 1.0f).Dot(lookAt)); pTransformComponent->GetTransform().SetRotation(cd::Quaternion::FromAxisAngle(rotationAxis, rotationAngle)); + pTransformComponent->Dirty(); pTransformComponent->Build(); } @@ -327,7 +359,6 @@ const cd::Transform& ViewportCameraController::GetMainCameraTransform() void ViewportCameraController::MoveForward(float amount) { m_eye = m_eye + m_lookAt * amount; - ControllerToCamera(); } void ViewportCameraController::MoveBackward(float amount) @@ -338,7 +369,6 @@ void ViewportCameraController::MoveBackward(float amount) void ViewportCameraController::MoveLeft(float amount) { m_eye = m_eye + m_lookAt.Cross(m_up) * amount; - ControllerToCamera(); } void ViewportCameraController::MoveRight(float amount) @@ -349,7 +379,6 @@ void ViewportCameraController::MoveRight(float amount) void ViewportCameraController::MoveUp(float amount) { m_eye = m_eye + cd::Vec3f(0.0f, 1.0f, 0.0f) * amount; - ControllerToCamera(); } void ViewportCameraController::MoveDown(float amount) @@ -411,7 +440,6 @@ void ViewportCameraController::ElevationChanging(float angleDegrees) { m_elevation += cd::Math::TWO_PI; } - ControllerToCamera(); } void ViewportCameraController::AzimuthChanging(float angleDegrees) @@ -425,7 +453,6 @@ void ViewportCameraController::AzimuthChanging(float angleDegrees) { m_azimuth += cd::Math::TWO_PI; } - ControllerToCamera(); } void ViewportCameraController::SynchronizeTrackingCamera() @@ -497,19 +524,6 @@ void ViewportCameraController::Focusing() } } -void ViewportCameraController::Zoom(float delta) -{ - float scaleDelta = delta * m_movementSpeed; - m_distanceFromLookAt -= scaleDelta; - m_eye = m_eye + m_lookAt * scaleDelta; -} - -void ViewportCameraController::Panning(float x, float y) -{ - MoveLeft(x); - m_eye = m_eye + m_up * y; -} - void ViewportCameraController::MoveToPosition(cd::Point position, cd::Vec3f rotation) { m_isFocusing = true; diff --git a/Engine/Source/Editor/Camera/ViewportCameraController.h b/Engine/Source/Editor/Camera/ViewportCameraController.h index 64438ef1..387a8932 100644 --- a/Engine/Source/Editor/Camera/ViewportCameraController.h +++ b/Engine/Source/Editor/Camera/ViewportCameraController.h @@ -15,14 +15,12 @@ class ViewportCameraController : public ICameraController { public: ViewportCameraController() = delete; - explicit ViewportCameraController(const SceneWorld* pSceneWorld, float sensitivity, float movement_speed); explicit ViewportCameraController(const SceneWorld* pSceneWorld, float horizontal_sensitivity, float vertical_sensitivity, float movement_speed); - ~ViewportCameraController() = default; - ViewportCameraController(const ViewportCameraController&) = delete; ViewportCameraController(ViewportCameraController&&) = delete; ViewportCameraController& operator=(const ViewportCameraController&) = delete; ViewportCameraController& operator=(ViewportCameraController&&) = delete; + virtual ~ViewportCameraController() = default; // Operations virtual bool IsInAnimation() const override; @@ -41,18 +39,14 @@ class ViewportCameraController : public ICameraController // TODO : EventDriven, not update. void Update(float deltaTime); - // Synchronizes the controller to the transform of camera current state - void CameraToController(); - - // Synchronizes the transform of camera to the controller's current state - void ControllerToCamera(); - // Implement the effect of a translation animation. void CameraFocus(); void Focusing(); - + // void Zoom(float delta); + void Panning(float x, float y); + void Turning(float x, float y); // Configs void SetMovementSpeed(float speed); @@ -76,14 +70,10 @@ class ViewportCameraController : public ICameraController void PitchLocal(float angleDegrees); void RollLocal(float angleDegrees); - void Panning(float x, float y); - // Circling Operations void AzimuthChanging(float amount); void ElevationChanging(float amount); - - // Synchronize view when begin using mayastyle camera or fpscamera void SynchronizeTrackingCamera(); @@ -95,6 +85,12 @@ class ViewportCameraController : public ICameraController const cd::Transform& GetMainCameraTransform(); float CalculateZoomScale() { return std::max(std::abs(m_distanceFromLookAt), m_dollyThreshold); } + // Synchronizes the controller to the transform of camera current state + void CameraToController(); + + // Synchronizes the transform of camera to the controller's current state + void ControllerToCamera(); + private: const SceneWorld* m_pSceneWorld; @@ -106,7 +102,6 @@ class ViewportCameraController : public ICameraController float m_horizontalSensitivity = 0.0f; float m_verticalSensitivity = 0.0f; float m_movementSpeed = 0.0f; - float m_initialMovemenSpeed = 0.0f; float m_mouseScroll = 0.0f; cd::Vec3f m_lookAtPoint = cd::Vec3f::Zero(); diff --git a/Engine/Source/Editor/EditorApp.cpp b/Engine/Source/Editor/EditorApp.cpp index ed7b437d..d25c355e 100644 --- a/Engine/Source/Editor/EditorApp.cpp +++ b/Engine/Source/Editor/EditorApp.cpp @@ -204,7 +204,7 @@ void EditorApp::InitEditorImGuiContext(engine::Language language) void EditorApp::InitEditorUILayers() { - InitEditorController(); + InitCameraController(); // Add UI layers after finish imgui and rendering contexts' initialization. auto pMainMenu = std::make_unique("MainMenu"); @@ -562,14 +562,10 @@ void EditorApp::InitShaderPrograms(bool compileAllShaders) const } } -void EditorApp::InitEditorController() +void EditorApp::InitCameraController() { - // Controller for Input events. - m_pViewportCameraController = std::make_unique( - m_pSceneWorld.get(), - 12.0f /* horizontal sensitivity */, - 12.0f /* vertical sensitivity */); - m_pViewportCameraController->CameraToController(); + m_pViewportCameraController = std::make_unique(m_pSceneWorld.get(), + 12.0f /* horizontal sensitivity */, 12.0f /* vertical sensitivity */, 5.0f /* move speed */); } void EditorApp::AddEditorRenderer(std::unique_ptr pRenderer) @@ -620,6 +616,9 @@ bool EditorApp::Update(float deltaTime) InitEngineUILayers(); } + // Input + engine::Input::Get().Reset(); + // Window m_pWindowManager->Update(); auto mainWindowPos = m_pMainWindow->GetPosition(); @@ -629,9 +628,6 @@ bool EditorApp::Update(float deltaTime) // World Data m_pSceneWorld->Update(); - // Input - engine::Input::Get().Update(); - // Update Editor GUI m_pEditorImGuiContext->SetRectPosition(mainWindowX, mainWindowY); m_pEditorImGuiContext->BeginFrame(); @@ -689,9 +685,6 @@ bool EditorApp::Update(float deltaTime) } m_pRenderContext->EndFrame(); - // Reset input data. - engine::Input::Get().FlushInputs(); - return !GetMainWindow()->ShouldClose(); } diff --git a/Engine/Source/Editor/EditorApp.h b/Engine/Source/Editor/EditorApp.h index 01839044..e2d82fb7 100644 --- a/Engine/Source/Editor/EditorApp.h +++ b/Engine/Source/Editor/EditorApp.h @@ -74,7 +74,7 @@ class EditorApp final : public engine::IApplication void InitECWorld(); // Misc - void InitEditorController(); + void InitCameraController(); bool IsAtmosphericScatteringEnable() const; private: diff --git a/Engine/Source/Editor/UILayers/MainMenu.cpp b/Engine/Source/Editor/UILayers/MainMenu.cpp index f086137d..6ca9ce98 100644 --- a/Engine/Source/Editor/UILayers/MainMenu.cpp +++ b/Engine/Source/Editor/UILayers/MainMenu.cpp @@ -165,9 +165,6 @@ void MainMenu::ViewMenu() pTransformComponent->Dirty(); pTransformComponent->Build(); pCameraComponent->BuildViewMatrix(pTransformComponent->GetTransform()); - - // TODO : add event queue to get mouse down and up events. - pCameraController->CameraToController(); } }; diff --git a/Engine/Source/Editor/UILayers/SceneView.cpp b/Engine/Source/Editor/UILayers/SceneView.cpp index 2a19d485..a9bfa10e 100644 --- a/Engine/Source/Editor/UILayers/SceneView.cpp +++ b/Engine/Source/Editor/UILayers/SceneView.cpp @@ -237,14 +237,13 @@ void SceneView::UpdateToolMenuButtons() ImGui::PopStyleColor(); } -void SceneView::PickSceneMesh(float regionWidth, float regionHeight) +void SceneView::PickSceneMesh() { // Loop through scene's all static meshes' AABB to test intersections with Ray. engine::SceneWorld* pSceneWorld = GetSceneWorld(); engine::CameraComponent* pCameraComponent = pSceneWorld->GetCameraComponent(pSceneWorld->GetMainCameraEntity()); ImVec2 mousePos = ImGui::GetMousePos(); - auto [scenePosX, scenePosY] = GetRectPosition(); - cd::Ray pickRay = pCameraComponent->EmitRay(mousePos.x - scenePosX, mousePos.y - scenePosY, regionWidth, regionHeight); + cd::Ray pickRay = pCameraComponent->EmitRay(mousePos.x - m_workRectPosX, mousePos.y - m_workRectPosY, m_workRectWidth, m_workRectHeight); float minRayTime = FLT_MAX; engine::Entity nearestEntity = engine::INVALID_ENTITY; @@ -322,22 +321,30 @@ void SceneView::Update() } } - // Draw scene. - ImGui::Image(reinterpret_cast(m_pRenderTarget->GetTextureHandle(0).idx), - ImVec2(m_pRenderTarget->GetWidth(), m_pRenderTarget->GetHeight())); + // Draw scene : index 0 should be SceneColor. + ImGui::Image(reinterpret_cast(m_pRenderTarget->GetTextureHandle(0).idx), ImVec2(m_pRenderTarget->GetWidth(), m_pRenderTarget->GetHeight())); ImGui::PopStyleVar(); ImGui::End(); - if (m_currentOperation == SelectOperation && ImGui::IsMouseDown(ImGuiMouseButton_Left)) + // Operations + if (m_pCameraController->IsInControl() || ImGuizmo::IsUsing()) { - PickSceneMesh(regionWidth, regionHeight); } - - if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && - engine::INVALID_ENTITY != pSceneWorld->GetSelectedEntity()) + else { - m_pCameraController->CameraFocus(); + // Pick + if (m_currentOperation == SelectOperation && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) + { + PickSceneMesh(); + } + + // Focus + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && + engine::INVALID_ENTITY != pSceneWorld->GetSelectedEntity()) + { + m_pCameraController->CameraFocus(); + } } } diff --git a/Engine/Source/Editor/UILayers/SceneView.h b/Engine/Source/Editor/UILayers/SceneView.h index 9e4f2e8f..d7979637 100644 --- a/Engine/Source/Editor/UILayers/SceneView.h +++ b/Engine/Source/Editor/UILayers/SceneView.h @@ -57,7 +57,7 @@ class SceneView : public engine::ImGuiBaseLayer engine::MulticastDelegate OnResize; - void PickSceneMesh(float regionWidth, float regionHeight); + void PickSceneMesh(); ImGuizmo::OPERATION GetImGuizmoOperation() const { return m_currentOperation; } RenderModeType GetRenderMode() const { return m_renderMode; } diff --git a/Engine/Source/Runtime/Camera/ICameraController.h b/Engine/Source/Runtime/Camera/ICameraController.h index cf59b13f..d86dedbe 100644 --- a/Engine/Source/Runtime/Camera/ICameraController.h +++ b/Engine/Source/Runtime/Camera/ICameraController.h @@ -21,7 +21,7 @@ class ICameraController virtual bool IsTurning() const { return false; } virtual bool IsTracking() const { return false; } virtual bool IsInWalkMode() const { return false; } - virtual bool IsControling() const { return IsInAnimation() || IsZooming() || IsFOVZooming() || IsPanning() || IsTurning() || IsTracking() || IsInWalkMode(); } + virtual bool IsInControl() const { return IsInAnimation() || IsZooming() || IsFOVZooming() || IsPanning() || IsTurning() || IsTracking() || IsInWalkMode(); } // Event Handlers virtual void OnMouseDown() {} diff --git a/Engine/Source/Runtime/Window/Input.cpp b/Engine/Source/Runtime/Window/Input.cpp index 191ffcdb..2e0db097 100644 --- a/Engine/Source/Runtime/Window/Input.cpp +++ b/Engine/Source/Runtime/Window/Input.cpp @@ -67,16 +67,4 @@ void Input::AppendInputCharacter(const char* c, size_t len) m_inputCharBufferIndex += len; } -void Input::FlushInputs() -{ - m_keyEventList.clear(); - m_inputCharBufferIndex = 0; - m_inputCharBuffer[0] = '\0'; -} - -void Input::Update() -{ - Input::Get().Reset(); -} - } \ No newline at end of file diff --git a/Engine/Source/Runtime/Window/Input.h b/Engine/Source/Runtime/Window/Input.h index 5325d555..6ada10e0 100644 --- a/Engine/Source/Runtime/Window/Input.h +++ b/Engine/Source/Runtime/Window/Input.h @@ -48,8 +48,14 @@ class Input // TODO : consider foreground/background switch. void Reset() { + // mouse m_mousePositionOffsetX = m_mousePositionOffsetY = 0; m_mouseScrollOffsetY = 0; + + // keyboard + m_keyEventList.clear(); + m_inputCharBufferIndex = 0; + m_inputCharBuffer[0] = '\0'; } // Mouse device @@ -95,10 +101,6 @@ class Input const std::vector& GetKeyEventList() const { return m_keyEventList; } const char* GetInputCharacters() const { return m_inputCharBuffer.data(); } - void FlushInputs(); - - void Update(); - private: Input();