添加简单的可视化三维控件,添加简单的摄像机控制,添加简单全局输入事件

This commit is contained in:
2025-06-05 19:38:50 +08:00
parent b47fce6fce
commit b2c7a45902
28 changed files with 653 additions and 146 deletions

View File

@ -5,10 +5,15 @@
#include "EditorLayer.h"
#include <imgui.h>
#include <ImGuizmo.h>
#include <glm/gtc/type_ptr.hpp>
#include <Hazel/Core/Input.h>
#include <Hazel/Math/Math.h>
#include <Hazel/Scene/SceneSerializer.h>
#include <Hazel/Utils/PlatformUtils.h>
#include "glm/gtx/matrix_decompose.hpp"
namespace Hazel
{
EditorLayer::EditorLayer()
@ -31,51 +36,9 @@ namespace Hazel
m_ActiveScene = CreateRef<Scene>();
// Entity
m_SquareEntity = m_ActiveScene->CreateEntity("Square A");
m_SquareEntity.AddComponent<SpriteRendererComponent>(glm::vec4{0.2f, 0.3f, 0.8f, 1.0f});
auto redSquare = m_ActiveScene->CreateEntity("Square B");
redSquare.AddComponent<SpriteRendererComponent>(glm::vec4{1.0f, 0.0f, 0.0f, 1.0f});
m_CameraEntity = m_ActiveScene->CreateEntity("Camera A");
m_CameraEntity.AddComponent<CameraComponent>();
m_PrimaryCamera = true;
m_SecondCamera = m_ActiveScene->CreateEntity("Camera B");
m_SecondCamera.AddComponent<CameraComponent>();
m_SecondCamera.GetComponent<CameraComponent>().Primary = false;
class CameraController : public ScriptableEntity
{
public:
void OnUpdate(const TimeStep ts) override
{
auto& translation = GetComponent<TransformComponent>().Translation;
const auto state = SDL_GetKeyboardState(nullptr);
if (state[SDL_SCANCODE_A])
translation.x -= ts * speed;
if (state[SDL_SCANCODE_D])
translation.x += ts * speed;
if (state[SDL_SCANCODE_W])
translation.y += ts * speed;
if (state[SDL_SCANCODE_S])
translation.y -= ts * speed;
}
private:
float speed = 2.0f;
};
m_CameraEntity.AddComponent<NativeScriptComponent>().Bind<CameraController>();
m_SecondCamera.AddComponent<NativeScriptComponent>().Bind<CameraController>();
m_EditorCamera = EditorCamera(45.0f, 1.667f, 0.1f, 1000.0f);
m_SceneHierachyPanel.SetContext(m_ActiveScene);
m_State = SDL_GetKeyboardState(nullptr);
}
void EditorLayer::OnDetech()
@ -93,7 +56,8 @@ namespace Hazel
m_FrameBuffer->Resize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y);
m_CameraController.OnResize(m_ViewPortSize.x, m_ViewPortSize.y);
m_ActiveScene->OnViewportResize(m_ViewPortSize.x, m_ViewPortSize.y);
m_EditorCamera.SetViewPortSize(m_ViewPortSize.x, m_ViewPortSize.y);
m_ActiveScene->OnViewportResize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y);
}
@ -101,6 +65,7 @@ namespace Hazel
if (m_ViewportFocused && m_ViewportHovered)
{
m_CameraController.OnUpdate(ts);
m_EditorCamera.OnUpdate(ts);
}
// update Renderer
@ -112,7 +77,7 @@ namespace Hazel
// Renderer2D::BeginScene(m_CameraController.GetCamera());
// update Scene
m_ActiveScene->OnUpdate(ts);
m_ActiveScene->OnUpdateEditor(ts, m_EditorCamera);
// Renderer2D::DrawQuad({0, 0.5f}, {1.0f, 1.0f}, {0.2f, 0.3f, 0.8f, 1.0f});
// Renderer2D::DrawQuad({0, -0.5f}, {1.0f, 1.0f}, {0.8f, 0.2f, 0.2f, 1.0f});
@ -192,22 +157,13 @@ namespace Hazel
// ImGui::MenuItem("Padding", NULL, &opt_padding);
// ImGui::Separator();
if (ImGui::MenuItem("New", "Ctrl+N"))
{
NewScene();
}
if (ImGui::MenuItem("Open...", "Ctrl+O"))
{
OpenScene();
}
if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S"))
{
SaveScene();
}
ImGui::Separator();
if (ImGui::MenuItem("Exit")) { Hazel::Application::Get().Close(); }
ImGui::EndMenu();
@ -216,7 +172,10 @@ namespace Hazel
ImGui::EndMenuBar();
}
// Scene Hierachy Panel
m_SceneHierachyPanel.OnImGuiRender();
// Render Status
{
ImGui::Begin("Render Status");
@ -229,18 +188,11 @@ namespace Hazel
ImGui::Separator();
if (ImGui::Checkbox("Camera A", &m_PrimaryCamera))
{
m_CameraEntity.GetComponent<CameraComponent>().Primary = m_PrimaryCamera;
m_SecondCamera.GetComponent<CameraComponent>().Primary = !m_PrimaryCamera;
}
ImGui::Separator();
ImGui::Text("viewPortSize: (%.2f, %.2f)", m_ViewPortSize.x, m_ViewPortSize.y);
ImGui::End();
}
// ViewPort
{
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {0.0f, 0.0f});
ImGui::Begin("Viewport");
@ -257,46 +209,69 @@ namespace Hazel
ImGui::Image(m_FrameBuffer->GetColorAttachmentID(), {m_ViewPortSize.x, m_ViewPortSize.y}, {0, 1},
{1, 0});
Entity selectedEntity = m_SceneHierachyPanel.GetSelectedEntity();
if (selectedEntity)
{
ImGuizmo::SetOrthographic(false);
ImGuizmo::SetDrawlist();
const float windowWidth = ImGui::GetWindowWidth();
const float windowHeight = ImGui::GetWindowHeight();
const ImVec2 windowPos = ImGui::GetWindowPos();
ImGuizmo::SetRect(windowPos.x,windowPos.y,windowWidth,windowHeight);
// auto cameraEntity = m_ActiveScene->GetPrimaryCameraEntity();
if (m_GizmoType != -1)
{
// const auto& camera = cameraEntity.GetComponent<CameraComponent>().Camera;
auto& tc = selectedEntity.GetComponent<TransformComponent>();
// const glm::mat4& cameraProjection = camera.GetProjection();
// glm::mat4 cameraView = glm::inverse(cameraEntity.GetComponent<TransformComponent>().GetTransform());
glm::mat4 cameraProjection = m_EditorCamera.GetProjection();
glm::mat4 cameraView = m_EditorCamera.GetViewMatrix();
glm::mat4 transform = tc.GetTransform();
bool snap = SDL_GetModState() & SDL_KMOD_CTRL;
float snapValue = 0.5f;
if (m_GizmoType == ImGuizmo::OPERATION::TRANSLATE)
snapValue = 0.25f;
else if (m_GizmoType == ImGuizmo::OPERATION::ROTATE)
snapValue = 15.0f;
else if (m_GizmoType == ImGuizmo::OPERATION::SCALE)
snapValue = 0.25f;
float snapValues[3] = { snapValue, snapValue, snapValue };
if (ImGuizmo::Manipulate(glm::value_ptr(cameraView), glm::value_ptr(cameraProjection), ImGuizmo::OPERATION(m_GizmoType), ImGuizmo::LOCAL,glm::value_ptr(transform), nullptr, snap ? snapValues : nullptr))
{
if (ImGuizmo::IsUsing())
{
glm::vec3 translation, rotation, scale;
Hazel::Math::DecomposeTransform(transform, translation, rotation, scale);
glm::vec3 deltaRotation = rotation - tc.Rotation;
tc.Translation = translation;
tc.Rotation += deltaRotation;
tc.Scale = scale;
}
}
}
}
ImGui::End();
ImGui::PopStyleVar();
}
ImGui::End();
}
}
void EditorLayer::OnEvent(SDL_Event& e)
{
if (m_ViewportFocused && m_ViewportHovered)
{
m_CameraController.OnEvent(e);
}
#define SHORTCUT_NEW (SDL_KMOD_CTRL | SDLK_N)
#define SHORTCUT_OPEN (SDL_KMOD_CTRL | SDLK_O)
#define SHORTCUT_SAVE_ALL (SDL_KMOD_CTRL | SDL_KMOD_SHIFT | SDLK_S)
const auto mod = SDL_GetModState();
const auto ctrl = (mod & SDL_KMOD_CTRL) ? SDL_KMOD_CTRL : 0;
const auto shift = (mod & SDL_KMOD_SHIFT) ? SDL_KMOD_SHIFT : 0;
switch (ctrl | shift | e.key.key)
{
case SHORTCUT_NEW:
NewScene();
break;
case SHORTCUT_OPEN:
OpenScene();
break;
case SHORTCUT_SAVE_ALL:
SaveScene();
break;
default:
break;
}
}
void EditorLayer::SaveScene()
void EditorLayer::SaveScene() const
{
std::string filepath = FileDiaglogs::SaveFile("Hazel Scene (*.scene)\0*.scene\0");
if (!filepath.empty())
@ -326,4 +301,59 @@ namespace Hazel
m_ActiveScene->OnViewportResize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y);
m_SceneHierachyPanel.SetContext(m_ActiveScene);
}
void EditorLayer::ChangeOptMode(unsigned int mode)
{
if (m_ViewportHovered)
m_GizmoType = mode;
}
void EditorLayer::OnEvent(SDL_Event& e)
{
if (m_ViewportFocused && m_ViewportHovered)
{
m_CameraController.OnEvent(e);
m_EditorCamera.OnEvent(e);
}
#define SHORTCUT_NEW (SDL_KMOD_CTRL | SDLK_N)
#define SHORTCUT_OPEN (SDL_KMOD_CTRL | SDLK_O)
#define SHORTCUT_SAVE_ALL (SDL_KMOD_CTRL | SDL_KMOD_SHIFT | SDLK_S)
const auto mod = SDL_GetModState();
const auto ctrl = (mod & SDL_KMOD_CTRL) ? SDL_KMOD_CTRL : 0;
const auto shift = (mod & SDL_KMOD_SHIFT) ? SDL_KMOD_SHIFT : 0;
switch (ctrl | shift | e.key.key)
{
case SHORTCUT_NEW:
NewScene();
break;
case SHORTCUT_OPEN:
OpenScene();
break;
case SHORTCUT_SAVE_ALL:
SaveScene();
break;
// GIZMO
case SDLK_Q:
ChangeOptMode(-1);
break;
case SDLK_W:
ChangeOptMode(ImGuizmo::OPERATION::TRANSLATE);
break;
case SDLK_E:
ChangeOptMode(ImGuizmo::OPERATION::SCALE);
break;
case SDLK_R:
ChangeOptMode(ImGuizmo::OPERATION::ROTATE);
break;
default:
break;
}
}
}

