diff --git a/resources/debug/debug.material b/resources/debug/debug.material index 0ac47e3..333426e 100644 --- a/resources/debug/debug.material +++ b/resources/debug/debug.material @@ -69,3 +69,27 @@ material Debug/Red2 } } +/** + * Debug material for normal visualization overlay. + * Renders on top of everything (depth_check off, depth_write off) + * Uses vertex colours so each normal line can have its own colour. + * Rendered in overlay queue to appear on top of all geometry. + */ +material Debug/NormalOverlay +{ + technique + { + pass + { + lighting off + depth_check off + depth_write off + ambient 1.0 1.0 1.0 1.0 + diffuse vertexcolour + specular 0.0 0.0 0.0 1.0 + cull_software none + cull_hardware none + scene_blend alpha_blend + } + } +} diff --git a/src/features/editScene/systems/EditorUISystem.cpp b/src/features/editScene/systems/EditorUISystem.cpp index 550ca84..c6d9923 100644 --- a/src/features/editScene/systems/EditorUISystem.cpp +++ b/src/features/editScene/systems/EditorUISystem.cpp @@ -40,6 +40,7 @@ #include "../components/GoapRunner.hpp" #include "../components/PathFollowing.hpp" #include "../components/Actuator.hpp" +#include "../components/EventHandler.hpp" #include "../components/PrefabInstance.hpp" #include "../ui/TransformEditor.hpp" @@ -1071,6 +1072,14 @@ void EditorUISystem::renderComponentList(flecs::entity entity) componentCount++; } + // Render EventHandler if present + if (entity.has()) { + auto &handler = entity.get_mut(); + m_componentRegistry.render(entity, + handler); + componentCount++; + } + // Show message if no components if (componentCount == 0) { diff --git a/src/features/editScene/ui/BehaviorTreeEditor.cpp b/src/features/editScene/ui/BehaviorTreeEditor.cpp index fa5b0f9..2b185cc 100644 --- a/src/features/editScene/ui/BehaviorTreeEditor.cpp +++ b/src/features/editScene/ui/BehaviorTreeEditor.cpp @@ -27,6 +27,8 @@ static ImU32 nodeTypeColorU32(const Ogre::String &type) return IM_COL32(0x80, 0x80, 0x80, 0xFF); if (type == "enablePhysics") return IM_COL32(0x4C, 0xCC, 0x4C, 0xFF); + if (type == "sendEvent") + return IM_COL32(0xFF, 0x99, 0x00, 0xFF); return IM_COL32(0xFF, 0xFF, 0xFF, 0xFF); } @@ -204,6 +206,8 @@ void BehaviorTreeEditor::renderTree(BehaviorTreeNode &node, queueAddChild(&node, "disablePhysics"); if (ImGui::MenuItem("Add Enable Physics")) queueAddChild(&node, "enablePhysics"); + if (ImGui::MenuItem("Add Send Event")) + queueAddChild(&node, "sendEvent"); } if (parent) { size_t idx = findChildIndex(*parent, &node); @@ -257,6 +261,8 @@ void BehaviorTreeEditor::renderTree(BehaviorTreeNode &node, queueAddChild(&node, "disablePhysics"); if (ImGui::MenuItem("Enable Physics")) queueAddChild(&node, "enablePhysics"); + if (ImGui::MenuItem("Send Event")) + queueAddChild(&node, "sendEvent"); ImGui::EndPopup(); } } @@ -310,7 +316,8 @@ void BehaviorTreeEditor::renderProperties(BehaviorTreeNode *node) "delay", "teleportToChild", "disablePhysics", - "enablePhysics" }; + "enablePhysics", + "sendEvent" }; int typeIdx = 0; for (int i = 0; i < IM_ARRAYSIZE(types); i++) { if (node->type == types[i]) { @@ -354,6 +361,9 @@ void BehaviorTreeEditor::renderProperties(BehaviorTreeNode *node) } else if (node->type == "teleportToChild") { label = "Child Name"; hint = "Name of child entity under Smart Object to teleport to"; + } else if (node->type == "sendEvent") { + label = "Event Name"; + hint = "Name of the event to send via EventBus"; } if (ImGui::InputText(label, buf, sizeof(buf))) @@ -363,7 +373,8 @@ void BehaviorTreeEditor::renderProperties(BehaviorTreeNode *node) // Params input for nodes that need it if (node->type == "setBit" || node->type == "setValue" || - node->type == "checkValue" || node->type == "delay") { + node->type == "checkValue" || node->type == "delay" || + node->type == "sendEvent") { char pbuf[256]; snprintf(pbuf, sizeof(pbuf), "%s", node->params.c_str()); @@ -376,6 +387,8 @@ void BehaviorTreeEditor::renderProperties(BehaviorTreeNode *node) phint = "Comparison: == 5, > 3.14, != 1,2,3"; else if (node->type == "delay") phint = "Duration in seconds (float, default 1.0)"; + else if (node->type == "sendEvent") + phint = "Event params: key=val key2=val2 ..."; if (ImGui::InputText("Params", pbuf, sizeof(pbuf))) node->params = pbuf; if (phint && ImGui::IsItemHovered()) diff --git a/src/features/editScene/ui/InlineBehaviorTreeEditor.cpp b/src/features/editScene/ui/InlineBehaviorTreeEditor.cpp index 46e2c96..8b274fb 100644 --- a/src/features/editScene/ui/InlineBehaviorTreeEditor.cpp +++ b/src/features/editScene/ui/InlineBehaviorTreeEditor.cpp @@ -96,6 +96,8 @@ static ImVec4 typeColorVec(const char *type) return ImVec4(0.5f, 0.5f, 0.5f, 1.0f); if (!strcmp(type, "enablePhysics")) return ImVec4(0.3f, 0.8f, 0.3f, 1.0f); + if (!strcmp(type, "sendEvent")) + return ImVec4(1.0f, 0.6f, 0.0f, 1.0f); return ImVec4(1.0f, 1.0f, 1.0f, 1.0f); } @@ -145,6 +147,12 @@ void InlineBehaviorTreeEditor::renderNode(BehaviorTreeNode &node, .childIndex = node.children.size(), .addType = "teleportToChild" }); } + if (ImGui::MenuItem("Add Send Event")) { + queueOp(EditOp{ .type = EditOp::Add, + .parent = &node, + .childIndex = node.children.size(), + .addType = "sendEvent" }); + } if (parent && ImGui::MenuItem("Remove")) { for (size_t i = 0; i < parent->children.size(); i++) { if (&parent->children[i] == &node) { @@ -260,7 +268,8 @@ void InlineBehaviorTreeEditor::renderProps(BehaviorTreeNode *node) "delay", "teleportToChild", "disablePhysics", - "enablePhysics" }; + "enablePhysics", + "sendEvent" }; int current = 0; for (int i = 0; i < IM_ARRAYSIZE(types); i++) { if (node->type == types[i]) { @@ -305,6 +314,9 @@ void InlineBehaviorTreeEditor::renderProps(BehaviorTreeNode *node) } else if (node->type == "teleportToChild") { label = "Child Name"; hint = "Name of child entity under Smart Object to teleport to"; + } else if (node->type == "sendEvent") { + label = "Event Name"; + hint = "Name of the event to send via EventBus"; } if (ImGui::InputText(label, buf, sizeof(buf))) @@ -314,7 +326,8 @@ void InlineBehaviorTreeEditor::renderProps(BehaviorTreeNode *node) // Params input for nodes that need it if (node->type == "setBit" || node->type == "setValue" || - node->type == "checkValue" || node->type == "delay") { + node->type == "checkValue" || node->type == "delay" || + node->type == "sendEvent") { char pbuf[256]; snprintf(pbuf, sizeof(pbuf), "%s", node->params.c_str()); @@ -327,6 +340,8 @@ void InlineBehaviorTreeEditor::renderProps(BehaviorTreeNode *node) phint = "Comparison: == 5, > 3.14, != 1,2,3"; else if (node->type == "delay") phint = "Duration in seconds (float, default 1.0)"; + else if (node->type == "sendEvent") + phint = "Event params: key=val key2=val2 ..."; if (ImGui::InputText("Params", pbuf, sizeof(pbuf))) node->params = pbuf; if (phint && ImGui::IsItemHovered())