From 79b6af1fff8fe9e350b8dbdec61fcced57d02298 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Thu, 16 Apr 2026 17:11:12 +0300 Subject: [PATCH] Furniture vertical offset --- .../editScene/components/CellGrid.hpp | 1 + .../editScene/systems/CellGridSystem.cpp | 16 ++++++++++++++-- .../editScene/systems/EditorUISystem.cpp | 3 ++- .../editScene/systems/SceneSerializer.cpp | 2 ++ src/features/editScene/ui/RoomEditor.cpp | 19 +++++++++++++++++++ 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/features/editScene/components/CellGrid.hpp b/src/features/editScene/components/CellGrid.hpp index 4ec69c7..bc7e6fc 100644 --- a/src/features/editScene/components/CellGrid.hpp +++ b/src/features/editScene/components/CellGrid.hpp @@ -209,6 +209,7 @@ struct RoomComponent { bool createWindows = false; // Convert exterior-facing walls to windows bool fillRoomWithFurniture = false; // Automatically place furniture based on tags unsigned int furnitureSeed = 42; // Seed for deterministic furniture placement + float furnitureYOffset = 0.05f; // Y offset for all furniture in this room // Dirty flag - triggers regeneration of cell grid bool dirty = true; diff --git a/src/features/editScene/systems/CellGridSystem.cpp b/src/features/editScene/systems/CellGridSystem.cpp index 775a160..82ec8ee 100644 --- a/src/features/editScene/systems/CellGridSystem.cpp +++ b/src/features/editScene/systems/CellGridSystem.cpp @@ -2389,8 +2389,20 @@ void CellGridSystem::buildFurniture(flecs::entity entity, Ogre::Vector3 pos = grid.cellToWorld(fcell.x, fcell.y, fcell.z); - // Apply small Y offset so furniture sits on floor - pos.y += 0.05f; + // Determine Y offset from the room that contains this furniture cell + float furnitureYOffset = 0.05f; + bool foundRoom = false; + entity.children([&](flecs::entity child) { + if (foundRoom) return; + if (child.has()) { + const auto &room = child.get(); + if (room.contains(fcell.x, fcell.y, fcell.z)) { + furnitureYOffset = room.furnitureYOffset; + foundRoom = true; + } + } + }); + pos.y += furnitureYOffset; Ogre::Quaternion localRot( Ogre::Degree(90.0f * fcell.rotation), Ogre::Vector3::UNIT_Y); diff --git a/src/features/editScene/systems/EditorUISystem.cpp b/src/features/editScene/systems/EditorUISystem.cpp index 98c4f2e..9fdbee5 100644 --- a/src/features/editScene/systems/EditorUISystem.cpp +++ b/src/features/editScene/systems/EditorUISystem.cpp @@ -223,7 +223,8 @@ void EditorUISystem::renderHierarchyWindow() ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_MenuBar; + ImGuiWindowFlags_NoResize | ImGuiWindowFlags_MenuBar | + ImGuiWindowFlags_HorizontalScrollbar; if (ImGui::Begin("Entity Hierarchy", nullptr, windowFlags)) { // Menu bar diff --git a/src/features/editScene/systems/SceneSerializer.cpp b/src/features/editScene/systems/SceneSerializer.cpp index d5be8af..89dcc5e 100644 --- a/src/features/editScene/systems/SceneSerializer.cpp +++ b/src/features/editScene/systems/SceneSerializer.cpp @@ -1409,6 +1409,7 @@ nlohmann::json SceneSerializer::serializeRoom(flecs::entity entity) json["createWindows"] = room.createWindows; json["fillRoomWithFurniture"] = room.fillRoomWithFurniture; json["furnitureSeed"] = room.furnitureSeed; + json["furnitureYOffset"] = room.furnitureYOffset; // Serialize exits (bool array for Z-, Z+, X-, X+) nlohmann::json exits = nlohmann::json::array(); @@ -1662,6 +1663,7 @@ void SceneSerializer::deserializeRoom(flecs::entity entity, const nlohmann::json room.createWindows = json.value("createWindows", false); room.fillRoomWithFurniture = json.value("fillRoomWithFurniture", false); room.furnitureSeed = json.value("furnitureSeed", 42u); + room.furnitureYOffset = json.value("furnitureYOffset", 0.05f); // Load exits (bool array for Z-, Z+, X-, X+) if (json.contains("exits") && json["exits"].is_array()) { diff --git a/src/features/editScene/ui/RoomEditor.cpp b/src/features/editScene/ui/RoomEditor.cpp index ff4b990..777c06f 100644 --- a/src/features/editScene/ui/RoomEditor.cpp +++ b/src/features/editScene/ui/RoomEditor.cpp @@ -50,6 +50,9 @@ bool RoomEditor::renderComponent(flecs::entity entity, RoomComponent& room) room.furnitureSeed = static_cast(seed); modified = true; } + if (ImGui::DragFloat("Furniture Y Offset", &room.furnitureYOffset, 0.01f, 0.0f, 0.5f)) { + modified = true; + } ImGui::TextDisabled("Change seed for different furniture arrangement"); ImGui::TextDisabled("(Windows are created after all doors)"); @@ -196,6 +199,8 @@ bool RoomEditor::renderComponent(flecs::entity entity, RoomComponent& room) // List current connections with remove buttons int removeIndex = -1; + float contentRight = ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x; + float maxRowRight = 0.0f; for (size_t i = 0; i < room.connectedRoomIds.size(); i++) { const std::string& connectedId = room.connectedRoomIds[i]; ImGui::PushID((int)i); @@ -224,9 +229,23 @@ bool RoomEditor::renderComponent(flecs::entity entity, RoomComponent& room) removeIndex = (int)i; modified = true; } + + maxRowRight = std::max(maxRowRight, + ImGui::GetItemRectMax().x - ImGui::GetWindowPos().x); ImGui::PopID(); } + /* Ensure the horizontal scrollbar thumb appears when connection + * rows overflow the panel width. ImGui culls off-screen widgets, + * so we explicitly extend the content width with a dummy. */ + float savedX = ImGui::GetCursorPosX(); + float savedY = ImGui::GetCursorPosY(); + if (maxRowRight > contentRight) { + ImGui::SetCursorPosX(0.0f); + ImGui::Dummy(ImVec2(maxRowRight + 1.0f, 0.0f)); + ImGui::SetCursorPos(ImVec2(savedX, savedY)); + } + if (removeIndex >= 0) { // Remove from this room std::string removedId = room.connectedRoomIds[removeIndex];