Files
XCEngine/editor/src/Commands/EntityCommands.h

246 lines
8.1 KiB
C++

#pragma once
#include "Core/IEditorContext.h"
#include "Core/ISelectionManager.h"
#include "Core/ISceneManager.h"
#include "Utils/UndoUtils.h"
#include <XCEngine/Components/CameraComponent.h>
#include <XCEngine/Components/LightComponent.h>
#include <XCEngine/Components/MeshFilterComponent.h>
#include <XCEngine/Components/MeshRendererComponent.h>
#include <XCEngine/Core/Math/Quaternion.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Resources/BuiltinResources.h>
#include <string>
namespace XCEngine {
namespace Editor {
namespace Commands {
struct NoopEntitySetup {
void operator()(::XCEngine::Components::GameObject&, ISceneManager&) const {
}
};
template <typename SetupFn = NoopEntitySetup>
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