View File

@ -23,10 +23,11 @@ namespace Hazel
virtual void OnImGuiRender() override;
virtual void OnEvent(SDL_Event& e) override;
private:
void SaveScene();
void SaveScene() const;
void OpenScene();
void NewScene();
void ChangeOptMode(unsigned int mode);
private:
OrthographicCameraController m_CameraController;
@ -34,11 +35,7 @@ namespace Hazel
Ref<Texture2D> m_CheckerBoardTexture;
Ref<Scene> m_ActiveScene;
Entity m_SquareEntity;
Entity m_CameraEntity;
Entity m_SecondCamera;
bool m_PrimaryCamera = false;
EditorCamera m_EditorCamera;
glm::vec4 m_BackgroundColor = { 0.2f, 0.2f, 0.2f, 1.0f };
glm::vec4 m_SquareColor = { 0.2f, 0.2f, 0.2f, 1.0f };
@ -49,8 +46,8 @@ namespace Hazel
Ref<FrameBuffer> m_FrameBuffer;
SceneHierachyPanel m_SceneHierachyPanel;
const bool* m_State = nullptr;
int m_GizmoType = 0;
};
}

View File

@ -21,6 +21,7 @@ namespace Hazel
void DrawComponents(Entity entity);
Entity GetSelectedEntity() const { return m_SelectionContext; }
private:
void DrawEntityNode(Entity entity);