16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 00:49:19 +02:00

Launcher improvements

Launcher windows are more Starter-like now:
- The scenery picker, vehicle list and keymapper buttons are now tied to the top portion of the screen.
- The current window is spanning the entire rest of the screen.
- Scenarios are now grouped into categories in the exact same way as Starter does.
- Some drawbacks include:
  - Currently you cannot edit the current trainset, as the vehicle picker window overwrites the scenario list window.
  - The GUI doesn't update when the screen resolution is changed.
This commit is contained in:
jakubg1
2025-09-09 16:40:04 +02:00
parent 22c0aed82d
commit c217081823
12 changed files with 335 additions and 334 deletions

View File

@@ -36,69 +36,60 @@ bool ui::keymapper_panel::key(int key)
return true; return true;
} }
void ui::keymapper_panel::render() void ui::keymapper_panel::render_contents()
{ {
if (!is_open) if (ImGui::Button(STR_C("Load")))
return; keyboard.init();
auto const panelname{(title.empty() ? m_name : title) + "###" + m_name}; ImGui::SameLine();
if (ImGui::Begin(panelname.c_str(), &is_open)) { if (ImGui::Button(STR_C("Save")))
if (ImGui::Button(STR_C("Load"))) keyboard.dump_bindings();
keyboard.init();
ImGui::SameLine(); for (const std::pair<user_command, std::tuple<int, std::string>> &binding : keyboard.bindings()) {
// Binding ID
ImGui::AlignTextToFramePadding();
ImGui::Text(simulation::Commands_descriptions[static_cast<std::size_t>(binding.first)].name.c_str());
if (ImGui::Button(STR_C("Save"))) // Binding description
keyboard.dump_bindings(); std::string description = std::get<std::string>(binding.second);
ImGui::SameLine(260);
ImGui::Text((description.size() > 0 ? description : "(No description)").c_str());
for (const std::pair<user_command, std::tuple<int, std::string>> &binding : keyboard.bindings()) { // Binding key button
// Binding ID int keycode = std::get<int>(binding.second);
ImGui::AlignTextToFramePadding(); std::string label;
ImGui::Text(simulation::Commands_descriptions[static_cast<std::size_t>(binding.first)].name.c_str());
// Binding description if (keycode & keyboard_input::keymodifier::control)
std::string description = std::get<std::string>(binding.second); label += "ctrl + ";
ImGui::SameLine(260); if (keycode & keyboard_input::keymodifier::shift)
ImGui::Text((description.size() > 0 ? description : "(No description)").c_str()); label += "shift + ";
// Binding key button auto it = keyboard.keytonamemap.find(keycode & 0xFFFF);
int keycode = std::get<int>(binding.second); if (it != keyboard.keytonamemap.end())
std::string label; label += it->second;
if (keycode & keyboard_input::keymodifier::control) label = ToUpper(label);
label += "ctrl + ";
if (keycode & keyboard_input::keymodifier::shift)
label += "shift + ";
auto it = keyboard.keytonamemap.find(keycode & 0xFFFF); bool styles_pushed = false;
if (it != keyboard.keytonamemap.end()) if (bind_active == binding.first) {
label += it->second; label = "Press key (F10 to unbind)";
ImVec4 active_col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive);
label = ToUpper(label); ImGui::PushStyleColor(ImGuiCol_Button, active_col);
styles_pushed = true;
bool styles_pushed = false;
if (bind_active == binding.first) {
label = "Press key (F10 to unbind)";
ImVec4 active_col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonActive);
ImGui::PushStyleColor(ImGuiCol_Button, active_col);
styles_pushed = true;
}
label += "##" + std::to_string((int)binding.first);
ImGui::SameLine(ImGui::GetContentRegionAvailWidth() - 150);
if (ImGui::Button(label.c_str(), ImVec2(150, 0))) {
if (bind_active == binding.first)
bind_active = user_command::none;
else
bind_active = binding.first;
}
if (styles_pushed)
ImGui::PopStyleColor();
} }
}
ImGui::End(); label += "##" + std::to_string((int)binding.first);
ImGui::SameLine(ImGui::GetContentRegionAvailWidth() - 150);
if (ImGui::Button(label.c_str(), ImVec2(150, 0))) {
if (bind_active == binding.first)
bind_active = user_command::none;
else
bind_active = binding.first;
}
if (styles_pushed)
ImGui::PopStyleColor();
}
} }

View File

@@ -10,12 +10,12 @@ class keymapper_panel : public ui_panel
public: public:
keymapper_panel(); keymapper_panel();
void render() override; void render_contents() override;
bool key(int key); bool key(int key);
private: private:
driverkeyboard_input keyboard; driverkeyboard_input keyboard;
user_command bind_active = user_command::none; user_command bind_active = user_command::none;
const std::string panelname = (title.empty() ? m_name : title) + "###" + m_name;
}; };
} // namespace ui } // namespace ui

