添加场景在运行时会临时复制一个场景功能,添加克隆实体功能
This commit is contained in:
@ -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:
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
#include <Hazel/Renderer/Camera.h>
|
||||
#include <Hazel/Renderer/ScenceCamera.h>
|
||||
|
||||
#include "ScriptableEntity.h"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
@ -15,9 +14,18 @@
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include "glm/gtx/quaternion.hpp"
|
||||
#include <box2d/types.h>
|
||||
#include <Hazel/Core/UUID.h>
|
||||
|
||||
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;
|
||||
|
||||
@ -5,8 +5,9 @@
|
||||
#ifndef ENTITY_H
|
||||
#define ENTITY_H
|
||||
#include <Hazel/Core/Log.h>
|
||||
|
||||
#include <Hazel/Core/UUID.h>
|
||||
#include "Scene.h"
|
||||
#include "Components.h"
|
||||
|
||||
|
||||
|
||||
@ -33,6 +34,14 @@ namespace Hazel
|
||||
return component;
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
T& AddOrRelpaceComponent(Args&&... args)
|
||||
{
|
||||
T& component = m_Scene->m_Registry.emplace_or_replace<T>(m_EntityHandle, std::forward<Args>(args)...);
|
||||
m_Scene->OnComponentAdded<T>(*this, component);
|
||||
return component;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
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<IDComponent>().ID; }
|
||||
const std::string& GetName() { return GetComponent<TagComponent>().Tag; }
|
||||
|
||||
private:
|
||||
entt::entity m_EntityHandle{ entt::null };
|
||||
Scene* m_Scene = nullptr;
|
||||
|
||||
@ -4,9 +4,11 @@
|
||||
|
||||
#include "Scene.h"
|
||||
|
||||
#include <spirv_common.hpp>
|
||||
#include <Hazel/Renderer/Renderer2D.h>
|
||||
|
||||
#include "Components.h"
|
||||
#include "ScriptableEntity.h"
|
||||
|
||||
#include "Entity.h"
|
||||
#include "../../../vendor/box2d/src/physics_world.h"
|
||||
@ -37,13 +39,79 @@ namespace Hazel
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
static void CopyComponent(entt::registry& dst, entt::registry& src, const std::unordered_map<UUID, entt::entity>& enttMap)
|
||||
{
|
||||
auto view = src.view<Component>();
|
||||
for (auto e : view)
|
||||
{
|
||||
UUID uuid = src.get<IDComponent>(e).ID;
|
||||
if (enttMap.find(uuid) == enttMap.end())
|
||||
{
|
||||
HZ_CORE_ERROR("ERROR");
|
||||
assert(-1);
|
||||
}
|
||||
|
||||
entt::entity entity = enttMap.at(uuid);
|
||||
auto& component = view.get<Component>(e);
|
||||
|
||||
dst.emplace_or_replace<Component>(entity, component);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Component>
|
||||
static void CopyComponentIfExists(Entity dst, Entity src)
|
||||
{
|
||||
if (src.HasComponent<Component>())
|
||||
dst.AddOrRelpaceComponent<Component>(src.GetComponent<Component>());
|
||||
}
|
||||
|
||||
Ref<Scene> Scene::Copy(Ref<Scene> other)
|
||||
{
|
||||
Ref<Scene> newScene = CreateRef<Scene>();
|
||||
|
||||
newScene->m_ViewportWidth = other->m_ViewportWidth;
|
||||
newScene->m_ViewportHeight = other->m_ViewportHeight;
|
||||
|
||||
std::unordered_map<UUID, entt::entity> enttMap;
|
||||
|
||||
auto& srcSceneRegistry = other->m_Registry;
|
||||
auto& dstSceneRegistry = newScene->m_Registry;
|
||||
|
||||
// Create entity in new Secne
|
||||
auto idView = srcSceneRegistry.view<IDComponent>();
|
||||
for (auto e : idView)
|
||||
{
|
||||
UUID uuid = srcSceneRegistry.get<IDComponent>(e).ID;
|
||||
const auto& name = srcSceneRegistry.get<TagComponent>(e).Tag;
|
||||
Entity newEntity = newScene->CreateEntityWithUUID(uuid, name);
|
||||
enttMap[uuid] = (entt::entity)newEntity;
|
||||
}
|
||||
|
||||
CopyComponent<TransformComponent>(dstSceneRegistry, srcSceneRegistry, enttMap);
|
||||
CopyComponent<SpriteRendererComponent>(dstSceneRegistry, srcSceneRegistry, enttMap);
|
||||
CopyComponent<CameraComponent>(dstSceneRegistry, srcSceneRegistry, enttMap);
|
||||
CopyComponent<NativeScriptComponent>(dstSceneRegistry, srcSceneRegistry, enttMap);
|
||||
CopyComponent<RigidBody2DComponent>(dstSceneRegistry, srcSceneRegistry, enttMap);
|
||||
CopyComponent<BoxCollider2DComponent>(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<IDComponent>(uuid);
|
||||
entity.AddComponent<TransformComponent>();
|
||||
entity.AddComponent<TagComponent>(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<TransformComponent>(newEntity, entity);
|
||||
CopyComponentIfExists<SpriteRendererComponent>(newEntity, entity);
|
||||
CopyComponentIfExists<CameraComponent>(newEntity, entity);
|
||||
CopyComponentIfExists<NativeScriptComponent>(newEntity, entity);
|
||||
CopyComponentIfExists<RigidBody2DComponent>(newEntity, entity);
|
||||
CopyComponentIfExists<BoxCollider2DComponent>(newEntity, entity);
|
||||
}
|
||||
|
||||
Entity Scene::GetPrimaryCameraEntity()
|
||||
{
|
||||
auto view = m_Registry.view<CameraComponent>();
|
||||
@ -232,9 +312,13 @@ namespace Hazel
|
||||
template <typename T>
|
||||
void Scene::OnComponentAdded(Entity entity, T& component)
|
||||
{
|
||||
static_assert(false);
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
void Scene::OnComponentAdded<IDComponent>(Entity entity, IDComponent& component)
|
||||
{
|
||||
}
|
||||
template<>
|
||||
void Scene::OnComponentAdded<TransformComponent>(Entity entity, TransformComponent& component)
|
||||
{
|
||||
@ -243,6 +327,7 @@ namespace Hazel
|
||||
template<>
|
||||
void Scene::OnComponentAdded<CameraComponent>(Entity entity, CameraComponent& component)
|
||||
{
|
||||
if (m_ViewportWidth > 0 && m_ViewportHeight > 0)
|
||||
component.Camera.SetViewPortSize(m_ViewportWidth, m_ViewportHeight);
|
||||
}
|
||||
|
||||
@ -272,6 +357,7 @@ namespace Hazel
|
||||
}
|
||||
|
||||
|
||||
template HAZEL_API void Scene::OnComponentAdded<IDComponent>(Entity, IDComponent&);
|
||||
template HAZEL_API void Scene::OnComponentAdded<TransformComponent>(Entity, TransformComponent&);
|
||||
template HAZEL_API void Scene::OnComponentAdded<CameraComponent>(Entity, CameraComponent&);
|
||||
template HAZEL_API void Scene::OnComponentAdded<TagComponent>(Entity, TagComponent&);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
|
||||
#include <box2d/id.h>
|
||||
#include <Hazel/Core/TimeStep.h>
|
||||
#include <Hazel/Core/UUID.h>
|
||||
#include <Hazel/Renderer/EditorCamera.h>
|
||||
|
||||
#include "entt.hpp"
|
||||
@ -23,7 +24,10 @@ namespace Hazel
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
Entity CreateEntity(const std::string& name = "");
|
||||
static Ref<Scene> Copy(Ref<Scene> 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:
|
||||
|
||||
@ -139,8 +139,14 @@ namespace Hazel
|
||||
|
||||
static void SerializeEntity(YAML::Emitter& out, Entity entity)
|
||||
{
|
||||
if (!entity.HasComponent<IDComponent>())
|
||||
{
|
||||
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<TagComponent>())
|
||||
{
|
||||
@ -280,7 +286,7 @@ namespace Hazel
|
||||
{
|
||||
for (auto entity : entities)
|
||||
{
|
||||
uint64_t uuid = entity["Entity"].as<uint64_t>(); // TODO
|
||||
uint64_t uuid = entity["Entity"].as<uint64_t>();
|
||||
|
||||
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)
|
||||
|
||||
@ -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<Scene> newScene = CreateRef<Scene>();
|
||||
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<Scene>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Scene> m_ActiveScene;
|
||||
Ref<Scene> m_EditorScene;
|
||||
EditorCamera m_EditorCamera;
|
||||
|
||||
Entity m_HoveredEntity;
|
||||
|
||||
Reference in New Issue
Block a user