From b2c7a459027ac3c7d265aac56ba2a1685899492a Mon Sep 17 00:00:00 2001 From: Atdunbg <979541498@qq.com> Date: Thu, 5 Jun 2025 19:38:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=AE=80=E5=8D=95=E7=9A=84?= =?UTF-8?q?=E5=8F=AF=E8=A7=86=E5=8C=96=E4=B8=89=E7=BB=B4=E6=8E=A7=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=AE=80=E5=8D=95=E7=9A=84=E6=91=84?= =?UTF-8?q?=E5=83=8F=E6=9C=BA=E6=8E=A7=E5=88=B6=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=AE=80=E5=8D=95=E5=85=A8=E5=B1=80=E8=BE=93=E5=85=A5=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 3 + Hazel/CMakeLists.txt | 28 ++- Hazel/src/Hazel.h | 2 +- Hazel/src/Hazel/Core/Core.h | 2 +- Hazel/src/Hazel/Core/Input.cpp | 5 + Hazel/src/Hazel/Core/Input.h | 29 +++ Hazel/src/Hazel/ImGui/ImGuiLayer.cpp | 9 +- Hazel/src/Hazel/Math/Math.cpp | 90 +++++++ Hazel/src/Hazel/Math/Math.h | 17 ++ Hazel/src/Hazel/Renderer/Buffer.cpp | 1 - Hazel/src/Hazel/Renderer/Camera.h | 6 +- Hazel/src/Hazel/Renderer/EditorCamera.cpp | 152 ++++++++++++ Hazel/src/Hazel/Renderer/EditorCamera.h | 80 +++++++ Hazel/src/Hazel/Renderer/Renderer2D.cpp | 29 ++- Hazel/src/Hazel/Renderer/Renderer2D.h | 3 + Hazel/src/Hazel/Renderer/ScenceCamera.cpp | 4 +- Hazel/src/Hazel/Scene/Components.h | 13 +- Hazel/src/Hazel/Scene/Scene.cpp | 30 ++- Hazel/src/Hazel/Scene/Scene.h | 7 +- Hazel/src/Platform/OpenGL/OpenGLBuffer.cpp | 2 +- Hazel/src/Platform/OpenGL/OpenGLBuffer.h | 2 +- .../src/Platform/OpenGL/OpenGLRendererAPI.cpp | 7 +- .../src/Platform/OpenGL/OpenGLVertexArray.cpp | 4 +- Hazel/src/Platform/Windows/WindowInput.cpp | 41 ++++ Hazel/vendor/ImGuizmo | 1 + Sandbox/src/Editor/EditorLayer.cpp | 220 ++++++++++-------- Sandbox/src/Editor/EditorLayer.h | 11 +- .../src/Editor/Panels/SceneHierachyPanel.h | 1 + 28 files changed, 653 insertions(+), 146 deletions(-) create mode 100644 Hazel/src/Hazel/Core/Input.cpp create mode 100644 Hazel/src/Hazel/Core/Input.h create mode 100644 Hazel/src/Hazel/Math/Math.cpp create mode 100644 Hazel/src/Hazel/Math/Math.h create mode 100644 Hazel/src/Hazel/Renderer/EditorCamera.cpp create mode 100644 Hazel/src/Hazel/Renderer/EditorCamera.h create mode 100644 Hazel/src/Platform/Windows/WindowInput.cpp create mode 160000 Hazel/vendor/ImGuizmo diff --git a/.gitmodules b/.gitmodules index 74b1520..14af16a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ [submodule "Hazel/vendor/yaml-cpp"] path = Hazel/vendor/yaml-cpp url = https://github.com/jbeder/yaml-cpp.git +[submodule "Hazel/vendor/ImGuizmo"] + path = Hazel/vendor/ImGuizmo + url = https://github.com/CedricGuillemet/ImGuizmo.git diff --git a/Hazel/CMakeLists.txt b/Hazel/CMakeLists.txt index b4dba14..0e1b385 100644 --- a/Hazel/CMakeLists.txt +++ b/Hazel/CMakeLists.txt @@ -12,12 +12,12 @@ file(GLOB_RECURSE SOURCES "src/**.cpp") # stb_image set(STB_INCLUDE_DIR vendor/stb) include_directories(${SRB_INCLUDE_DIR}/include) -file(GLOB_RECURSE STB ${STB_INCLUDE_DIR}/include/*) +#file(GLOB_RECURSE STB ${STB_INCLUDE_DIR}/include/*) # entt set(ENTT_INCLUDE_DIR vendor/entt) include_directories(${ENTT_INCLUDE_DIR}/include) -file(GLOB_RECURSE ENTT ${ENTT_INCLUDE_DIR}/include/*) +#file(GLOB_RECURSE ENTT ${ENTT_INCLUDE_DIR}/include/*) # imgui set(IMGUI_INCLUDE_DIR vendor/imgui) @@ -26,15 +26,20 @@ file(GLOB IMGUI ${IMGUI_INCLUDE_DIR}/*.cpp ${IMGUI_INCLUDE_DIR}/backends/imgui_impl_opengl3.cpp ${IMGUI_INCLUDE_DIR}/backends/imgui_impl_sdl3.cpp) -set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries" FORCE) -add_subdirectory(vendor/SDL) -set(SDL3_SHARED ON CACHE BOOL "Build SDL as shared library" FORCE) +# ImGuizmo +set(IMGUIZMO_INCLUDE_DIR vendor/ImGuizmo) +include_directories(${IMGUIZMO_INCLUDE_DIR}) +file(GLOB IMGUIZMO ${IMGUIZMO_INCLUDE_DIR}/*.cpp) -add_library(${PROJECT_NAME} SHARED + +# set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries" FORCE) +add_subdirectory(vendor/SDL) +#set(SDL3_SHARED ON CACHE BOOL "Build SDL as shared library" FORCE) + +add_library(${PROJECT_NAME} STATIC ${SOURCES} - ${STB} - ${ENTT} ${IMGUI} + ${IMGUIZMO} ) target_include_directories(${PROJECT_NAME} @@ -43,6 +48,7 @@ target_include_directories(${PROJECT_NAME} ${STB_INCLUDE_DIR} ${IMGUI_INCLUDE_DIR} ${ENTT_INCLUDE_DIR} + ${IMGUIZMO_INCLUDE_DIR} ) @@ -53,15 +59,17 @@ target_link_libraries(${PROJECT_NAME} PUBLIC opengl32 glm::glm yaml-cpp::yaml-cpp + ) -target_compile_definitions(${PROJECT_NAME} PRIVATE HZ_BUILD_DLL STB_IMAGE_IMPLEMENTATION HZ_PROFILE)# 编译DLL时定义 +# target_compile_definitions(${PROJECT_NAME} PRIVATE HZ_BUILD_DLL IMGUI_API=__declspec\(dllexport\) STB_IMAGE_IMPLEMENTATION)# 编译DLL时定义 +target_compile_definitions(${PROJECT_NAME} PRIVATE STB_IMAGE_IMPLEMENTATION) if(CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_definitions(${PROJECT_NAME} PUBLIC HZ_PROFILE)# 编译DLL时定义 endif () if(WIN32) - target_compile_definitions(${PROJECT_NAME} PUBLIC HZ_PLATFORM_WINDOWS IMGUI_API=__declspec\(dllexport\))# 编译DLL时定义 + target_compile_definitions(${PROJECT_NAME} PUBLIC HZ_PLATFORM_WINDOWS)# 编译DLL时定义 set(CMAKE_SHARED_LIBRARY_PREFIX "") endif () diff --git a/Hazel/src/Hazel.h b/Hazel/src/Hazel.h index b65a0ca..3be690e 100644 --- a/Hazel/src/Hazel.h +++ b/Hazel/src/Hazel.h @@ -1,7 +1,7 @@ #pragma once -#define STB_IMAGE_IMPLEMENTATION +// #define STB_IMAGE_IMPLEMENTATION // For use by Hazel Applications #include "Hazel/Core/Application.h" diff --git a/Hazel/src/Hazel/Core/Core.h b/Hazel/src/Hazel/Core/Core.h index ab2147d..f46b915 100644 --- a/Hazel/src/Hazel/Core/Core.h +++ b/Hazel/src/Hazel/Core/Core.h @@ -4,7 +4,7 @@ #ifdef HZ_BUILD_DLL #define HAZEL_API __declspec(dllexport) #else - #define HAZEL_API __declspec(dllimport) + #define HAZEL_API #endif #else diff --git a/Hazel/src/Hazel/Core/Input.cpp b/Hazel/src/Hazel/Core/Input.cpp new file mode 100644 index 0000000..0074c05 --- /dev/null +++ b/Hazel/src/Hazel/Core/Input.cpp @@ -0,0 +1,5 @@ +// +// Created by sfd on 25-6-5. +// + +#include "Input.h" diff --git a/Hazel/src/Hazel/Core/Input.h b/Hazel/src/Hazel/Core/Input.h new file mode 100644 index 0000000..bd6fbe2 --- /dev/null +++ b/Hazel/src/Hazel/Core/Input.h @@ -0,0 +1,29 @@ +// +// Created by sfd on 25-6-5. +// + +#ifndef INPUT_H +#define INPUT_H +#include + +#include "Core.h" + +namespace Hazel +{ + class HAZEL_API Input{ + public: + virtual ~Input() = default; + + static bool IsKeyPressed(int key); + + static bool IsMouseButtonPressed(int button); + static std::pair GetMousePosition(); + + static float GetMouseX(); + static float GetMouseY(); + }; +} + + + +#endif //INPUT_H diff --git a/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp b/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp index 9beb8eb..ed023fe 100644 --- a/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp +++ b/Hazel/src/Hazel/ImGui/ImGuiLayer.cpp @@ -9,7 +9,7 @@ #include #include #include - +#include "ImGuizmo.h" namespace Hazel { @@ -73,10 +73,9 @@ namespace Hazel void ImGuiLayer::OnEvent(SDL_Event& e) { - // if (m_BlockEvent) - // { + // if (m_BlockEvent){} + ImGui_ImplSDL3_ProcessEvent(&e); - // } } void ImGuiLayer::OnImGuiRender() @@ -89,7 +88,7 @@ namespace Hazel ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL3_NewFrame(); ImGui::NewFrame(); - + ImGuizmo::BeginFrame(); } void ImGuiLayer::End() diff --git a/Hazel/src/Hazel/Math/Math.cpp b/Hazel/src/Hazel/Math/Math.cpp new file mode 100644 index 0000000..3bcfeaf --- /dev/null +++ b/Hazel/src/Hazel/Math/Math.cpp @@ -0,0 +1,90 @@ +// +// Created by sfd on 25-6-4. +// + +#include "Math.h" + +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + + +namespace Hazel::Math +{ + bool DecomposeTransform(const glm::mat4& transform, glm::vec3& translation, glm::vec3& rotation, glm::vec3& scale) + { + // From glm::decompose in matrix_decompose.inl + + using namespace glm; + using T = float; + + mat4 LocalMatrix(transform); + + // Normalize the matrix. + if (epsilonEqual(LocalMatrix[3][3], static_cast(0), epsilon())) + return false; + + // First, isolate perspective. This is the messiest. + if ( + epsilonNotEqual(LocalMatrix[0][3], static_cast(0), epsilon()) || + epsilonNotEqual(LocalMatrix[1][3], static_cast(0), epsilon()) || + epsilonNotEqual(LocalMatrix[2][3], static_cast(0), epsilon())) + { + // Clear the perspective partition + LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] = static_cast(0); + LocalMatrix[3][3] = static_cast(1); + } + + // Next take care of translation (easy). + translation = vec3(LocalMatrix[3]); + LocalMatrix[3] = vec4(0, 0, 0, LocalMatrix[3].w); + + vec3 Row[3], Pdum3; + + // Now get scale and shear. + for (length_t i = 0; i < 3; ++i) + for (length_t j = 0; j < 3; ++j) + Row[i][j] = LocalMatrix[i][j]; + + // Compute X scale factor and normalize first row. + scale.x = length(Row[0]); + Row[0] = detail::scale(Row[0], static_cast(1)); + scale.y = length(Row[1]); + Row[1] = detail::scale(Row[1], static_cast(1)); + scale.z = length(Row[2]); + Row[2] = detail::scale(Row[2], static_cast(1)); + + + + // At this point, the matrix (in rows[]) is orthonormal. + // Check for a coordinate system flip. If the determinant + // is -1, then negate the matrix and the scaling factors. +#if 0 + Pdum3 = cross(Row[1], Row[2]); // v3Cross(row[1], row[2], Pdum3); + if (dot(Row[0], Pdum3) < 0) + { + for (length_t i = 0; i < 3; i++) + { + scale[i] *= static_cast(-1); + Row[i] *= static_cast(-1); + } + } +#endif + + rotation.y = asin(-Row[0][2]); + if (cos(rotation.y) != 0) + { + rotation.x = atan2(Row[1][2], Row[2][2]); + rotation.z = atan2(Row[0][1], Row[0][0]); + } + else + { + rotation.x = atan2(-Row[2][0], Row[1][1]); + rotation.z = 0; + } + + + return true; + } +} diff --git a/Hazel/src/Hazel/Math/Math.h b/Hazel/src/Hazel/Math/Math.h new file mode 100644 index 0000000..4e66094 --- /dev/null +++ b/Hazel/src/Hazel/Math/Math.h @@ -0,0 +1,17 @@ +// +// Created by sfd on 25-6-4. +// + +#ifndef MATH_H +#define MATH_H + +#include + +namespace Hazel +{ + namespace Math + { + bool DecomposeTransform(const glm::mat4& transform, glm::vec3& outTranslation, glm::vec3& outRotation, glm::vec3& outScale); + } +} +#endif //MATH_H \ No newline at end of file diff --git a/Hazel/src/Hazel/Renderer/Buffer.cpp b/Hazel/src/Hazel/Renderer/Buffer.cpp index 3385811..2f610fb 100644 --- a/Hazel/src/Hazel/Renderer/Buffer.cpp +++ b/Hazel/src/Hazel/Renderer/Buffer.cpp @@ -57,7 +57,6 @@ namespace Hazel return nullptr; case RendererAPI::API::OPENGL: return std::make_shared(indices, count); - break; default: break; } diff --git a/Hazel/src/Hazel/Renderer/Camera.h b/Hazel/src/Hazel/Renderer/Camera.h index 313f6cd..da3ce96 100644 --- a/Hazel/src/Hazel/Renderer/Camera.h +++ b/Hazel/src/Hazel/Renderer/Camera.h @@ -11,12 +11,12 @@ namespace Hazel { class HAZEL_API Camera{ public: Camera() = default; - Camera(const glm::mat4& projection) : m_Projection(projection) {} + Camera(const glm::mat4& projection) : m_ProjectionMatrix(projection) {} virtual ~Camera() = default; - const glm::mat4& GetProjection() const { return m_Projection; } + const glm::mat4& GetProjection() const { return m_ProjectionMatrix; } protected: - glm::mat4 m_Projection = glm::mat4(1.0f); + glm::mat4 m_ProjectionMatrix = glm::mat4(1.0f); }; } diff --git a/Hazel/src/Hazel/Renderer/EditorCamera.cpp b/Hazel/src/Hazel/Renderer/EditorCamera.cpp new file mode 100644 index 0000000..cfe7a7c --- /dev/null +++ b/Hazel/src/Hazel/Renderer/EditorCamera.cpp @@ -0,0 +1,152 @@ +// +// Created by sfd on 25-6-5. +// + +#include "EditorCamera.h" + +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +#include "glm/detail/type_quat.hpp" +#include "glm/ext/matrix_clip_space.hpp" +#include "glm/gtx/quaternion.hpp" + +namespace Hazel +{ + EditorCamera::EditorCamera(float fov, float aspectRatio, float nearClip, float farClip) + : m_FOV(fov), m_AspectRatio(aspectRatio), m_NearClip(nearClip), m_FarClip(farClip), Camera(glm::perspective(glm::radians(fov), aspectRatio, nearClip, farClip)) + { + m_Position = CalculatePosition(); + UpdateView(); + } + + void EditorCamera::UpdateProjection() + { + m_AspectRatio = m_ViewportWidth / m_ViewportHeight; + m_ProjectionMatrix = glm::perspective(glm::radians(m_FOV), m_AspectRatio, m_NearClip, m_FarClip); + } + + void EditorCamera::UpdateView() + { + // m_Yaw = m_Pitch = 0.0f; // Lock the camera's rotation + m_Position = CalculatePosition(); + + glm::quat orientation = GetOrientation(); + m_ViewMatrix = glm::translate(glm::mat4(1.0f), m_Position) * glm::toMat4(orientation); + m_ViewMatrix = glm::inverse(m_ViewMatrix); + } + + std::pair EditorCamera::PanSpeed() const + { + float x = std::min(m_ViewportWidth / 1000.0f, 2.4f); // max = 2.4f + float xFactor = 0.0366f * (x * x) - 0.1778f * x + 0.3021f; + + float y = std::min(m_ViewportHeight / 1000.0f, 2.4f); // max = 2.4f + float yFactor = 0.0366f * (y * y) - 0.1778f * y + 0.3021f; + + return { xFactor, yFactor }; + } + + float EditorCamera::RotationSpeed() const + { + return 0.8f; + } + + float EditorCamera::ZoomSpeed() const + { + float distance = m_Distance * 0.2f; + distance = std::max(distance, 0.0f); + float speed = distance * distance; + speed = std::min(speed, 100.0f); // max speed = 100 + return speed; + } + + void EditorCamera::OnUpdate(TimeStep ts) + { + if (Input::IsKeyPressed(SDL_SCANCODE_LALT)) + { + const glm::vec2& mouse{ Input::GetMouseX(), Input::GetMouseY() }; + const glm::vec2 delta = (mouse - m_InitialMousePosition) * 0.003f; + m_InitialMousePosition = mouse; + + if (Input::IsMouseButtonPressed(SDL_BUTTON_MIDDLE)) + MousePan(delta); + else if (Input::IsMouseButtonPressed(SDL_BUTTON_LEFT)) + MouseRotate(delta); + else if (Input::IsMouseButtonPressed(SDL_BUTTON_RIGHT)) + MouseZoom(delta.y); + } + + UpdateView(); + } + + void EditorCamera::OnEvent(SDL_Event& e) + { + OnMouseScroll(e); + } + + bool EditorCamera::OnMouseScroll(SDL_Event& e) + { + if (e.type == SDL_EVENT_MOUSE_WHEEL) + { + const float delta = e.motion.y * 0.1f; + MouseZoom(delta); + UpdateView(); + + return true; + } + return false; + } + + void EditorCamera::MousePan(const glm::vec2& delta) + { + auto [xSpeed, ySpeed] = PanSpeed(); + m_FocalPoint += -GetRightDirection() * delta.x * xSpeed * m_Distance; + m_FocalPoint += GetUpDirection() * delta.y * ySpeed * m_Distance; + } + + void EditorCamera::MouseRotate(const glm::vec2& delta) + { + float yawSign = GetUpDirection().y < 0 ? -1.0f : 1.0f; + m_Yaw += yawSign * delta.x * RotationSpeed(); + m_Pitch += delta.y * RotationSpeed(); + } + + void EditorCamera::MouseZoom(float delta) + { + m_Distance -= delta * ZoomSpeed(); + if (m_Distance < 1.0f) + { + m_FocalPoint += GetForwardDirection(); + m_Distance = 1.0f; + } + } + + glm::vec3 EditorCamera::GetUpDirection() const + { + return glm::rotate(GetOrientation(), glm::vec3(0.0f, 1.0f, 0.0f)); + } + + glm::vec3 EditorCamera::GetRightDirection() const + { + return glm::rotate(GetOrientation(), glm::vec3(1.0f, 0.0f, 0.0f)); + } + + glm::vec3 EditorCamera::GetForwardDirection() const + { + auto rotate = glm::rotate(GetOrientation(), glm::vec3(0.0f, 0.0f, -1.0f)); + return rotate; + } + + glm::vec3 EditorCamera::CalculatePosition() const + { + return m_FocalPoint - GetForwardDirection() * m_Distance; + } + + glm::quat EditorCamera::GetOrientation() const + { + return glm::quat(glm::vec3(-m_Pitch, -m_Yaw, 0.0f)); + } + +} diff --git a/Hazel/src/Hazel/Renderer/EditorCamera.h b/Hazel/src/Hazel/Renderer/EditorCamera.h new file mode 100644 index 0000000..1333a88 --- /dev/null +++ b/Hazel/src/Hazel/Renderer/EditorCamera.h @@ -0,0 +1,80 @@ +// +// Created by sfd on 25-6-5. +// + +#ifndef EDITORCAMERA_H +#define EDITORCAMERA_H +#include +#include + +#include "Camera.h" +#include + + +namespace Hazel +{ + class EditorCamera : public Camera + { + public: + EditorCamera() = default; + EditorCamera(float fov, float aspectRatio, float nearClip, float farClip); + + void OnUpdate(TimeStep ts); + void OnEvent(SDL_Event& e); + + inline float GetDistance() const { return m_Distance; } + inline void SetDistance(const float distance) { m_Distance = distance; } + + inline void SetViewPortSize(const float width, const float height) + { + m_ViewportWidth = width; + m_ViewportHeight = height; + UpdateProjection(); + } + + const glm::mat4& GetViewMatrix() const { return m_ViewMatrix; } + glm::mat4 GetViewProjection() const { return m_ProjectionMatrix * m_ViewMatrix; } + + glm::vec3 GetUpDirection() const; + glm::vec3 GetRightDirection() const; + glm::vec3 GetForwardDirection() const; + glm::vec3 GetPosition() const { return m_Position; } + glm::quat GetOrientation() const; + + float GetPitch() const { return m_Pitch; } + float GetYaw() const { return m_Yaw; } + + private: + void UpdateProjection(); + void UpdateView(); + + bool OnMouseScroll(SDL_Event& e); + + void MousePan(const glm::vec2& delta); + void MouseRotate(const glm::vec2& delta); + void MouseZoom(float delta); + + glm::vec3 CalculatePosition() const; + + std::pair PanSpeed() const; + float RotationSpeed() const; + float ZoomSpeed() const; + + private: + float m_FOV = 45.0f, m_AspectRatio = 1.778f, m_NearClip = 0.1f, m_FarClip = 1000.0f; + + glm::mat4 m_ViewMatrix; + glm::vec3 m_Position = {0.0f, 0.0f, 0.0f}; + glm::vec3 m_FocalPoint = {0.0f, 0.0f, 0.0f}; + + glm::vec2 m_InitialMousePosition = {0.0f, 0.0f}; + + float m_Distance = 10.0f; + float m_Pitch = 0.0f, m_Yaw = 0.0f; + + float m_ViewportWidth = 1280, m_ViewportHeight = 720; + }; +} + + +#endif //EDITORCAMERA_H diff --git a/Hazel/src/Hazel/Renderer/Renderer2D.cpp b/Hazel/src/Hazel/Renderer/Renderer2D.cpp index 4759dc3..fa3f76a 100644 --- a/Hazel/src/Hazel/Renderer/Renderer2D.cpp +++ b/Hazel/src/Hazel/Renderer/Renderer2D.cpp @@ -137,10 +137,19 @@ namespace Hazel s_Data.TextureShader->Bind(); s_Data.TextureShader->SetMat4("u_ViewProjection", viewProjection); - s_Data.QuadIndexCount = 0; - s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase; + StartBatch(); + } - s_Data.TextureSlotIndex = 1; + void Renderer2D::BeginScene(const EditorCamera& camera) + { + HZ_PROFILE_FUNCTION(); + + const glm::mat4 vieweProjection = camera.GetViewProjection(); + + s_Data.TextureShader->Bind(); + s_Data.TextureShader->SetMat4("u_ViewProjection", vieweProjection); + + StartBatch(); } void Renderer2D::BeginScene(const OrthographicCamera& camera) @@ -149,10 +158,7 @@ namespace Hazel s_Data.TextureShader->Bind(); s_Data.TextureShader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix()); - s_Data.QuadIndexCount = 0; - s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase; - - s_Data.TextureSlotIndex = 1; + StartBatch(); } void Renderer2D::EndScene() @@ -170,11 +176,20 @@ namespace Hazel { s_Data.TextureSlots[i]->Bind(i); } + if (s_Data.TextureSlotIndex == 0) RendererCommand::DrawIndexed(s_Data.QuadVertexArray, s_Data.QuadIndexCount); s_Data.Stats.DrawCalls++; } + void Renderer2D::StartBatch() + { + s_Data.QuadIndexCount = 0; + s_Data.QuadVertexBufferPtr = s_Data.QuadVertexBufferBase; + + s_Data.TextureSlotIndex = 1; + } + void Renderer2D::Shutdown() { HZ_PROFILE_FUNCTION(); diff --git a/Hazel/src/Hazel/Renderer/Renderer2D.h b/Hazel/src/Hazel/Renderer/Renderer2D.h index c109bc5..c1cc946 100644 --- a/Hazel/src/Hazel/Renderer/Renderer2D.h +++ b/Hazel/src/Hazel/Renderer/Renderer2D.h @@ -6,6 +6,7 @@ #define RENDERER2D_H #include "Camera.h" +#include "EditorCamera.h" #include "OrthographicCamera.h" #include "SubTexture2D.h" #include "Texture.h" @@ -27,10 +28,12 @@ namespace Hazel static void Init(); static void BeginScene(const Camera& camera, const glm::mat4& tranform); + static void BeginScene(const EditorCamera& camera); // TODO: remove this static void BeginScene(const OrthographicCamera& camera); // TODO: remove this static void EndScene(); static void Flush(); + static void StartBatch(); static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color); static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color); diff --git a/Hazel/src/Hazel/Renderer/ScenceCamera.cpp b/Hazel/src/Hazel/Renderer/ScenceCamera.cpp index 27036c8..71c5a75 100644 --- a/Hazel/src/Hazel/Renderer/ScenceCamera.cpp +++ b/Hazel/src/Hazel/Renderer/ScenceCamera.cpp @@ -44,7 +44,7 @@ namespace Hazel { if (m_ProjectionType == ProjectionType::Perspective) { - m_Projection = glm::perspective(m_PerspectiveFOV, m_AspectRatio, m_PerspectiveNear, m_PerspectiveFar); + m_ProjectionMatrix = glm::perspective(m_PerspectiveFOV, m_AspectRatio, m_PerspectiveNear, m_PerspectiveFar); } else { @@ -54,7 +54,7 @@ namespace Hazel const float orthoTop = m_OrthographicSize * 0.5f; - m_Projection = glm::ortho(orthoLeft, orthoRight, orthoBottom, orthoTop, m_OrthographicNear, + m_ProjectionMatrix = glm::ortho(orthoLeft, orthoRight, orthoBottom, orthoTop, m_OrthographicNear, m_OrthographicFar); } } diff --git a/Hazel/src/Hazel/Scene/Components.h b/Hazel/src/Hazel/Scene/Components.h index 2998160..b165abd 100644 --- a/Hazel/src/Hazel/Scene/Components.h +++ b/Hazel/src/Hazel/Scene/Components.h @@ -4,12 +4,15 @@ #ifndef COMPONENTS_H #define COMPONENTS_H -#include #include #include #include "ScriptableEntity.h" + +#define GLM_ENABLE_EXPERIMENTAL +#include #include "glm/glm.hpp" +#include "glm/gtx/quaternion.hpp" namespace Hazel { @@ -28,9 +31,11 @@ namespace Hazel glm::mat4 GetTransform() const { - glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), Rotation.x, glm::vec3(1.0f, 0.0f, 0.0f)) - * glm::rotate(glm::mat4(1.0f), Rotation.y, glm::vec3(0.0f, 1.0f, 0.0f)) - * glm::rotate(glm::mat4(1.0f), Rotation.z, glm::vec3(0.0f, 0.0f, 1.0f)); + // glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), Rotation.x, glm::vec3(1.0f, 0.0f, 0.0f)) + // * glm::rotate(glm::mat4(1.0f), Rotation.y, glm::vec3(0.0f, 1.0f, 0.0f)) + // * glm::rotate(glm::mat4(1.0f), Rotation.z, glm::vec3(0.0f, 0.0f, 1.0f)); + + const glm::mat4 rotation = glm::toMat4(glm::quat(Rotation)); return glm::translate(glm::mat4(1.0f), Translation) * rotation * glm::scale(glm::mat4(1.0f), Scale); } diff --git a/Hazel/src/Hazel/Scene/Scene.cpp b/Hazel/src/Hazel/Scene/Scene.cpp index 3094b0d..172179f 100644 --- a/Hazel/src/Hazel/Scene/Scene.cpp +++ b/Hazel/src/Hazel/Scene/Scene.cpp @@ -34,7 +34,7 @@ namespace Hazel m_Registry.destroy(entity); } - void Scene::OnUpdate(TimeStep& ts) + void Scene::OnUpdateRuntime(TimeStep& ts) { // Update scripts @@ -89,6 +89,22 @@ namespace Hazel } } + + void Scene::OnUpdateEditor(TimeStep & ts, const EditorCamera & camera) + { + Renderer2D::BeginScene(camera); + + auto group = m_Registry.group(entt::get); + for (auto entity : group) + { + auto [transform, sprite] = group.get(entity); + + Renderer2D::DrawQuad(transform.GetTransform(), sprite.Color); + } + + Renderer2D::EndScene(); + } + void Scene::OnViewportResize(uint32_t width, uint32_t height) { m_ViewportWidth = width; @@ -108,6 +124,18 @@ namespace Hazel } + Entity Scene::GetPrimaryCameraEntity() + { + auto view = m_Registry.view(); + for (auto entity : view) + { + auto& cameraComponent = view.get(entity); + if (cameraComponent.Primary) + return Entity{entity, this}; + } + return {}; + } + template void Scene::OnComponentAdded(Entity entity, T& component) { diff --git a/Hazel/src/Hazel/Scene/Scene.h b/Hazel/src/Hazel/Scene/Scene.h index 1c8d1bb..dd194dc 100644 --- a/Hazel/src/Hazel/Scene/Scene.h +++ b/Hazel/src/Hazel/Scene/Scene.h @@ -7,6 +7,7 @@ #include +#include #include "entt.hpp" #include "Hazel/Core/Core.h" @@ -26,9 +27,13 @@ namespace Hazel void DestoryEntity(Entity entity); - void OnUpdate(TimeStep& ts); + void OnUpdateRuntime(TimeStep& ts); + + void OnUpdateEditor(TimeStep& ts, const EditorCamera& camera); + void OnViewportResize(uint32_t width, uint32_t height); + Entity GetPrimaryCameraEntity(); private: template diff --git a/Hazel/src/Platform/OpenGL/OpenGLBuffer.cpp b/Hazel/src/Platform/OpenGL/OpenGLBuffer.cpp index 61712c6..c2f2bc9 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLBuffer.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLBuffer.cpp @@ -57,7 +57,7 @@ namespace Hazel //////////////////////////////////////////////////////////////////// ////////////////////// IndexBuffer /////////////////////////// //////////////////////////////////////////////////////////////////// - OpenGLIndexBuffer::OpenGLIndexBuffer(uint32_t* indices, uint32_t count) : m_Count(count) + OpenGLIndexBuffer::OpenGLIndexBuffer(const uint32_t* indices, const uint32_t count) : m_Count(count) { HZ_PROFILE_FUNCTION(); glCreateBuffers(1, &m_RendererID); diff --git a/Hazel/src/Platform/OpenGL/OpenGLBuffer.h b/Hazel/src/Platform/OpenGL/OpenGLBuffer.h index 82d1b45..f905c91 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLBuffer.h +++ b/Hazel/src/Platform/OpenGL/OpenGLBuffer.h @@ -28,7 +28,7 @@ namespace Hazel class OpenGLIndexBuffer : public IndexBuffer { public: - OpenGLIndexBuffer(uint32_t* indices, uint32_t count); + OpenGLIndexBuffer(const uint32_t* indices, uint32_t count); virtual ~OpenGLIndexBuffer(); virtual void Bind() const override; virtual void Unbind() const override; diff --git a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp index 6b9d205..c2968cf 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLRendererAPI.cpp @@ -33,11 +33,10 @@ namespace Hazel glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - void OpenGLRendererAPI::DrawIndexed(const std::shared_ptr& vertexArray, uint32_t indexCount) + void OpenGLRendererAPI::DrawIndexed(const std::shared_ptr& vertexArray, const uint32_t indexCount) { - // uint32_t count = indexCount == 0 ? vertexArray->GetIndexBuffer()->GetCount() : indexCount; - uint32_t count = indexCount ? indexCount : vertexArray->GetIndexBuffer()->GetCount(); - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0); + const uint32_t count = indexCount ? indexCount : vertexArray->GetIndexBuffer()->GetCount(); + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, nullptr); glBindTexture(GL_TEXTURE_2D, 0); } } diff --git a/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp b/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp index 5640b78..a2f5d11 100644 --- a/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp +++ b/Hazel/src/Platform/OpenGL/OpenGLVertexArray.cpp @@ -71,12 +71,12 @@ namespace Hazel uint32_t index = 0; - for (auto& element : vertexBuffer->GetLayout()) + for (const auto& element : vertexBuffer->GetLayout()) { glEnableVertexAttribArray(index); glVertexAttribPointer(index, element.GetComponentCount(), ShaderDataTypeToOpenGLBaseType(element.Type), element.Normalized ? GL_TRUE : GL_FALSE, vertexBuffer->GetLayout().GetStride(), - reinterpret_cast(element.Offset)); + (void*)element.Offset); index ++; } diff --git a/Hazel/src/Platform/Windows/WindowInput.cpp b/Hazel/src/Platform/Windows/WindowInput.cpp new file mode 100644 index 0000000..d19c667 --- /dev/null +++ b/Hazel/src/Platform/Windows/WindowInput.cpp @@ -0,0 +1,41 @@ +// +// Created by sfd on 25-6-5. +// + +#include +#include +#include + +namespace Hazel +{ + bool Input::IsKeyPressed(const int key) + { + const auto state = SDL_GetKeyboardState(nullptr); + + return state[key]; + } + + bool Input::IsMouseButtonPressed(const int button) + { + const auto mod = SDL_GetMouseState(nullptr, nullptr); + return mod & SDL_BUTTON_MASK(button); + } + + std::pair Input::GetMousePosition() + { + float xpos, ypos; + SDL_GetMouseState(&xpos, &ypos); + + return {xpos, ypos}; + } + + float Input::GetMouseX() + { + return GetMousePosition().first; + } + + float Input::GetMouseY() + { + return GetMousePosition().second; + } +} diff --git a/Hazel/vendor/ImGuizmo b/Hazel/vendor/ImGuizmo new file mode 160000 index 0000000..2310acd --- /dev/null +++ b/Hazel/vendor/ImGuizmo @@ -0,0 +1 @@ +Subproject commit 2310acda820d7383d4c4884b7945ada92cd16a47 diff --git a/Sandbox/src/Editor/EditorLayer.cpp b/Sandbox/src/Editor/EditorLayer.cpp index 2e5f70f..b059c52 100644 --- a/Sandbox/src/Editor/EditorLayer.cpp +++ b/Sandbox/src/Editor/EditorLayer.cpp @@ -5,10 +5,15 @@ #include "EditorLayer.h" #include +#include #include +#include +#include #include #include +#include "glm/gtx/matrix_decompose.hpp" + namespace Hazel { EditorLayer::EditorLayer() @@ -31,51 +36,9 @@ namespace Hazel m_ActiveScene = CreateRef(); - // Entity - m_SquareEntity = m_ActiveScene->CreateEntity("Square A"); - m_SquareEntity.AddComponent(glm::vec4{0.2f, 0.3f, 0.8f, 1.0f}); - - auto redSquare = m_ActiveScene->CreateEntity("Square B"); - redSquare.AddComponent(glm::vec4{1.0f, 0.0f, 0.0f, 1.0f}); - - - m_CameraEntity = m_ActiveScene->CreateEntity("Camera A"); - m_CameraEntity.AddComponent(); - m_PrimaryCamera = true; - - - m_SecondCamera = m_ActiveScene->CreateEntity("Camera B"); - m_SecondCamera.AddComponent(); - m_SecondCamera.GetComponent().Primary = false; - - - class CameraController : public ScriptableEntity - { - public: - void OnUpdate(const TimeStep ts) override - { - auto& translation = GetComponent().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().Bind(); - m_SecondCamera.AddComponent().Bind(); - + 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().Primary = m_PrimaryCamera; - m_SecondCamera.GetComponent().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().Camera; + auto& tc = selectedEntity.GetComponent(); + + + // const glm::mat4& cameraProjection = camera.GetProjection(); + // glm::mat4 cameraView = glm::inverse(cameraEntity.GetComponent().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; + } + } + } diff --git a/Sandbox/src/Editor/EditorLayer.h b/Sandbox/src/Editor/EditorLayer.h index 290bf79..944d297 100644 --- a/Sandbox/src/Editor/EditorLayer.h +++ b/Sandbox/src/Editor/EditorLayer.h @@ -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 m_CheckerBoardTexture; Ref 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 m_FrameBuffer; SceneHierachyPanel m_SceneHierachyPanel; - const bool* m_State = nullptr; + int m_GizmoType = 0; }; } diff --git a/Sandbox/src/Editor/Panels/SceneHierachyPanel.h b/Sandbox/src/Editor/Panels/SceneHierachyPanel.h index df8fe85..3fe48b2 100644 --- a/Sandbox/src/Editor/Panels/SceneHierachyPanel.h +++ b/Sandbox/src/Editor/Panels/SceneHierachyPanel.h @@ -21,6 +21,7 @@ namespace Hazel void DrawComponents(Entity entity); + Entity GetSelectedEntity() const { return m_SelectionContext; } private: void DrawEntityNode(Entity entity);