|
|
|
@@ -2,8 +2,9 @@
|
|
|
|
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
|
|
|
#include <imgui/imgui_internal.h>
|
|
|
|
|
|
|
|
|
|
EditorSystem::EditorSystem(EventBroker* eventBroker)
|
|
|
|
|
EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer)
|
|
|
|
|
: ImpureSystem(eventBroker)
|
|
|
|
|
, m_Renderer(renderer)
|
|
|
|
|
{
|
|
|
|
|
auto config = ResourceManager::Load<ConfigFile>("Config.ini");
|
|
|
|
|
m_Enabled = config->Get<bool>("Debug.EditorEnabled", false);
|
|
|
|
@@ -15,51 +16,52 @@ EditorSystem::EditorSystem(EventBroker* eventBroker)
|
|
|
|
|
|
|
|
|
|
EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand);
|
|
|
|
|
EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress);
|
|
|
|
|
EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease);
|
|
|
|
|
EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove);
|
|
|
|
|
EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorSystem::Update(World* world, double dt)
|
|
|
|
|
{
|
|
|
|
|
m_World = world;
|
|
|
|
|
|
|
|
|
|
if (!m_Enabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_Widget == 0) {
|
|
|
|
|
m_Widget = world->CreateEntity();
|
|
|
|
|
world->AttachComponent(m_Widget, "Transform");
|
|
|
|
|
auto& model = world->AttachComponent(m_Widget, "Model");
|
|
|
|
|
model["Resource"] = "Models/TranslationWidget.obj";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_Selection != m_LastSelection) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto& widgetModel = world->GetComponent(m_Widget, "Model");
|
|
|
|
|
widgetModel["Visible"] = m_Visible;
|
|
|
|
|
if (m_Selection != 0) {
|
|
|
|
|
if (world->HasComponent(m_Selection, "Transform")) {
|
|
|
|
|
glm::vec3 pos = RenderQueueFactory::AbsolutePosition(world, m_Selection);
|
|
|
|
|
auto widgetTransform = world->GetComponent(m_Widget, "Transform");
|
|
|
|
|
widgetTransform["Position"] = pos;
|
|
|
|
|
} else {
|
|
|
|
|
m_Selection = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!m_Visible) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateWidget();
|
|
|
|
|
|
|
|
|
|
drawUI(world, dt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool EditorSystem::OnInputCommand(const Events::InputCommand& e)
|
|
|
|
|
{
|
|
|
|
|
if (e.Command == "ToggleEditor" && e.Value > 0) {
|
|
|
|
|
m_Visible = !m_Visible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (e.Command == "EditorToolMove" && e.Value > 0) {
|
|
|
|
|
setWidgetMode(WidgetMode::Translate);
|
|
|
|
|
}
|
|
|
|
|
if (e.Command == "EditorToolRotate" && e.Value > 0) {
|
|
|
|
|
setWidgetMode(WidgetMode::Rotate);
|
|
|
|
|
}
|
|
|
|
|
if (e.Command == "EditorToolScale" && e.Value > 0) {
|
|
|
|
|
setWidgetMode(WidgetMode::Scale);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (e.Command == "EditorToggleTransformSpace" && e.Value > 0) {
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
|
|
|
setWidgetSpace(WidgetSpace::Local);
|
|
|
|
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
setWidgetSpace(WidgetSpace::Global);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -71,17 +73,232 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EditorSystem::OnMouseMove(const Events::MouseMove& e)
|
|
|
|
|
{
|
|
|
|
|
if (m_Widget == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
|
|
|
glm::vec3 widgetOrientation = widgetTransform["Orientation"];
|
|
|
|
|
|
|
|
|
|
glm::quat totalOrientation = m_Renderer->Camera()->Orientation() * glm::inverse(glm::quat(widgetOrientation));
|
|
|
|
|
|
|
|
|
|
int width;
|
|
|
|
|
int height;
|
|
|
|
|
glfwGetFramebufferSize(m_Renderer->Window(), &width, &height);
|
|
|
|
|
Rectangle res(width, height);
|
|
|
|
|
|
|
|
|
|
glm::vec2 delta2(res.Width / 2.f + e.DeltaX, res.Height / 2.f + -e.DeltaY);
|
|
|
|
|
glm::vec3 deltaWorld = ScreenCoords::ToWorldPos(
|
|
|
|
|
delta2,
|
|
|
|
|
m_WidgetPickingDepth,
|
|
|
|
|
res,
|
|
|
|
|
m_Renderer->Camera()->ProjectionMatrix(),
|
|
|
|
|
glm::toMat4(glm::inverse(totalOrientation))
|
|
|
|
|
);
|
|
|
|
|
glm::vec3 origin = ScreenCoords::ToWorldPos(
|
|
|
|
|
glm::vec2(res.Width / 2.f, res.Height / 2.f),
|
|
|
|
|
m_WidgetPickingDepth,
|
|
|
|
|
res,
|
|
|
|
|
m_Renderer->Camera()->ProjectionMatrix(),
|
|
|
|
|
glm::toMat4(glm::inverse(totalOrientation))
|
|
|
|
|
);
|
|
|
|
|
deltaWorld = deltaWorld - origin;
|
|
|
|
|
glm::vec3 movement = deltaWorld * m_WidgetCurrentAxis;
|
|
|
|
|
|
|
|
|
|
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
|
|
|
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
|
|
|
if (m_WidgetMode == WidgetMode::Translate) {
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
|
|
|
EntityID parent = m_World->GetParent(m_Selection);
|
|
|
|
|
glm::quat inverseParentOrientation;
|
|
|
|
|
if (parent != 0) {
|
|
|
|
|
inverseParentOrientation = glm::inverse(RenderQueueFactory::AbsoluteOrientation(m_World, parent));
|
|
|
|
|
}
|
|
|
|
|
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * movement;
|
|
|
|
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
|
|
|
(glm::vec3&)selectionTransform["Position"] += glm::quat((glm::vec3)selectionTransform["Orientation"]) * movement;
|
|
|
|
|
}
|
|
|
|
|
} else if (m_WidgetMode == WidgetMode::Rotate) {
|
|
|
|
|
glm::vec3 finalMovement;
|
|
|
|
|
finalMovement.x = -deltaWorld.y * m_WidgetCurrentAxis.x;
|
|
|
|
|
finalMovement.y = deltaWorld.x * m_WidgetCurrentAxis.y;
|
|
|
|
|
finalMovement.z = deltaWorld.y * m_WidgetCurrentAxis.z;
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
|
|
|
EntityID parent = m_World->GetParent(m_Selection);
|
|
|
|
|
glm::quat parentOrientation;
|
|
|
|
|
if (parent != 0) {
|
|
|
|
|
parentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, parent);
|
|
|
|
|
}
|
|
|
|
|
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
|
|
|
|
|
//glm::quat currentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection);
|
|
|
|
|
glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation);
|
|
|
|
|
glm::quat deltaOrientation(finalMovement);
|
|
|
|
|
selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation));
|
|
|
|
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"];
|
|
|
|
|
glm::quat currentOrientation(selectionOrientation);
|
|
|
|
|
glm::quat deltaOrientation(finalMovement);
|
|
|
|
|
selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation);
|
|
|
|
|
}
|
|
|
|
|
} else if (m_WidgetMode == WidgetMode::Scale) {
|
|
|
|
|
glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"];
|
|
|
|
|
glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"];
|
|
|
|
|
glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"];
|
|
|
|
|
if (m_WidgetCurrentAxis.x > 0) {
|
|
|
|
|
scaleX.x += movement.x;
|
|
|
|
|
}
|
|
|
|
|
if (m_WidgetCurrentAxis.y > 0) {
|
|
|
|
|
scaleY.y += movement.y;
|
|
|
|
|
}
|
|
|
|
|
if (m_WidgetCurrentAxis.z > 0) {
|
|
|
|
|
scaleZ.z += movement.z;
|
|
|
|
|
}
|
|
|
|
|
if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) {
|
|
|
|
|
float max = glm::max(scaleX.x, glm::max(scaleY.y, scaleZ.z));
|
|
|
|
|
(glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(max);
|
|
|
|
|
}
|
|
|
|
|
(glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e)
|
|
|
|
|
{
|
|
|
|
|
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
|
|
|
|
m_WidgetCurrentAxis = glm::vec3(0.f);
|
|
|
|
|
//setWidgetMode(m_WidgetMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EditorSystem::OnPicking(const Events::Picking& e)
|
|
|
|
|
{
|
|
|
|
|
for (auto& pos : m_PickingQueue) {
|
|
|
|
|
auto result = e.Pick(pos);
|
|
|
|
|
LOG_INFO("Selected %i", result.Entity);
|
|
|
|
|
m_Selection = result.Entity;
|
|
|
|
|
EntityID entity = result.Entity;
|
|
|
|
|
if (glm::length2(m_WidgetCurrentAxis) > 0.f) {
|
|
|
|
|
} else {
|
|
|
|
|
LOG_INFO("Selected %i", entity);
|
|
|
|
|
if (entity != 0) {
|
|
|
|
|
EntityID parent = m_World->GetParent(entity);
|
|
|
|
|
if (parent == m_Widget) {
|
|
|
|
|
m_WidgetCurrentAxis = glm::vec3(
|
|
|
|
|
(entity == m_WidgetX) || (entity == m_WidgetOrigin),
|
|
|
|
|
(entity == m_WidgetY) || (entity == m_WidgetOrigin),
|
|
|
|
|
(entity == m_WidgetZ) || (entity == m_WidgetOrigin)
|
|
|
|
|
);
|
|
|
|
|
m_WidgetPickingDepth = result.Depth;
|
|
|
|
|
|
|
|
|
|
//auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
|
|
|
//auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
|
|
|
//widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"];
|
|
|
|
|
} else {
|
|
|
|
|
ImGui::SetActiveID(0, nullptr);
|
|
|
|
|
m_Selection = entity;
|
|
|
|
|
setWidgetMode(m_WidgetMode);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
m_Selection = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_PickingQueue.clear();
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditorSystem::updateWidget()
|
|
|
|
|
{
|
|
|
|
|
if (m_Widget == 0) {
|
|
|
|
|
m_Widget = m_World->CreateEntity();
|
|
|
|
|
m_World->AttachComponent(m_Widget, "Transform");
|
|
|
|
|
m_WidgetX = m_World->CreateEntity(m_Widget);
|
|
|
|
|
m_World->AttachComponent(m_WidgetX, "Transform");
|
|
|
|
|
m_World->AttachComponent(m_WidgetX, "Model");
|
|
|
|
|
m_WidgetY = m_World->CreateEntity(m_Widget);
|
|
|
|
|
m_World->AttachComponent(m_WidgetY, "Transform");
|
|
|
|
|
m_World->AttachComponent(m_WidgetY, "Model");
|
|
|
|
|
m_WidgetZ = m_World->CreateEntity(m_Widget);
|
|
|
|
|
m_World->AttachComponent(m_WidgetZ, "Transform");
|
|
|
|
|
m_World->AttachComponent(m_WidgetZ, "Model");
|
|
|
|
|
m_WidgetOrigin = m_World->CreateEntity(m_Widget);
|
|
|
|
|
m_World->AttachComponent(m_WidgetOrigin, "Transform");
|
|
|
|
|
m_World->AttachComponent(m_WidgetOrigin, "Model");
|
|
|
|
|
setWidgetMode(WidgetMode::Translate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_Selection != 0) {
|
|
|
|
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
|
|
|
glm::vec3 selectionPosition = RenderQueueFactory::AbsolutePosition(m_World, m_Selection);
|
|
|
|
|
widgetTransform["Position"] = selectionPosition;
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorSystem::setWidgetMode(WidgetMode newMode)
|
|
|
|
|
{
|
|
|
|
|
if (m_Widget == 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto widgetTransform = m_World->GetComponent(m_Widget, "Transform");
|
|
|
|
|
widgetTransform["Orientation"] = glm::vec3(0.f);
|
|
|
|
|
m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f);
|
|
|
|
|
m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f);
|
|
|
|
|
m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f);
|
|
|
|
|
m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f);
|
|
|
|
|
|
|
|
|
|
if (newMode == WidgetMode::Translate) {
|
|
|
|
|
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false;
|
|
|
|
|
if (m_Selection != 0) {
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
|
|
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (newMode == WidgetMode::Scale) {
|
|
|
|
|
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/ScaleWidgetX.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/ScaleWidgetY.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/ScaleWidgetZ.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = true;
|
|
|
|
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj";
|
|
|
|
|
if (m_Selection != 0) {
|
|
|
|
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
|
|
|
widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"];
|
|
|
|
|
}
|
|
|
|
|
} else if (newMode == WidgetMode::Rotate) {
|
|
|
|
|
m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj";
|
|
|
|
|
m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false;
|
|
|
|
|
if (m_Selection != 0) {
|
|
|
|
|
auto selectionTransform = m_World->GetComponent(m_Selection, "Transform");
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_WidgetMode = newMode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditorSystem::setWidgetSpace(WidgetSpace space)
|
|
|
|
|
{
|
|
|
|
|
m_WidgetSpace = space;
|
|
|
|
|
setWidgetMode(m_WidgetMode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorSystem::drawUI(World* world, double dt)
|
|
|
|
|
{
|
|
|
|
|
ImGui::ShowTestWindow();
|
|
|
|
@@ -102,24 +319,32 @@ void EditorSystem::drawUI(World* world, double dt)
|
|
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Move")) {
|
|
|
|
|
auto& model = world->GetComponent(m_Widget, "Model");
|
|
|
|
|
model["Resource"] = "Models/TranslationWidget.obj";
|
|
|
|
|
setWidgetMode(WidgetMode::Translate);
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Rotate")) {
|
|
|
|
|
auto& model = world->GetComponent(m_Widget, "Model");
|
|
|
|
|
model["Resource"] = "Models/RotationWidget.obj";
|
|
|
|
|
setWidgetMode(WidgetMode::Rotate);
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Scale")) {
|
|
|
|
|
auto& model = world->GetComponent(m_Widget, "Model");
|
|
|
|
|
model["Resource"] = "Models/ScaleWidget.obj";
|
|
|
|
|
setWidgetMode(WidgetMode::Scale);
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (m_WidgetSpace == WidgetSpace::Global) {
|
|
|
|
|
if (ImGui::Button("(Global)")) {
|
|
|
|
|
setWidgetSpace(WidgetSpace::Local);
|
|
|
|
|
}
|
|
|
|
|
} else if (m_WidgetSpace == WidgetSpace::Local) {
|
|
|
|
|
if (ImGui::Button("(Local)")) {
|
|
|
|
|
setWidgetSpace(WidgetSpace::Global);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndMainMenuBar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ImGui::Begin("Components")) {
|
|
|
|
|
std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components");
|
|
|
|
|
if (ImGui::Begin(title.c_str())) {
|
|
|
|
|
if (m_Selection != 0) {
|
|
|
|
|
auto& pools = world->GetComponentPools();
|
|
|
|
|
|
|
|
|
@@ -205,23 +430,62 @@ void EditorSystem::drawUI(World* world, double dt)
|
|
|
|
|
ImGui::End();
|
|
|
|
|
|
|
|
|
|
if (ImGui::Begin("Entitites")) {
|
|
|
|
|
static EntityID draggingEntity = 0;
|
|
|
|
|
auto entityChildren = world->GetEntityChildren();
|
|
|
|
|
std::function<void(EntityID)> recurse = [&](EntityID parent) {
|
|
|
|
|
auto range = entityChildren.equal_range(parent);
|
|
|
|
|
for (auto it = range.first; it != range.second; it++) {
|
|
|
|
|
|
|
|
|
|
ImVec2 pos = ImGui::GetCursorScreenPos();
|
|
|
|
|
float width = ImGui::GetContentRegionAvailWidth();
|
|
|
|
|
ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13));
|
|
|
|
|
auto window = ImGui::GetCurrentWindow();
|
|
|
|
|
if (m_Selection == it->second) {
|
|
|
|
|
const ImU32 col = window->Color(ImGuiCol_HeaderActive);
|
|
|
|
|
window->DrawList->AddRectFilled(bb.Min, bb.Max, col);
|
|
|
|
|
}
|
|
|
|
|
ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(it->second)).c_str());
|
|
|
|
|
bool hovered = false;
|
|
|
|
|
bool held = false;
|
|
|
|
|
if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) {
|
|
|
|
|
m_Selection = it->second;
|
|
|
|
|
}
|
|
|
|
|
if (held) {
|
|
|
|
|
ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0);
|
|
|
|
|
if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) {
|
|
|
|
|
if (draggingEntity == 0) {
|
|
|
|
|
draggingEntity = it->second;
|
|
|
|
|
LOG_DEBUG("Started drag of entity %i", draggingEntity);
|
|
|
|
|
}
|
|
|
|
|
ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0));
|
|
|
|
|
ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings);
|
|
|
|
|
ImGui::Text("#%i", draggingEntity);
|
|
|
|
|
ImGui::End();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once);
|
|
|
|
|
if (ImGui::TreeNode((std::string("#") + std::to_string(it->second)).c_str())) {
|
|
|
|
|
if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) {
|
|
|
|
|
m_Selection = it->second;
|
|
|
|
|
if (draggingEntity != 0 && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) {
|
|
|
|
|
LOG_DEBUG("Changed parent of %i to %i", draggingEntity, it->second);
|
|
|
|
|
changeParent(draggingEntity, it->second);
|
|
|
|
|
draggingEntity = 0;
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Add")) {
|
|
|
|
|
EntityID entity = world->CreateEntity(it->second);
|
|
|
|
|
world->AttachComponent(entity, "Transform");
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Delete")) {
|
|
|
|
|
world->DeleteEntity(it->second);
|
|
|
|
|
|
|
|
|
|
if (ImGui::BeginPopupContextItem("item context menu")) {
|
|
|
|
|
if (ImGui::Button("Add")) {
|
|
|
|
|
EntityID entity = world->CreateEntity(it->second);
|
|
|
|
|
world->AttachComponent(entity, "Transform");
|
|
|
|
|
}
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Delete")) {
|
|
|
|
|
world->DeleteEntity(it->second);
|
|
|
|
|
ImGui::CloseCurrentPopup();
|
|
|
|
|
if (m_Selection == it->second) {
|
|
|
|
|
m_Selection = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndPopup();
|
|
|
|
|
}
|
|
|
|
|
recurse(it->second);
|
|
|
|
|
ImGui::TreePop();
|
|
|
|
@@ -250,3 +514,20 @@ bool EditorSystem::createDeleteButton(std::string componentType)
|
|
|
|
|
window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16);
|
|
|
|
|
return pressed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditorSystem::changeParent(EntityID entity, EntityID newParent)
|
|
|
|
|
{
|
|
|
|
|
if (entity == newParent) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// An entity can't be a child to one of its own children
|
|
|
|
|
auto children = m_World->GetEntityChildren().equal_range(entity);
|
|
|
|
|
for (auto it = children.first; it != children.second; it++) {
|
|
|
|
|
if (it->second == newParent) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_World->SetParent(entity, newParent);
|
|
|
|
|
}
|
|
|
|
|