From e3b90e8bba2974fff074e8146b345d08166702fe Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Tue, 14 Apr 2026 12:35:20 +0300 Subject: [PATCH] Fixed room connectivity code --- .../editScene/systems/RoomLayoutSystem.cpp | 29 +++++---- src/features/editScene/ui/RoomEditor.cpp | 64 +++++++++++++++---- src/features/editScene/ui/RoomEditor.hpp | 6 ++ 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/src/features/editScene/systems/RoomLayoutSystem.cpp b/src/features/editScene/systems/RoomLayoutSystem.cpp index 51c84d1..9806cd7 100644 --- a/src/features/editScene/systems/RoomLayoutSystem.cpp +++ b/src/features/editScene/systems/RoomLayoutSystem.cpp @@ -381,22 +381,29 @@ void RoomLayoutSystem::processRoomConnection(flecs::entity roomAEntity, const Ro // This mirrors the original Lua connectRooms() logic size_t index = 0; if (cellsA.size() > 1) { - // Calculate average (center) point + // Calculate average (center) point using the SAME method as original Lua + // Note: Original Lua uses integer division which truncates toward zero int sumX = 0, sumZ = 0; - for (const auto& cell : cellsA) { - sumX += cell.first; - sumZ += cell.second; + for (size_t i = 0; i < cellsA.size(); i++) { + sumX += cellsA[i].first; + sumZ += cellsA[i].second; } - int avgX = sumX / cellsA.size(); - int avgZ = sumZ / cellsA.size(); + sumX /= cellsA.size(); + sumZ /= cellsA.size(); - // Find closest point to average + + // Find closest point to average (using same logic as original Lua) + // Original: if (distance > mdx * mdx + mdz * mdz) - uses > not >= + // This keeps the first cell in case of ties int minDistance = -1; for (size_t i = 0; i < cellsA.size(); i++) { - int dx = cellsA[i].first - avgX; - int dz = cellsA[i].second - avgZ; - int dist = dx * dx + dz * dz; - if (minDistance == -1 || dist < minDistance) { + int mdx = cellsA[i].first - sumX; + int mdz = cellsA[i].second - sumZ; + int dist = mdx * mdx + mdz * mdz; + if (i == 0) { + index = 0; + minDistance = dist; + } else if (dist < minDistance) { minDistance = dist; index = i; } diff --git a/src/features/editScene/ui/RoomEditor.cpp b/src/features/editScene/ui/RoomEditor.cpp index 5f240e4..828d4df 100644 --- a/src/features/editScene/ui/RoomEditor.cpp +++ b/src/features/editScene/ui/RoomEditor.cpp @@ -121,8 +121,6 @@ bool RoomEditor::renderComponent(flecs::entity entity, RoomComponent& room) if (ImGui::CollapsingHeader("Connections", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::Indent(); - ImGui::Text("Connected to %zu room(s):", room.connectedRoomIds.size()); - // Build a map of persistent ID -> room info for displaying connections std::unordered_map roomMap; std::unordered_map roomLabels; @@ -138,15 +136,28 @@ bool RoomEditor::renderComponent(flecs::entity entity, RoomComponent& room) }); } + ImGui::Text("Connected to %zu room(s):", room.connectedRoomIds.size()); + // List current connections with remove buttons int removeIndex = -1; for (size_t i = 0; i < room.connectedRoomIds.size(); i++) { const std::string& connectedId = room.connectedRoomIds[i]; ImGui::PushID((int)i); - auto it = roomLabels.find(connectedId); - if (it != roomLabels.end()) { - ImGui::Text(" %zu: %s", i + 1, it->second.c_str()); + auto it = roomMap.find(connectedId); + if (it != roomMap.end()) { + // Check if rooms are actually adjacent + const auto& otherRoom = it->second.get(); + bool isAdjacent = areRoomsAdjacent(room, otherRoom); + + if (isAdjacent) { + ImGui::Text(" %zu: %s", i + 1, roomLabels[connectedId].c_str()); + } else { + // Mark non-adjacent connections in yellow + ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), + " %zu: %s (Not adjacent - will not create door)", + i + 1, roomLabels[connectedId].c_str()); + } } else { ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), " %zu: (Invalid room ID: %s)", i + 1, connectedId.c_str()); @@ -198,19 +209,28 @@ bool RoomEditor::renderComponent(flecs::entity entity, RoomComponent& room) if (availableRooms.empty()) { ImGui::TextDisabled(" No available rooms to connect"); } else { - static int selectedRoomIdx = 0; + // Use non-static index to avoid flickering when list changes + // Store index in a map keyed by entity ID + flecs::entity_t entityId = entity.id(); + if (m_selectedRoomIndex.find(entityId) == m_selectedRoomIndex.end()) { + m_selectedRoomIndex[entityId] = 0; + } + int& selectedRoomIdx = m_selectedRoomIndex[entityId]; if (selectedRoomIdx >= (int)availableRooms.size()) selectedRoomIdx = 0; - // Build combo items - std::string comboItems; + // Build combo items using ImGui style (null-terminated strings) + // Each item is terminated by \0, and the list is terminated by an extra \0 + std::vector comboItems; for (size_t i = 0; i < availableRoomLabels.size(); i++) { - if (i > 0) comboItems += "\0"; - comboItems += availableRoomLabels[i]; + for (char c : availableRoomLabels[i]) { + comboItems.push_back(c); + } + comboItems.push_back('\0'); // End of this item } - comboItems += "\0"; + comboItems.push_back('\0'); // End of list ImGui::PushID("add_conn"); - if (ImGui::Combo("Room", &selectedRoomIdx, comboItems.c_str())) { + if (ImGui::Combo("Room", &selectedRoomIdx, comboItems.data())) { // Selection changed } @@ -263,3 +283,23 @@ std::string RoomEditor::formatRoomLabel(flecs::entity entity, const RoomComponen return label; } + +bool RoomEditor::areRoomsAdjacent(const RoomComponent& roomA, const RoomComponent& roomB) +{ + // Two rooms are adjacent if they share at least one edge + // Check if roomB is directly adjacent to roomA on any side + + // Check Z- side of roomA (is roomB at z = roomA.minZ - 1 with overlapping X?) + if (roomB.maxZ == roomA.minZ && roomB.maxX > roomA.minX && roomB.minX < roomA.maxX) return true; + + // Check Z+ side of roomA + if (roomB.minZ == roomA.maxZ && roomB.maxX > roomA.minX && roomB.minX < roomA.maxX) return true; + + // Check X- side of roomA + if (roomB.maxX == roomA.minX && roomB.maxZ > roomA.minZ && roomB.minZ < roomA.maxZ) return true; + + // Check X+ side of roomA + if (roomB.minX == roomA.maxX && roomB.maxZ > roomA.minZ && roomB.minZ < roomA.maxZ) return true; + + return false; +} diff --git a/src/features/editScene/ui/RoomEditor.hpp b/src/features/editScene/ui/RoomEditor.hpp index 339c2fe..90cce12 100644 --- a/src/features/editScene/ui/RoomEditor.hpp +++ b/src/features/editScene/ui/RoomEditor.hpp @@ -15,4 +15,10 @@ private: // Format a room label for display in connection lists // Format: "Name [E:entityId P:persistentId] (Type)" std::string formatRoomLabel(flecs::entity entity, const RoomComponent& room); + + // Check if two rooms are adjacent (share at least one edge) + bool areRoomsAdjacent(const RoomComponent& roomA, const RoomComponent& roomB); + + // Track selected room index per entity to avoid static variable issues + std::unordered_map m_selectedRoomIndex; };