246 lines
8.1 KiB
C++
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
|