From ea59c82f35037309f0324f6df21f1041c9ae9129 Mon Sep 17 00:00:00 2001 From: Atdunbg <979541498@qq.com> Date: Wed, 18 Jun 2025 20:59:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9C=BA=E6=99=AF=E5=9C=A8?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=E6=97=B6=E4=BC=9A=E4=B8=B4=E6=97=B6=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E4=B8=80=E4=B8=AA=E5=9C=BA=E6=99=AF=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=85=8B=E9=9A=86=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Hazel/src/Hazel/Renderer/ScenceCamera.h | 2 +- Hazel/src/Hazel/Scene/Components.h | 12 ++- Hazel/src/Hazel/Scene/Entity.h | 14 +++- Hazel/src/Hazel/Scene/Scene.cpp | 90 ++++++++++++++++++++++- Hazel/src/Hazel/Scene/Scene.h | 8 +- Hazel/src/Hazel/Scene/SceneSerializer.cpp | 12 ++- Sandbox/src/Editor/EditorLayer.cpp | 66 +++++++++++++---- Sandbox/src/Editor/EditorLayer.h | 3 + 8 files changed, 185 insertions(+), 22 deletions(-) diff --git a/Hazel/src/Hazel/Renderer/ScenceCamera.h b/Hazel/src/Hazel/Renderer/ScenceCamera.h index 4a52e38..f2616a9 100644 --- a/Hazel/src/Hazel/Renderer/ScenceCamera.h +++ b/Hazel/src/Hazel/Renderer/ScenceCamera.h @@ -44,7 +44,7 @@ namespace Hazel ProjectionType GetProjectionType() const { return m_ProjectionType; } - void SetProjectionType(const ProjectionType type) { m_ProjectionType = type; RecalculateProjection(); } + void SetProjectionType(const ProjectionType type) { m_ProjectionType = type; } private: void RecalculateProjection(); private: diff --git a/Hazel/src/Hazel/Scene/Components.h b/Hazel/src/Hazel/Scene/Components.h index 108ecda..b533fec 100644 --- a/Hazel/src/Hazel/Scene/Components.h +++ b/Hazel/src/Hazel/Scene/Components.h @@ -7,7 +7,6 @@ #include #include -#include "ScriptableEntity.h" #define GLM_ENABLE_EXPERIMENTAL #include @@ -15,9 +14,18 @@ #include "glm/glm.hpp" #include "glm/gtx/quaternion.hpp" +#include +#include namespace Hazel { + struct IDComponent + { + UUID ID; + IDComponent() = default; + IDComponent(const UUID& uuid) : ID(uuid) {} + IDComponent(const IDComponent&) = default; + }; struct TransformComponent { @@ -77,6 +85,8 @@ namespace Hazel CameraComponent(const CameraComponent&) = default; }; + // forward declaration + class ScriptableEntity; struct NativeScriptComponent { ScriptableEntity* Instance = nullptr; diff --git a/Hazel/src/Hazel/Scene/Entity.h b/Hazel/src/Hazel/Scene/Entity.h index 3199319..e26fbbd 100644 --- a/Hazel/src/Hazel/Scene/Entity.h +++ b/Hazel/src/Hazel/Scene/Entity.h @@ -5,8 +5,9 @@ #ifndef ENTITY_H #define ENTITY_H #include - +#include #include "Scene.h" +#include "Components.h" @@ -33,6 +34,14 @@ namespace Hazel return component; } + template + T& AddOrRelpaceComponent(Args&&... args) + { + T& component = m_Scene->m_Registry.emplace_or_replace(m_EntityHandle, std::forward(args)...); + m_Scene->OnComponentAdded(*this, component); + return component; + } + template T& GetComponent() { @@ -73,6 +82,9 @@ namespace Hazel bool operator==(const Entity& other) const { return m_EntityHandle == other.m_EntityHandle && m_Scene == other.m_Scene; } bool operator!=(const Entity& other) const { return !(*this==other); } + UUID GetUUID() { return GetComponent().ID; } + const std::string& GetName() { return GetComponent().Tag; } + private: entt::entity m_EntityHandle{ entt::null }; Scene* m_Scene = nullptr; diff --git a/Hazel/src/Hazel/Scene/Scene.cpp b/Hazel/src/Hazel/Scene/Scene.cpp index d74346e..1416a73 100644 --- a/Hazel/src/Hazel/Scene/Scene.cpp +++ b/Hazel/src/Hazel/Scene/Scene.cpp @@ -4,9 +4,11 @@ #include "Scene.h" +#include #include #include "Components.h" +#include "ScriptableEntity.h" #include "Entity.h" #include "../../../vendor/box2d/src/physics_world.h" @@ -37,13 +39,79 @@ namespace Hazel { } + template + static void CopyComponent(entt::registry& dst, entt::registry& src, const std::unordered_map& enttMap) + { + auto view = src.view(); + for (auto e : view) + { + UUID uuid = src.get(e).ID; + if (enttMap.find(uuid) == enttMap.end()) + { + HZ_CORE_ERROR("ERROR"); + assert(-1); + } + + entt::entity entity = enttMap.at(uuid); + auto& component = view.get(e); + + dst.emplace_or_replace(entity, component); + } + } + + template + static void CopyComponentIfExists(Entity dst, Entity src) + { + if (src.HasComponent()) + dst.AddOrRelpaceComponent(src.GetComponent()); + } + + Ref Scene::Copy(Ref other) + { + Ref newScene = CreateRef(); + + newScene->m_ViewportWidth = other->m_ViewportWidth; + newScene->m_ViewportHeight = other->m_ViewportHeight; + + std::unordered_map enttMap; + + auto& srcSceneRegistry = other->m_Registry; + auto& dstSceneRegistry = newScene->m_Registry; + + // Create entity in new Secne + auto idView = srcSceneRegistry.view(); + for (auto e : idView) + { + UUID uuid = srcSceneRegistry.get(e).ID; + const auto& name = srcSceneRegistry.get(e).Tag; + Entity newEntity = newScene->CreateEntityWithUUID(uuid, name); + enttMap[uuid] = (entt::entity)newEntity; + } + + CopyComponent(dstSceneRegistry, srcSceneRegistry, enttMap); + CopyComponent(dstSceneRegistry, srcSceneRegistry, enttMap); + CopyComponent(dstSceneRegistry, srcSceneRegistry, enttMap); + CopyComponent(dstSceneRegistry, srcSceneRegistry, enttMap); + CopyComponent(dstSceneRegistry, srcSceneRegistry, enttMap); + CopyComponent(dstSceneRegistry, srcSceneRegistry, enttMap); + + return newScene; + } + Entity Scene::CreateEntity(const std::string& name) + { + return CreateEntityWithUUID(UUID(), name); + } + + Entity Scene::CreateEntityWithUUID(UUID uuid, const std::string& name) { Entity entity = {m_Registry.create(), this}; + entity.AddComponent(uuid); entity.AddComponent(); entity.AddComponent(name.empty() ? "Entity" : name); return entity; + } void Scene::DestoryEntity(const Entity entity) @@ -217,6 +285,18 @@ namespace Hazel } + void Scene::DuplicateEntity(Entity entity) + { + Entity newEntity = CreateEntity(entity.GetName() + " copy"); + + CopyComponentIfExists(newEntity, entity); + CopyComponentIfExists(newEntity, entity); + CopyComponentIfExists(newEntity, entity); + CopyComponentIfExists(newEntity, entity); + CopyComponentIfExists(newEntity, entity); + CopyComponentIfExists(newEntity, entity); + } + Entity Scene::GetPrimaryCameraEntity() { auto view = m_Registry.view(); @@ -232,9 +312,13 @@ namespace Hazel template void Scene::OnComponentAdded(Entity entity, T& component) { - static_assert(false); + } + template<> + void Scene::OnComponentAdded(Entity entity, IDComponent& component) + { + } template<> void Scene::OnComponentAdded(Entity entity, TransformComponent& component) { @@ -243,7 +327,8 @@ namespace Hazel template<> void Scene::OnComponentAdded(Entity entity, CameraComponent& component) { - component.Camera.SetViewPortSize(m_ViewportWidth, m_ViewportHeight); + if (m_ViewportWidth > 0 && m_ViewportHeight > 0) + component.Camera.SetViewPortSize(m_ViewportWidth, m_ViewportHeight); } template<> @@ -272,6 +357,7 @@ namespace Hazel } + template HAZEL_API void Scene::OnComponentAdded(Entity, IDComponent&); template HAZEL_API void Scene::OnComponentAdded(Entity, TransformComponent&); template HAZEL_API void Scene::OnComponentAdded(Entity, CameraComponent&); template HAZEL_API void Scene::OnComponentAdded(Entity, TagComponent&); diff --git a/Hazel/src/Hazel/Scene/Scene.h b/Hazel/src/Hazel/Scene/Scene.h index 356eed0..65d4eb3 100644 --- a/Hazel/src/Hazel/Scene/Scene.h +++ b/Hazel/src/Hazel/Scene/Scene.h @@ -8,6 +8,7 @@ #include #include +#include #include #include "entt.hpp" @@ -23,7 +24,10 @@ namespace Hazel Scene(); ~Scene(); - Entity CreateEntity(const std::string& name = ""); + static Ref Copy(Ref other); + + Entity CreateEntity(const std::string& name = std::string()); + Entity CreateEntityWithUUID(UUID uuid, const std::string& name = std::string()); void DestoryEntity(Entity entity); @@ -34,6 +38,8 @@ namespace Hazel void OnUpdateEditor(TimeStep& ts, const EditorCamera& camera); void OnViewportResize(uint32_t width, uint32_t height); + void DuplicateEntity(Entity entity); + Entity GetPrimaryCameraEntity(); private: diff --git a/Hazel/src/Hazel/Scene/SceneSerializer.cpp b/Hazel/src/Hazel/Scene/SceneSerializer.cpp index 52654d9..c13a813 100644 --- a/Hazel/src/Hazel/Scene/SceneSerializer.cpp +++ b/Hazel/src/Hazel/Scene/SceneSerializer.cpp @@ -139,8 +139,14 @@ namespace Hazel static void SerializeEntity(YAML::Emitter& out, Entity entity) { + if (!entity.HasComponent()) + { + HZ_CORE_ERROR("Entity Could not find UUID!"); + assert(-1); + } + out << YAML::BeginMap; // entity - out << YAML::Key << "Entity" << YAML::Value << "123479283"; // TODO: entity ID goes here + out << YAML::Key << "Entity" << YAML::Value << entity.GetUUID(); if (entity.HasComponent()) { @@ -280,7 +286,7 @@ namespace Hazel { for (auto entity : entities) { - uint64_t uuid = entity["Entity"].as(); // TODO + uint64_t uuid = entity["Entity"].as(); std::string name; auto TagComponent = entity["TagComponent"]; @@ -289,7 +295,7 @@ namespace Hazel HZ_CORE_TRACE("Deserializing Entity: {0}:({1})", name, uuid); - Entity deserializedEntity = m_Scene->CreateEntity(name); + Entity deserializedEntity = m_Scene->CreateEntityWithUUID(uuid, name); auto transformComponent = entity["TransformComponent"]; if (transformComponent) diff --git a/Sandbox/src/Editor/EditorLayer.cpp b/Sandbox/src/Editor/EditorLayer.cpp index 2c58411..c6f8aa9 100644 --- a/Sandbox/src/Editor/EditorLayer.cpp +++ b/Sandbox/src/Editor/EditorLayer.cpp @@ -280,7 +280,8 @@ namespace Hazel const float windowWidth = ImGui::GetWindowWidth(); const float windowHeight = ImGui::GetWindowHeight(); - const ImVec2 windowPos = ImGui::GetWindowPos(); + ImVec2 windowPos = ImGui::GetWindowPos(); + windowPos.y += m_ViewPortSize.y - windowsSize.y; ImGuizmo::SetRect(windowPos.x, windowPos.y, windowWidth, windowHeight); @@ -366,12 +367,30 @@ namespace Hazel void EditorLayer::OpenScene(const std::filesystem::path& scenePath) { + if (m_SceneState != SceneState::Edit) + OnSceneStop(); + + Ref newScene = CreateRef(); + SceneSerializer serializer(newScene); + if (serializer.Deserialize(scenePath.string())) + { + m_EditorScene = newScene; + m_EditorScene->OnViewportResize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y); + + m_ActiveScene = m_EditorScene; + + m_SceneHierachyPanel.SetContext(m_ActiveScene); + } + + /* m_ActiveScene = CreateRef(); m_ActiveScene->OnViewportResize((uint32_t)m_ViewPortSize.x, (uint32_t)m_ViewPortSize.y); m_SceneHierachyPanel.SetContext(m_ActiveScene); SceneSerializer serializer(m_ActiveScene); serializer.Deserialize(scenePath.string()); + */ + } void EditorLayer::NewScene() @@ -381,6 +400,34 @@ namespace Hazel m_SceneHierachyPanel.SetContext(m_ActiveScene); } + void EditorLayer::OnDuplicateEntity() + { + if (m_SceneState != SceneState::Edit) + return; + Entity selectedEntity = m_SceneHierachyPanel.GetSelectedEntity(); + if (selectedEntity) + m_EditorScene->DuplicateEntity(selectedEntity); + } + + void EditorLayer::OnScenePlay() + { + m_SceneState = SceneState::Play; + + m_ActiveScene = Scene::Copy(m_EditorScene); + m_ActiveScene->OnRuntimeStart(); + + m_SceneHierachyPanel.SetContext(m_ActiveScene); + } + + void EditorLayer::OnSceneStop() + { + m_SceneState = SceneState::Edit; + m_ActiveScene->OnRuntimeStop(); + m_ActiveScene = m_EditorScene; + + m_SceneHierachyPanel.SetContext(m_ActiveScene); + } + void EditorLayer::ChangeOptMode(unsigned int mode) { if (m_ViewportHovered) @@ -401,11 +448,12 @@ namespace Hazel #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) +#define SHORTCUT_CTRL_D (SDL_KMOD_CTRL | SDLK_D) 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; - + if (e.key.down && e.key.repeat == 0) switch (ctrl | shift | e.key.key) { case SHORTCUT_EXIT: @@ -420,6 +468,9 @@ namespace Hazel case SHORTCUT_SAVE_ALL: SaveScene(); break; + case SHORTCUT_CTRL_D: + OnDuplicateEntity(); + break; // GIZMO case SDLK_Q: @@ -475,15 +526,4 @@ namespace Hazel ImGui::End(); } - void EditorLayer::OnScenePlay() - { - m_SceneState = SceneState::Play; - m_ActiveScene->OnRuntimeStart(); - } - - void EditorLayer::OnSceneStop() - { - m_SceneState = SceneState::Edit; - m_ActiveScene->OnRuntimeStop(); - } } diff --git a/Sandbox/src/Editor/EditorLayer.h b/Sandbox/src/Editor/EditorLayer.h index 0c04033..feb3383 100644 --- a/Sandbox/src/Editor/EditorLayer.h +++ b/Sandbox/src/Editor/EditorLayer.h @@ -34,6 +34,8 @@ namespace Hazel void OpenScene(const std::filesystem::path& scenePath); void NewScene(); + void OnDuplicateEntity(); + void ChangeOptMode(unsigned int mode); private: @@ -44,6 +46,7 @@ namespace Hazel Ref m_ActiveScene; + Ref m_EditorScene; EditorCamera m_EditorCamera; Entity m_HoveredEntity;