#pragma once #include "Core/IEditorContext.h" #include "Core/ISelectionManager.h" #include "Core/ISceneManager.h" #include "Utils/UndoUtils.h" #include #include #include #include #include #include #include #include namespace XCEngine { namespace Editor { namespace Commands { struct NoopEntitySetup { void operator()(::XCEngine::Components::GameObject&, ISceneManager&) const { } }; template inline ::XCEngine::Components::GameObject* CreateEntity( IEditorContext& context, const std::string& commandLabel, const std::string& entityName, ::XCEngine::Components::GameObject* parent = nullptr, SetupFn setup = {}) { ::XCEngine::Components::GameObject* created = nullptr; UndoUtils::ExecuteSceneCommand(context, commandLabel, [&]() { auto& sceneManager = context.GetSceneManager(); created = sceneManager.CreateEntity(entityName, parent); if (!created) { return; } setup(*created, sceneManager); context.GetSelectionManager().SetSelectedEntity(created->GetID()); }); return created; } inline ::XCEngine::Components::GameObject* CreateEmptyEntity( IEditorContext& context, ::XCEngine::Components::GameObject* parent = nullptr, const std::string& commandLabel = "Create Entity", const std::string& entityName = "GameObject") { return CreateEntity(context, commandLabel, entityName, parent); } inline ::XCEngine::Components::GameObject* CreateCameraEntity( IEditorContext& context, ::XCEngine::Components::GameObject* parent = nullptr, const std::string& commandLabel = "Create Camera", const std::string& entityName = "Camera") { return CreateEntity( context, commandLabel, entityName, parent, [](::XCEngine::Components::GameObject& entity, ISceneManager&) { entity.AddComponent<::XCEngine::Components::CameraComponent>(); }); } inline ::XCEngine::Components::GameObject* CreateLightEntity( IEditorContext& context, ::XCEngine::Components::GameObject* parent = nullptr, const std::string& commandLabel = "Create Light", const std::string& entityName = "Light") { return CreateEntity( context, commandLabel, entityName, parent, [](::XCEngine::Components::GameObject& entity, ISceneManager&) { entity.AddComponent<::XCEngine::Components::LightComponent>(); }); } inline ::XCEngine::Components::GameObject* CreatePrimitiveEntity( IEditorContext& context, ::XCEngine::Resources::BuiltinPrimitiveType primitiveType, ::XCEngine::Components::GameObject* parent = nullptr) { const char* primitiveName = ::XCEngine::Resources::GetBuiltinPrimitiveDisplayName(primitiveType); return CreateEntity( context, std::string("Create ") + primitiveName, primitiveName, parent, [primitiveType](::XCEngine::Components::GameObject& entity, ISceneManager&) { auto* meshFilter = entity.GetComponent<::XCEngine::Components::MeshFilterComponent>(); if (meshFilter == nullptr) { meshFilter = entity.AddComponent<::XCEngine::Components::MeshFilterComponent>(); } meshFilter->SetMeshPath(::XCEngine::Resources::GetBuiltinPrimitiveMeshPath(primitiveType).CStr()); auto* meshRenderer = entity.GetComponent<::XCEngine::Components::MeshRendererComponent>(); if (meshRenderer == nullptr) { meshRenderer = entity.AddComponent<::XCEngine::Components::MeshRendererComponent>(); } meshRenderer->SetMaterialPath(0, ::XCEngine::Resources::GetBuiltinDefaultPrimitiveMaterialPath().CStr()); }); } inline bool RenameEntity( IEditorContext& context, ::XCEngine::Components::GameObject::ID entityId, const std::string& newName, const std::string& commandLabel = "Rename Entity") { if (newName.empty() || !context.GetSceneManager().GetEntity(entityId)) { return false; } UndoUtils::ExecuteSceneCommand(context, commandLabel, [&]() { context.GetSceneManager().RenameEntity(entityId, newName); }); return true; } inline bool DeleteEntity( IEditorContext& context, ::XCEngine::Components::GameObject::ID entityId, const std::string& commandLabel = "Delete Entity") { if (!context.GetSceneManager().GetEntity(entityId)) { return false; } UndoUtils::ExecuteSceneCommand(context, commandLabel, [&]() { context.GetSceneManager().DeleteEntity(entityId); }); return true; } inline bool CopyEntity(IEditorContext& context, ::XCEngine::Components::GameObject::ID entityId) { if (!context.GetSceneManager().GetEntity(entityId)) { return false; } context.GetSceneManager().CopyEntity(entityId); return true; } inline ::XCEngine::Components::GameObject::ID PasteEntity( IEditorContext& context, ::XCEngine::Components::GameObject::ID parentId = 0, const std::string& commandLabel = "Paste Entity") { ::XCEngine::Components::GameObject::ID newId = 0; UndoUtils::ExecuteSceneCommand(context, commandLabel, [&]() { newId = context.GetSceneManager().PasteEntity(parentId); if (newId != 0) { context.GetSelectionManager().SetSelectedEntity(newId); } }); return newId; } inline ::XCEngine::Components::GameObject::ID DuplicateEntity( IEditorContext& context, ::XCEngine::Components::GameObject::ID entityId, const std::string& commandLabel = "Duplicate Entity") { if (!context.GetSceneManager().GetEntity(entityId)) { return 0; } ::XCEngine::Components::GameObject::ID newId = 0; UndoUtils::ExecuteSceneCommand(context, commandLabel, [&]() { newId = context.GetSceneManager().DuplicateEntity(entityId); if (newId != 0) { context.GetSelectionManager().SetSelectedEntity(newId); } }); return newId; } inline bool CanReparentEntity( const ::XCEngine::Components::GameObject* source, const ::XCEngine::Components::GameObject* newParent) { if (!source) { return false; } for (auto* current = newParent; current != nullptr; current = current->GetParent()) { if (current == source) { return false; } } return true; } inline bool ReparentEntityPreserveWorldTransform( IEditorContext& context, ::XCEngine::Components::GameObject* source, ::XCEngine::Components::GameObject::ID newParentId, const std::string& commandLabel = "Reparent Entity") { if (!source) { return false; } const ::XCEngine::Components::GameObject::ID currentParentId = source->GetParent() ? source->GetParent()->GetID() : 0; if (currentParentId == newParentId) { return false; } UndoUtils::ExecuteSceneCommand(context, commandLabel, [&]() { auto& sceneManager = context.GetSceneManager(); auto* transform = source->GetTransform(); if (!transform) { sceneManager.MoveEntity(source->GetID(), newParentId); return; } const ::XCEngine::Math::Vector3 worldPos = transform->GetPosition(); const ::XCEngine::Math::Quaternion worldRot = transform->GetRotation(); const ::XCEngine::Math::Vector3 worldScale = transform->GetScale(); sceneManager.MoveEntity(source->GetID(), newParentId); transform->SetPosition(worldPos); transform->SetRotation(worldRot); transform->SetScale(worldScale); }); return true; } inline bool DetachEntity( IEditorContext& context, ::XCEngine::Components::GameObject* entity, const std::string& commandLabel = "Reparent Entity") { if (!entity || entity->GetParent() == nullptr) { return false; } return ReparentEntityPreserveWorldTransform(context, entity, 0, commandLabel); } } // namespace Commands } // namespace Editor } // namespace XCEngine