View File

@@ -1,8 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "launcher/launcheruilayer.h" #include "launcher/launcheruilayer.h"
#include "application.h" #include "application.h"
#include "translation.h"
#include "Logs.h"
launcher_ui::launcher_ui() launcher_ui::launcher_ui()
: m_scenery_scanner(m_vehicles_bank), m_scenerylist_panel(m_scenery_scanner) : m_scenery_scanner(m_vehicles_bank), m_scenerylist_panel(m_scenery_scanner)
{ {
@@ -13,11 +13,16 @@ launcher_ui::launcher_ui()
add_external_panel(&m_keymapper_panel); add_external_panel(&m_keymapper_panel);
add_external_panel(&m_vehiclepicker_panel); add_external_panel(&m_vehiclepicker_panel);
open_panel(&m_vehiclepicker_panel);
m_suppress_menu = true;
load_random_background(); load_random_background();
} }
bool launcher_ui::on_key(const int Key, const int Action) bool launcher_ui::on_key(const int Key, const int Action)
{ {
if (m_scenerylist_panel.on_key(Key, Action))
return true;
if (m_keymapper_panel.key(Key)) if (m_keymapper_panel.key(Key))
return true; return true;
@@ -26,20 +31,41 @@ bool launcher_ui::on_key(const int Key, const int Action)
void launcher_ui::render_() void launcher_ui::render_()
{ {
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse; ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove;
ImVec2 display_size = ImGui::GetIO().DisplaySize; const float topbar_height = 50 * Global.ui_scale;
ImGui::SetNextWindowPos(ImVec2(display_size.x * 0.66f, display_size.y / 2.0f)); const ImVec2 topbar_button_size = ImVec2(150 * Global.ui_scale, topbar_height - 16);
ImGui::SetNextWindowSize(ImVec2(200 * Global.ui_scale, -1)); ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowSize(ImVec2(Global.window_size.x, topbar_height));
if (ImGui::Begin(STR_C("Main menu"), nullptr, flags)) { if (ImGui::Begin(STR_C("Main menu"), nullptr, flags)) {
if (ImGui::Button(STR_C("Scenario list"), ImVec2(-1, 0))) if (ImGui::Button(STR_C("Scenario list"), topbar_button_size))
m_scenerylist_panel.is_open = !m_scenerylist_panel.is_open; open_panel(&m_scenerylist_panel);
if (ImGui::Button(STR_C("Vehicle list"), ImVec2(-1, 0))) ImGui::SameLine();
m_vehiclepicker_panel.is_open = !m_vehiclepicker_panel.is_open; if (ImGui::Button(STR_C("Vehicle list"), topbar_button_size))
if (ImGui::Button(STR_C("Keymapper"), ImVec2(-1, 0))) open_panel(&m_vehiclepicker_panel);
m_keymapper_panel.is_open = !m_keymapper_panel.is_open; ImGui::SameLine();
if (ImGui::Button(STR_C("Quit"), ImVec2(-1, 0))) if (ImGui::Button(STR_C("Keymapper"), topbar_button_size))
open_panel(&m_keymapper_panel);
ImGui::SameLine();
if (ImGui::Button(STR_C("Quit"), topbar_button_size))
Application.queue_quit(false); Application.queue_quit(false);
} }
ImGui::End(); ImGui::End();
} }
void launcher_ui::close_panels()
{
m_scenerylist_panel.is_open = false;
m_vehiclepicker_panel.is_open = false;
m_keymapper_panel.is_open = false;
}
void launcher_ui::open_panel(ui_panel* panel)
{
close_panels();
const float topbar_height = 50 * Global.ui_scale;
panel->pos = glm::vec2(0, topbar_height);
panel->size = glm::vec2(Global.window_size.x, Global.window_size.y - topbar_height);
panel->no_title_bar = true;
panel->is_open = true;
}

View File

@@ -23,6 +23,8 @@ public:
private: private:
void render_() override; void render_() override;
void close_panels();
void open_panel(ui_panel *panel);
ui::vehicles_bank m_vehicles_bank; ui::vehicles_bank m_vehicles_bank;
scenery_scanner m_scenery_scanner; scenery_scanner m_scenery_scanner;

View File

@@ -5,6 +5,8 @@
#include "renderer.h" #include "renderer.h"
#include "application.h" #include "application.h"
#include "Logs.h" #include "Logs.h"
#include "translation.h"
#include <filesystem> #include <filesystem>
ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner) ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner)
@@ -12,6 +14,21 @@ ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner)
{ {
} }
bool ui::scenerylist_panel::on_key(int key, int action)
{
if (!is_open)
return false;
auto it = keyboard.keytonamemap.find(key);
if (it == keyboard.keytonamemap.end())
return false;
if (Global.ctrlState && it->second == "delete")
purge_selected_trainset();
return true;
}
void ui::scenerylist_panel::draw_scenery_list() void ui::scenerylist_panel::draw_scenery_list()
{ {
// Draw all the scenarios which are not assigned to any category. // Draw all the scenarios which are not assigned to any category.
@@ -355,6 +372,11 @@ void ui::scenerylist_panel::draw_droptarget(trainset_desc &trainset, int positio
} }
} }
void ui::scenerylist_panel::purge_selected_trainset()
{
selected_trainset->vehicles.clear();
}
ui::dynamic_edit_popup::dynamic_edit_popup(ui_panel &panel, dynamic_desc &dynamic) ui::dynamic_edit_popup::dynamic_edit_popup(ui_panel &panel, dynamic_desc &dynamic)
: popup(panel), dynamic(dynamic) : popup(panel), dynamic(dynamic)
{ {

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "driverkeyboardinput.h"
#include "uilayer.h" #include "uilayer.h"
#include "scenery_scanner.h" #include "scenery_scanner.h"
#include "widgets/popup.h" #include "widgets/popup.h"
@@ -35,8 +36,11 @@ class scenerylist_panel : public ui_panel
scenerylist_panel(scenery_scanner &scanner); scenerylist_panel(scenery_scanner &scanner);
void render_contents() override; void render_contents() override;
bool on_key(int key, int action);
private: private:
driverkeyboard_input keyboard;
struct vehicle_moved { struct vehicle_moved {
trainset_desc &source; trainset_desc &source;
dynamic_desc &dynamic; dynamic_desc &dynamic;
@@ -63,5 +67,6 @@ private:
void open_link(const std::string &link); void open_link(const std::string &link);
void draw_trainset(trainset_desc &trainset); void draw_trainset(trainset_desc &trainset);
void draw_droptarget(trainset_desc &trainset, int position); void draw_droptarget(trainset_desc &trainset, int position);
void purge_selected_trainset();
}; };
} // namespace ui } // namespace ui

View File

@@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "launcher/vehicle_picker.h" #include "launcher/vehicle_picker.h"
#include "renderer.h" #include "renderer.h"
#include "translation.h"
ui::vehiclepicker_panel::vehiclepicker_panel() ui::vehiclepicker_panel::vehiclepicker_panel()
: ui_panel(STR("Select vehicle"), false), placeholder_mini("textures/mini/other") : ui_panel(STR("Select vehicle"), false), placeholder_mini("textures/mini/other")
@@ -8,195 +9,170 @@ ui::vehiclepicker_panel::vehiclepicker_panel()
bank.scan_textures(); bank.scan_textures();
} }
void ui::vehiclepicker_panel::render() void ui::vehiclepicker_panel::render_contents()
{ {
if (!is_open) ImGui::Columns(3);
return;
static std::map<vehicle_type, std::string> type_names = ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.0f, 0.5f));
{
{ vehicle_type::electric_loco, STRN("Electric locos") },
{ vehicle_type::diesel_loco, STRN("Diesel locos") },
{ vehicle_type::steam_loco, STRN("Steam locos") },
{ vehicle_type::railcar, STRN("Railcars") },
{ vehicle_type::emu, STRN("EMU") },
{ vehicle_type::utility, STRN("Utility") },
{ vehicle_type::draisine, STRN("Draisines") },
{ vehicle_type::tram, STRN("Trams") },
{ vehicle_type::carriage, STRN("Carriages") },
{ vehicle_type::truck, STRN("Trucks") },
{ vehicle_type::bus, STRN("Buses") },
{ vehicle_type::car, STRN("Cars") },
{ vehicle_type::man, STRN("People") },
{ vehicle_type::animal, STRN("Animals") },
{ vehicle_type::unknown, STRN("Unknown") }
};
if (ImGui::Begin(m_name.c_str(), &is_open)) { if (ImGui::BeginChild("box1")) {
ImGui::Columns(3); for (auto const &e : type_names) {
deferred_image *image = nullptr;
auto it = bank.category_icons.find(e.first);
if (it != bank.category_icons.end())
image = &it->second;
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.0f, 0.5f)); if (selectable_image(Translations.lookup_s(e.second).c_str(), e.first == selected_type, image))
selected_type = e.first;
}
}
ImGui::EndChild();
ImGui::NextColumn();
if (ImGui::BeginChild("box1")) { ImGui::TextUnformatted(STR_C("Group by: "));
for (auto const &e : type_names) { ImGui::SameLine();
deferred_image *image = nullptr; if (ImGui::RadioButton(STR_C("type"), !display_by_groups))
auto it = bank.category_icons.find(e.first); display_by_groups = false;
if (it != bank.category_icons.end()) ImGui::SameLine();
image = &it->second; if (ImGui::RadioButton(STR_C("texture group"), display_by_groups))
display_by_groups = true;
if (selectable_image(Translations.lookup_s(e.second).c_str(), e.first == selected_type, image)) std::vector<const skin_set*> skinset_list;
selected_type = e.first;
if (display_by_groups) {
std::vector<const std::string*> model_list;
for (auto const &kv : bank.group_map) {
const std::string &group = kv.first;
bool model_added = false;
bool can_break = false;
bool map_sel_eq = (selected_group && group == *selected_group);
for (auto const &vehicle : kv.second) {
if (vehicle->type != selected_type)
continue;
for (auto const &skinset : vehicle->matching_skinsets) {
bool map_group_eq = (skinset->group == group);
bool sel_group_eq = (selected_group && skinset->group == *selected_group);
if (!model_added && map_group_eq) {
model_list.push_back(&group);
model_added = true;
}
if (map_sel_eq) {
if (sel_group_eq)
skinset_list.push_back(skinset.get());
}
else if (model_added) {
can_break = true;
break;
}
}
if (can_break)
break;
} }
} }
ImGui::EndChild();
ImGui::NextColumn();
ImGui::TextUnformatted(STR_C("Group by: ")); if (ImGui::BeginChild("box2")) {
ImGui::SameLine(); ImGuiListClipper clipper(model_list.size());
if (ImGui::RadioButton(STR_C("type"), !display_by_groups)) while (clipper.Step())
display_by_groups = false; for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
ImGui::SameLine(); auto group = model_list[i];
if (ImGui::RadioButton(STR_C("texture group"), display_by_groups))
display_by_groups = true;
std::vector<const skin_set*> skinset_list; deferred_image *image = nullptr;
auto it = bank.group_icons.find(*group);
if (it != bank.group_icons.end())
image = &it->second;
if (display_by_groups) { if (selectable_image(group->c_str(), group == selected_group, image))
std::vector<const std::string*> model_list; selected_group = group;
}
}
}
else {
std::vector<std::shared_ptr<const vehicle_desc>> model_list;
for (auto const &kv : bank.group_map) { for (auto const &v : bank.vehicles) {
const std::string &group = kv.first; auto desc = v.second;
bool model_added = false; if (selected_type == desc->type && desc->matching_skinsets.size() > 0)
bool can_break = false; model_list.push_back(desc);
bool map_sel_eq = (selected_group && group == *selected_group);
for (auto const &vehicle : kv.second) { if (selected_vehicle == desc && selected_type == desc->type) {
if (vehicle->type != selected_type) for (auto &skin : desc->matching_skinsets)
continue; skinset_list.push_back(skin.get());
}
}
for (auto const &skinset : vehicle->matching_skinsets) { if (ImGui::BeginChild("box2")) {
bool map_group_eq = (skinset->group == group); ImGuiListClipper clipper(model_list.size());
bool sel_group_eq = (selected_group && skinset->group == *selected_group); while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto &desc = model_list[i];
if (!model_added && map_group_eq) { const deferred_image *image = nullptr;
model_list.push_back(&group); for (auto const &skinset : desc->matching_skinsets) {
model_added = true; if (skinset->mini) {
} image = &skinset->mini;
if (map_sel_eq) {
if (sel_group_eq)
skinset_list.push_back(skinset.get());
}
else if (model_added) {
can_break = true;
break; break;
} }
} }
if (can_break) std::string label = desc->path.stem().string();
break; if (selectable_image(label.c_str(), desc == selected_vehicle, image))
} selected_vehicle = desc;
}
if (ImGui::BeginChild("box2")) {
ImGuiListClipper clipper(model_list.size());
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto group = model_list[i];
deferred_image *image = nullptr;
auto it = bank.group_icons.find(*group);
if (it != bank.group_icons.end())
image = &it->second;
if (selectable_image(group->c_str(), group == selected_group, image))
selected_group = group;
}
}
}
else {
std::vector<std::shared_ptr<const vehicle_desc>> model_list;
for (auto const &v : bank.vehicles) {
auto desc = v.second;
if (selected_type == desc->type && desc->matching_skinsets.size() > 0)
model_list.push_back(desc);
if (selected_vehicle == desc && selected_type == desc->type) {
for (auto &skin : desc->matching_skinsets)
skinset_list.push_back(skin.get());
}
}
if (ImGui::BeginChild("box2")) {
ImGuiListClipper clipper(model_list.size());
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto &desc = model_list[i];
const deferred_image *image = nullptr;
for (auto const &skinset : desc->matching_skinsets) {
if (skinset->mini) {
image = &skinset->mini;
break;
}
}
std::string label = desc->path.stem().string();
if (selectable_image(label.c_str(), desc == selected_vehicle, image))
selected_vehicle = desc;
}
}
}
ImGui::EndChild();
ImGui::NextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::InputText("##search", search_query.data(), search_query.size());
auto query_info = parse_search_query(search_query.data());
if (!query_info.empty())
skinset_list.erase(std::remove_if(skinset_list.begin(), skinset_list.end(),
std::bind(&vehiclepicker_panel::skin_filter, this, std::placeholders::_1, query_info)),
skinset_list.end());
if (ImGui::BeginChild("box3")) {
ImGuiListClipper clipper(skinset_list.size());
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto skin = skinset_list[i];
//std::string label = skin->skins[0].stem().string();
std::string label = skin->skin;
if (skin->meta && !skin->meta->name.empty() && skin->meta->name != "?")
label = skin->meta->name;
auto mini = skin->mini ? &skin->mini : &placeholder_mini;
if (selectable_image(label.c_str(), skin == selected_skinset, mini, skin))
selected_skinset = skin;
if (skin->meta && ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(STR_C("Skin: %s\nType: %s\nCarrier code: %s\nDepot: %s\nMaintenance: %s, by %s\nSkin author: %s\nPhoto author: %s"),
skin->skin.c_str(),
skin->vehicle.lock()->path.string().c_str(),
skin->meta->short_id.c_str(),
skin->meta->location.c_str(),
skin->meta->rev_date.c_str(),
skin->meta->rev_company.c_str(),
skin->meta->texture_author.c_str(),
skin->meta->photo_author.c_str());
ImGui::EndTooltip();
}
} }
} }
ImGui::EndChild();
ImGui::PopStyleVar();
} }
ImGui::End();
ImGui::EndChild();
ImGui::NextColumn();
ImGui::SetNextItemWidth(-1);
ImGui::InputText("##search", search_query.data(), search_query.size());
auto query_info = parse_search_query(search_query.data());
if (!query_info.empty())
skinset_list.erase(std::remove_if(skinset_list.begin(), skinset_list.end(),
std::bind(&vehiclepicker_panel::skin_filter, this, std::placeholders::_1, query_info)),
skinset_list.end());
if (ImGui::BeginChild("box3")) {
ImGuiListClipper clipper(skinset_list.size());
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
auto skin = skinset_list[i];
//std::string label = skin->skins[0].stem().string();
std::string label = skin->skin;
if (skin->meta && !skin->meta->name.empty() && skin->meta->name != "?")
label = skin->meta->name;
auto mini = skin->mini ? &skin->mini : &placeholder_mini;
if (selectable_image(label.c_str(), skin == selected_skinset, mini, skin))
selected_skinset = skin;
if (skin->meta && ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
ImGui::Text(STR_C("Skin: %s\nType: %s\nCarrier code: %s\nDepot: %s\nMaintenance: %s, by %s\nSkin author: %s\nPhoto author: %s"),
skin->skin.c_str(),
skin->vehicle.lock()->path.string().c_str(),
skin->meta->short_id.c_str(),
skin->meta->location.c_str(),
skin->meta->rev_date.c_str(),
skin->meta->rev_company.c_str(),
skin->meta->texture_author.c_str(),
skin->meta->photo_author.c_str());
ImGui::EndTooltip();
}
}
}
ImGui::EndChild();
ImGui::PopStyleVar();
} }
std::vector<ui::vehiclepicker_panel::search_info> ui::vehiclepicker_panel::parse_search_query(const std::string &str) std::vector<ui::vehiclepicker_panel::search_info> ui::vehiclepicker_panel::parse_search_query(const std::string &str)

