From 82e29cba15c827e09a29aeb2be24ce238d3113b6 Mon Sep 17 00:00:00 2001 From: Oznogon Date: Fri, 12 Dec 2025 12:20:23 -0800 Subject: [PATCH] Refactor DatabaseViewComponent - Use layout attributes to set padding on DatabaseScreen - Use layout attributes to set margins between between item list Back button and list, and between columns - Prevent extraneous bottom padding from being applied to item list - Prevent database details column from overlapping with crew screen/ main screen controls Also: - Add counting functions to PlayerInfo to support detecting when more than one crew screen is visible --- src/playerInfo.cpp | 25 ++++++ src/playerInfo.h | 2 + src/screenComponents/databaseView.cpp | 120 ++++++++++++++++++-------- src/screenComponents/databaseView.h | 12 +-- src/screens/crew6/scienceScreen.cpp | 18 +++- src/screens/extra/databaseScreen.cpp | 26 +++++- src/screens/extra/databaseScreen.h | 7 +- 7 files changed, 161 insertions(+), 49 deletions(-) diff --git a/src/playerInfo.cpp b/src/playerInfo.cpp index ac57decafe..7a675b5e5d 100644 --- a/src/playerInfo.cpp +++ b/src/playerInfo.cpp @@ -142,6 +142,31 @@ void PlayerInfo::reset() crew_positions.clear(); } +// Return the total number of positions populated by this player. +int PlayerInfo::countTotalPlayerPositions() +{ + if (crew_positions.empty()) return 0; + + int count = 0; + for (auto monitor : crew_positions) + for (auto position : monitor) count++; + + LOG(Info, "count: ", count); + return count; +} + +// Return the total number of positions populated by this player. +int PlayerInfo::countPlayerPositionsOnMonitor(int monitor) +{ + if (crew_positions.empty()) return 0; + + int count = 0; + for (auto position : crew_positions[monitor]) count++; + + LOG(Info, "count: ", count); + return count; +} + bool PlayerInfo::hasPosition(CrewPosition cp) { for(auto cps : crew_positions) { diff --git a/src/playerInfo.h b/src/playerInfo.h index 0548addd1b..633e0e01fc 100644 --- a/src/playerInfo.h +++ b/src/playerInfo.h @@ -30,6 +30,8 @@ class PlayerInfo : public MultiplayerObject void reset(); + int countTotalPlayerPositions(); + int countPlayerPositionsOnMonitor(int monitor); bool hasPosition(CrewPosition cp); bool isOnlyMainScreen(int monitor_index); diff --git a/src/screenComponents/databaseView.cpp b/src/screenComponents/databaseView.cpp index 4aa295a7f7..9df8b9b689 100644 --- a/src/screenComponents/databaseView.cpp +++ b/src/screenComponents/databaseView.cpp @@ -3,6 +3,7 @@ #include "components/database.h" #include "components/rendering.h" #include "ecs/query.h" +#include "playerInfo.h" #include "gui/gui2_listbox.h" #include "gui/gui2_image.h" @@ -17,19 +18,33 @@ DatabaseViewComponent::DatabaseViewComponent(GuiContainer* owner) { setAttribute("layout", "horizontal"); - // Setup the navigation bar - GuiElement* navigation_element = new GuiElement(this, "NAVIGATION_BAR"); - navigation_element->setAttribute("layout", "vertical"); - navigation_element->setMargins(20, 20, 20, 120)->setSize(navigation_width, GuiElement::GuiSizeMax); - back_button = new GuiButton(navigation_element,"BACK_BUTTON", "Back", [this](){ - selected_entry = sp::ecs::Entity::fromString(back_entry); - display(); - }); - back_button->setSize(GuiElement::GuiSizeMax, 50)->hide()->setMargins(0, 0, 0, 20); - item_list = new GuiListbox(navigation_element, "DATABASE_ITEM_LIST", [this](int index, string value) { - selected_entry = sp::ecs::Entity::fromString(value); - display(); - }); + // Setup the navigation bar. + navigation_element = new GuiElement(this, "DB_NAV_BAR"); + navigation_element + ->setSize(navigation_width, GuiElement::GuiSizeMax) + ->setAttribute("layout", "vertical"); + navigation_element + ->setAttribute("margin", "0, 20, 0, 0"); + + back_button = new GuiButton(navigation_element, "DB_BACK_BUTTON", tr("databaseView", "Back"), + [this]() + { + selected_entry = sp::ecs::Entity::fromString(back_entry); + display(); + } + ); + back_button + ->setSize(GuiElement::GuiSizeMax, 50.0f) + ->hide() + ->setAttribute("margin", "0, 0, 0, 20"); + + item_list = new GuiListbox(navigation_element, "DB_ITEM_LIST", + [this](int index, string value) + { + selected_entry = sp::ecs::Entity::fromString(value); + display(); + } + ); item_list->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); display(); } @@ -48,6 +63,18 @@ bool DatabaseViewComponent::findAndDisplayEntry(string name) return false; } +DatabaseViewComponent* DatabaseViewComponent::setDetailsPadding(int padding) +{ + details_padding = std::max(0, padding); + return this; +} + +DatabaseViewComponent* DatabaseViewComponent::setItemsPadding(int padding) +{ + items_padding = std::max(0, padding); + return this; +} + void DatabaseViewComponent::fillListBox() { item_list->setOptions({}); @@ -115,58 +142,77 @@ void DatabaseViewComponent::fillListBox() void DatabaseViewComponent::display() { - if (keyvalue_container) - keyvalue_container->destroy(); - if (details_container) - details_container->destroy(); - - keyvalue_container = new GuiElement(this, "KEY_VALUE_CONTAINER"); - keyvalue_container->setMargins(20)->setSize(400, GuiElement::GuiSizeMax)->setAttribute("layout", "vertical"); - - details_container = new GuiElement(this, "DETAILS_CONTAINER"); - details_container->setMargins(20)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax)->setAttribute("layout", "vertical"); - details_container->layout.padding.top = 50; + if (keyvalue_container) keyvalue_container->destroy(); + if (details_container) details_container->destroy(); + + keyvalue_container = new GuiElement(this, "DB_KV_CONTAINER"); + keyvalue_container + ->setSize(400.0f, GuiElement::GuiSizeMax) + ->setAttribute("layout", "vertical"); + + details_container = new GuiElement(this, "DB_DETAILS_CONTAINER"); + details_container + ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax) + ->setAttribute("layout", "vertical"); + details_container + ->setAttribute("margin", "20, 0, 0, 0"); + // Set conditional padding on details and item lists. + details_container + ->setAttribute("padding", "0, 0, " + static_cast(details_padding) + ", 0"); + + navigation_element + ->setAttribute("padding", "0, 0, 0, " + static_cast(items_padding)); fillListBox(); auto database = selected_entry.getComponent(); - if (!database) - return; - auto mrc = selected_entry.getComponent(); + if (!database) return; + auto mrc = selected_entry.getComponent(); bool has_key_values = database->key_values.size() > 0; bool has_image_or_model = mrc || database->image != ""; bool has_text = database->description.length() > 0; if (has_image_or_model) { - GuiElement* visual = (new GuiElement(details_container, "DATABASE_VISUAL_ELEMENT"))->setMargins(0, 0, 0, 40)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + GuiElement* visual = (new GuiElement(details_container, "DB_VISUAL_ELEMENT")) + ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); if (mrc) { - (new GuiRotatingModelView(visual, "DATABASE_MODEL_VIEW", selected_entry)) + (new GuiRotatingModelView(visual, "DB_MODEL_VIEW", selected_entry)) ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); - if(database->image != "") + + if (database->image != "") { - (new GuiImage(visual, "DATABASE_IMAGE", database->image))->setMargins(0)->setSize(32, 32); + (new GuiImage(visual, "DB_IMAGE", database->image)) + ->setSize(32.0f, 32.0f); } } else if(database->image != "") { - auto image = new GuiImage(visual, "DATABASE_IMAGE", database->image); - image->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + (new GuiImage(visual, "DB_IMAGE", database->image)) + ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); } } + if (has_text) { - (new GuiScrollFormattedText(details_container, "DATABASE_LONG_DESCRIPTION", database->description))->setTextSize(24)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + (new GuiScrollFormattedText(details_container, "DB_LONG_DESCRIPTION", database->description)) + ->setTextSize(24.0f) + ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); } if (has_key_values) { - for(auto& kv : database->key_values) - (new GuiKeyValueDisplay(keyvalue_container, "", 0.37, kv.key, kv.value))->setSize(GuiElement::GuiSizeMax, 40); - } else { + for (auto& kv : database->key_values) + { + (new GuiKeyValueDisplay(keyvalue_container, "", 0.37f, kv.key, kv.value)) + ->setSize(GuiElement::GuiSizeMax, 40.0f); + } + } + else + { keyvalue_container->destroy(); keyvalue_container = nullptr; } diff --git a/src/screenComponents/databaseView.h b/src/screenComponents/databaseView.h index 955d75c8f2..a173791ce9 100644 --- a/src/screenComponents/databaseView.h +++ b/src/screenComponents/databaseView.h @@ -1,5 +1,4 @@ -#ifndef DATABASE_VIEW_H -#define DATABASE_VIEW_H +#pragma once #include "gui/gui2_element.h" #include "ecs/entity.h" @@ -13,21 +12,24 @@ class DatabaseViewComponent : public GuiElement DatabaseViewComponent(GuiContainer* owner); bool findAndDisplayEntry(string name); + DatabaseViewComponent* setDetailsPadding(int padding); + DatabaseViewComponent* setItemsPadding(int padding); private: bool findAndDisplayEntry(string name, sp::ecs::Entity parent); - //Fill the selection listbox with options from the selected_entry, or the main database list if selected_entry is nullptr + // Fill the selection listbox with options from the selected_entry, or the main database list if selected_entry is nullptr void fillListBox(); void display(); sp::ecs::Entity selected_entry; string back_entry; + GuiElement* navigation_element = nullptr; GuiButton* back_button = nullptr; GuiListbox* item_list = nullptr; GuiElement* keyvalue_container = nullptr; GuiElement* details_container = nullptr; static constexpr int navigation_width = 400; + int details_padding = 0; + int items_padding = 0; }; - -#endif//DATABASE_VIEW_H diff --git a/src/screens/crew6/scienceScreen.cpp b/src/screens/crew6/scienceScreen.cpp index 94d628c5da..79ff906a62 100644 --- a/src/screens/crew6/scienceScreen.cpp +++ b/src/screens/crew6/scienceScreen.cpp @@ -185,7 +185,23 @@ ScienceScreen::ScienceScreen(GuiContainer* owner, CrewPosition crew_position) // Prep and hide the database view. database_view = new DatabaseViewComponent(this); - database_view->hide()->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + database_view + ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax) + ->hide() + ->setAttribute("padding", "20"); + + // Pad top of details column if crew screen selection controls are visible, + // and bottom of item list column to prevent overlap with probe/radar view + // selectors. + int details_padding = 0; + if (my_player_info) + { + if (my_player_info->main_screen_control != 0) details_padding = 120; + else if (my_player_info->countTotalPlayerPositions() > 1) details_padding = 70; + } + database_view + ->setDetailsPadding(details_padding) + ->setItemsPadding(120); // Probe view button probe_view_button = new GuiToggleButton(radar_view, "PROBE_VIEW", tr("scienceButton", "Probe View"), [this](bool value){ diff --git a/src/screens/extra/databaseScreen.cpp b/src/screens/extra/databaseScreen.cpp index 233a776f54..626cd024e8 100644 --- a/src/screens/extra/databaseScreen.cpp +++ b/src/screens/extra/databaseScreen.cpp @@ -1,4 +1,5 @@ #include "databaseScreen.h" +#include "playerInfo.h" #include "screenComponents/databaseView.h" #include "screenComponents/customShipFunctions.h" @@ -6,7 +7,28 @@ DatabaseScreen::DatabaseScreen(GuiContainer* owner) : GuiOverlay(owner, "DATABASE_SCREEN", colorConfig.background) { - (new DatabaseViewComponent(this))->setPosition(0, 0, sp::Alignment::TopLeft)->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + // Render background decorations. + (new GuiOverlay(this, "BACKGROUND_CROSSES", glm::u8vec4{255,255,255,255})) + ->setTextureTiled("gui/background/crosses.png"); - (new GuiCustomShipFunctions(this, CrewPosition::databaseView, ""))->setPosition(-20, 120, sp::Alignment::TopRight)->setSize(250, GuiElement::GuiSizeMax); + // Render database. + DatabaseViewComponent* dvc = new DatabaseViewComponent(this); + dvc->setPosition(0.0f, 0.0f, sp::Alignment::TopLeft) + ->setSize(GuiElement::GuiSizeMax, GuiElement::GuiSizeMax); + dvc->setAttribute("padding", "20"); + + // Pad top of details column if crew screen selection controls are visible. + int details_padding = 0; + if (my_player_info) + { + if (my_player_info->main_screen_control != 0) details_padding = 120; + else if (my_player_info->countTotalPlayerPositions() > 1) details_padding = 70; + } + dvc->setDetailsPadding(details_padding); + + // Render Databse View custom ship functions. + (new GuiCustomShipFunctions(this, CrewPosition::databaseView, "DB_CUSTOM_SHIP_FUNCTIONS")) + ->setSize(250.0f, GuiElement::GuiSizeMax) + ->setPosition(0.0f, 0.0f, sp::Alignment::TopRight) + ->setAttribute("padding", "0, 20, 120, 0"); } diff --git a/src/screens/extra/databaseScreen.h b/src/screens/extra/databaseScreen.h index 370df5bb76..79ed9200e9 100644 --- a/src/screens/extra/databaseScreen.h +++ b/src/screens/extra/databaseScreen.h @@ -1,13 +1,12 @@ -#ifndef DATABASE_SCREEN_H -#define DATABASE_SCREEN_H +#pragma once #include "gui/gui2_overlay.h" +class DatabaseViewComponent; + class DatabaseScreen : public GuiOverlay { private: public: DatabaseScreen(GuiContainer* owner); }; - -#endif//DATABASE_SCREEN_H