View File

@@ -2,6 +2,7 @@
#include "uilayer.h" #include "uilayer.h"
#include "textures_scanner.h" #include "textures_scanner.h"
#include "translation.h"
namespace ui { namespace ui {
@@ -10,7 +11,7 @@ class vehiclepicker_panel : public ui_panel
public: public:
vehiclepicker_panel(); vehiclepicker_panel();
void render() override; void render_contents() override;
private: private:
bool selectable_image(const char *desc, bool selected, const deferred_image *image, const skin_set *pickable = nullptr); bool selectable_image(const char *desc, bool selected, const deferred_image *image, const skin_set *pickable = nullptr);
@@ -22,6 +23,24 @@ private:
bool display_by_groups = true; bool display_by_groups = true;
deferred_image placeholder_mini; deferred_image placeholder_mini;
std::array<char, 128> search_query = { 0 }; std::array<char, 128> search_query = { 0 };
std::map<vehicle_type, std::string> type_names =
{
{ vehicle_type::electric_loco, STRN("Electric locos") },
{ vehicle_type::diesel_loco, STRN("Diesel locos") },
{ vehicle_type::steam_loco, STRN("Steam locos") },
{ vehicle_type::railcar, STRN("Railcars") },
{ vehicle_type::emu, STRN("EMU") },
{ vehicle_type::utility, STRN("Utility") },
{ vehicle_type::draisine, STRN("Draisines") },
{ vehicle_type::tram, STRN("Trams") },
{ vehicle_type::carriage, STRN("Carriages") },
{ vehicle_type::truck, STRN("Trucks") },
{ vehicle_type::bus, STRN("Buses") },
{ vehicle_type::car, STRN("Cars") },
{ vehicle_type::man, STRN("People") },
{ vehicle_type::animal, STRN("Animals") },
{ vehicle_type::unknown, STRN("Unknown") }
};
vehicles_bank bank; vehicles_bank bank;

View File

@@ -10,10 +10,11 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h" #include "stdafx.h"
#include "uilayer.h" #include "uilayer.h"
#include <utility>
#include "Globals.h" #include "Globals.h"
#include "renderer.h" #include "renderer.h"
#include "Logs.h" #include "Logs.h"
#include "Timer.h"
#include "simulation.h" #include "simulation.h"
#include "translation.h" #include "translation.h"
#include "application.h" #include "application.h"
@@ -29,7 +30,7 @@ bool ui_layer::m_cursorvisible;
ImFont *ui_layer::font_default{nullptr}; ImFont *ui_layer::font_default{nullptr};
ImFont *ui_layer::font_mono{nullptr}; ImFont *ui_layer::font_mono{nullptr};
ui_panel::ui_panel(std::string const &Identifier, bool const Isopen) : m_name(Identifier), is_open(Isopen) {} ui_panel::ui_panel(std::string Identifier, bool const Isopen) : is_open(Isopen), m_name(std::move(Identifier)) {}
void ui_panel::render() void ui_panel::render()
{ {
@@ -38,11 +39,16 @@ void ui_panel::render()
int flags = window_flags; int flags = window_flags;
if (flags == -1) if (flags == -1)
flags = ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoCollapse | flags = ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoCollapse;
((size.x > 0) ? ImGuiWindowFlags_NoResize : 0); if (size.x > 0)
flags |= ImGuiWindowFlags_NoResize;
if (no_title_bar)
flags |= ImGuiWindowFlags_NoTitleBar;
if (size.x > 0) if (pos.x != -1 && pos.y != -1)
ImGui::SetNextWindowSize(ImVec2S(size.x, size.y)); ImGui::SetNextWindowPos(ImVec2(pos.x, pos.y), ImGuiCond_Always);
if (size.x > 0)
ImGui::SetNextWindowSize(ImVec2S(size.x, size.y), ImGuiCond_Always);
else if (size_min.x == -1) else if (size_min.x == -1)
ImGui::SetNextWindowSize(ImVec2(0, 0), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(0, 0), ImGuiCond_FirstUseEver);
@@ -53,7 +59,7 @@ void ui_panel::render()
if (ImGui::Begin(panelname.c_str(), &is_open, flags)) { if (ImGui::Begin(panelname.c_str(), &is_open, flags)) {
render_contents(); render_contents();
popups.remove_if([](std::unique_ptr<ui::popup> &popup) popups.remove_if([](const std::unique_ptr<ui::popup> &popup)
{ {
return popup->render(); return popup->render();
}); });
@@ -93,6 +99,13 @@ void ui_log_panel::render_contents()
ImGui::PopFont(); ImGui::PopFont();
} }
ui_layer::ui_layer()
{
if (Global.loading_log)
add_external_panel(&m_logpanel);
m_logpanel.size = { 700, 400 };
}
ui_layer::~ui_layer() {} ui_layer::~ui_layer() {}
bool ui_layer::key_callback(int key, int scancode, int action, int mods) bool ui_layer::key_callback(int key, int scancode, int action, int mods)
@@ -119,13 +132,6 @@ bool ui_layer::mouse_button_callback(int button, int action, int mods)
return m_imguiio->WantCaptureMouse; return m_imguiio->WantCaptureMouse;
} }
ui_layer::ui_layer()
{
if (Global.loading_log)
add_external_panel(&m_logpanel);
m_logpanel.size = { 700, 400 };
}
void::ui_layer::load_random_background() void::ui_layer::load_random_background()
{ {
std::vector<std::string> images; std::vector<std::string> images;
@@ -504,7 +510,7 @@ void ui_layer::render_menu()
{ {
glm::dvec2 mousepos = Global.cursor_pos; glm::dvec2 mousepos = Global.cursor_pos;
if (!((Global.ControlPicking && mousepos.y < 50.0f) || m_imguiio->WantCaptureMouse) || m_progress != 0.0f) if (!((Global.ControlPicking && mousepos.y < 50.0f) || m_imguiio->WantCaptureMouse) || m_progress != 0.0f || m_suppress_menu)
return; return;
if (ImGui::BeginMainMenuBar()) if (ImGui::BeginMainMenuBar())

115
uilayer.h
View File

@@ -10,8 +10,8 @@ http://mozilla.org/MPL/2.0/.
#pragma once #pragma once
#include <string> #include <string>
#include <utility>
#include "Texture.h" #include "Texture.h"
#include "translation.h"
#include "widgets/popup.h" #include "widgets/popup.h"
// GuiLayer -- basic user interface class. draws requested information on top of openGL screen // GuiLayer -- basic user interface class. draws requested information on top of openGL screen
@@ -20,7 +20,7 @@ class ui_panel {
public: public:
// constructor // constructor
ui_panel( std::string const &Identifier, bool const Isopen ); ui_panel( std::string Identifier, bool Isopen );
virtual ~ui_panel() = default; virtual ~ui_panel() = default;
// methods // methods
virtual void update() {}; virtual void update() {};
@@ -29,23 +29,21 @@ public:
// temporary access // temporary access
// types // types
struct text_line { struct text_line {
std::string data; std::string data;
glm::vec4 color; glm::vec4 color;
text_line( std::string const &Data, glm::vec4 const &Color) : data(Data), color(Color) {}
text_line( std::string const &Data, glm::vec4 const &Color)
: data(Data), color(Color)
{}
}; };
// members // members
std::string title; std::string title;
bool is_open; bool is_open;
glm::ivec2 pos { -1, -1 };
glm::ivec2 size { -1, -1 }; glm::ivec2 size { -1, -1 };
glm::ivec2 size_min { -1, -1 }; glm::ivec2 size_min { -1, -1 };
glm::ivec2 size_max { -1, -1 }; glm::ivec2 size_max { -1, -1 };
std::deque<text_line> text_lines; std::deque<text_line> text_lines;
int window_flags = -1; int window_flags = -1;
bool no_title_bar = false;
const std::string& name() { return m_name; } const std::string& name() { return m_name; }
void register_popup(std::unique_ptr<ui::popup> &&popup); void register_popup(std::unique_ptr<ui::popup> &&popup);
@@ -59,19 +57,16 @@ protected:
class ui_expandable_panel : public ui_panel { class ui_expandable_panel : public ui_panel {
public: public:
using ui_panel::ui_panel; using ui_panel::ui_panel;
bool is_expanded { false }; bool is_expanded { false };
void render_contents() override; void render_contents() override;
}; };
class ui_log_panel : public ui_panel { class ui_log_panel : public ui_panel {
using ui_panel::ui_panel; using ui_panel::ui_panel;
void render_contents() override; void render_contents() override;
}; };
class ImFont; struct ImFont;
class ui_layer { class ui_layer {
public: public:
@@ -81,68 +76,38 @@ public:
virtual ~ui_layer(); virtual ~ui_layer();
// methods // methods
static static bool init( GLFWwindow *Window );
bool static void imgui_style();
init( GLFWwindow *Window );
static
void
imgui_style();
// assign texturing hardware unit // assign texturing hardware unit
static static void set_unit( GLint const Textureunit ) { m_textureunit = GL_TEXTURE0 + Textureunit; }
void static void shutdown();
set_unit( GLint const Textureunit ) { m_textureunit = GL_TEXTURE0 + Textureunit; }
static
void
shutdown();
// potentially processes provided input key. returns: true if the input was processed, false otherwise // potentially processes provided input key. returns: true if the input was processed, false otherwise
virtual virtual bool on_key( int Key, int Action );
bool
on_key( int const Key, int const Action );
// potentially processes provided mouse movement. returns: true if the input was processed, false otherwise // potentially processes provided mouse movement. returns: true if the input was processed, false otherwise
virtual virtual bool on_cursor_pos( double Horizontal, double Vertical );
bool
on_cursor_pos( double const Horizontal, double const Vertical );
// potentially processes provided mouse button. returns: true if the input was processed, false otherwise // potentially processes provided mouse button. returns: true if the input was processed, false otherwise
virtual virtual bool on_mouse_button( int Button, int Action );
bool
on_mouse_button( int const Button, int const Action );
// updates state of UI elements // updates state of UI elements
virtual virtual void update();
void
update();
// draws requested UI elements // draws requested UI elements
void void render();
render(); static void render_internal();
static void
render_internal();
// begins new UI frame // begins new UI frame
// (this is separate from render() to allow for debug GUI outside of proper UI framework) // (this is separate from render() to allow for debug GUI outside of proper UI framework)
void void begin_ui_frame();
begin_ui_frame(); static void begin_ui_frame_internal();
static void
begin_ui_frame_internal();
// //
static static void set_cursor( int Mode );
void
set_cursor( int const Mode );
// stores operation progress // stores operation progress
void void set_progress( float Progress = 0.0f, float Subtaskprogress = 0.0f );
set_progress( float const Progress = 0.0f, float const Subtaskprogress = 0.0f ); void set_progress( std::string const &Text ) { m_progresstext = Text; }
void
set_progress( std::string const &Text ) { m_progresstext = Text; }
// sets the ui background texture, if any // sets the ui background texture, if any
void void set_background( std::string const &Filename = "" );
set_background( std::string const &Filename = "" ); void set_tooltip( std::string const &Tooltip ) { m_tooltip = Tooltip; }
void void clear_panels();
set_tooltip( std::string const &Tooltip ) { m_tooltip = Tooltip; } void add_external_panel( ui_panel *Panel ) { m_panels.emplace_back( Panel ); }
void void add_owned_panel( ui_panel *Panel );
clear_panels();
void
add_external_panel( ui_panel *Panel ) { m_panels.emplace_back( Panel ); }
void
add_owned_panel( ui_panel *Panel );
// callback functions for imgui input // callback functions for imgui input
// returns true if input is consumed // returns true if input is consumed
@@ -158,35 +123,27 @@ protected:
// members // members
static GLFWwindow *m_window; static GLFWwindow *m_window;
static ImGuiIO *m_imguiio; static ImGuiIO *m_imguiio;
static bool m_cursorvisible; static bool m_cursorvisible;
void load_random_background(); void load_random_background();
virtual void render_menu_contents(); virtual void render_menu_contents();
ui_log_panel m_logpanel { "Log", true }; ui_log_panel m_logpanel { "Log", true };
bool m_suppress_menu = false; // if `true`, the menu at the top of the window will not be present
private: private:
// methods // methods
// render() subclass details // render() subclass details
virtual virtual void render_() {};
void
render_() {};
// draws background quad with specified earlier texture // draws background quad with specified earlier texture
void void render_background();
render_background();
// draws a progress bar in defined earlier state // draws a progress bar in defined earlier state
void void render_progress();
render_progress(); void render_tooltip();
void
render_tooltip();
void render_panels(); void render_panels();
void render_menu();
void render_menu(); void render_quit_widget();
void render_quit_widget();
// draws a quad between coordinates x,y and z,w with uv-coordinates spanning 0-1 // draws a quad between coordinates x,y and z,w with uv-coordinates spanning 0-1
void void quad( glm::vec4 const &Coordinates, glm::vec4 const &Color );
quad( glm::vec4 const &Coordinates, glm::vec4 const &Color );
// members // members
static GLint m_textureunit; static GLint m_textureunit;

View File

@@ -6,7 +6,7 @@
#include "widgets/cameraview_extcam.h" #include "widgets/cameraview_extcam.h"
#include "stb/stb_image.h" #include "stb/stb_image.h"
#include "Globals.h" #include "Globals.h"
#include "Logs.h" #include "translation.h"
#include "extras/piped_proc.h" #include "extras/piped_proc.h"
ui::cameraview_panel::cameraview_panel() ui::cameraview_panel::cameraview_panel()

View File

@@ -1,12 +1,9 @@
#include "stdafx.h" #include "stdafx.h"
#include "widgets/perfgraphs.h" #include "widgets/perfgraphs.h"
#include "Timer.h" #include "Timer.h"
#include "translation.h"
perfgraph_panel::perfgraph_panel() perfgraph_panel::perfgraph_panel() : ui_panel(STR("Performance"), false) {}
: ui_panel(STR("Performance"), false)
{
}
void perfgraph_panel::render_contents() { void perfgraph_panel::render_contents() {
if (ImGui::BeginCombo(STR_C("Timer"), timer_label[current_timer].c_str())) // The second parameter is the label previewed before opening the combo. if (ImGui::BeginCombo(STR_C("Timer"), timer_label[current_timer].c_str())) // The second parameter is the label previewed before opening the combo.