mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 05:49:19 +02:00
Merge branch 'master' into master
This commit is contained in:
@@ -36,69 +36,60 @@ bool ui::keymapper_panel::key(int key)
|
||||
return true;
|
||||
}
|
||||
|
||||
void ui::keymapper_panel::render()
|
||||
void ui::keymapper_panel::render_contents()
|
||||
{
|
||||
if (!is_open)
|
||||
return;
|
||||
if (ImGui::Button(STR_C("Load")))
|
||||
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("Load")))
|
||||
keyboard.init();
|
||||
if (ImGui::Button(STR_C("Save")))
|
||||
keyboard.dump_bindings();
|
||||
|
||||
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")))
|
||||
keyboard.dump_bindings();
|
||||
// Binding description
|
||||
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 ID
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text(simulation::Commands_descriptions[static_cast<std::size_t>(binding.first)].name.c_str());
|
||||
// Binding key button
|
||||
int keycode = std::get<int>(binding.second);
|
||||
std::string label;
|
||||
|
||||
// Binding description
|
||||
std::string description = std::get<std::string>(binding.second);
|
||||
ImGui::SameLine(260);
|
||||
ImGui::Text((description.size() > 0 ? description : "(No description)").c_str());
|
||||
if (keycode & keyboard_input::keymodifier::control)
|
||||
label += "ctrl + ";
|
||||
if (keycode & keyboard_input::keymodifier::shift)
|
||||
label += "shift + ";
|
||||
|
||||
// Binding key button
|
||||
int keycode = std::get<int>(binding.second);
|
||||
std::string label;
|
||||
auto it = keyboard.keytonamemap.find(keycode & 0xFFFF);
|
||||
if (it != keyboard.keytonamemap.end())
|
||||
label += it->second;
|
||||
|
||||
if (keycode & keyboard_input::keymodifier::control)
|
||||
label += "ctrl + ";
|
||||
if (keycode & keyboard_input::keymodifier::shift)
|
||||
label += "shift + ";
|
||||
label = ToUpper(label);
|
||||
|
||||
auto it = keyboard.keytonamemap.find(keycode & 0xFFFF);
|
||||
if (it != keyboard.keytonamemap.end())
|
||||
label += it->second;
|
||||
|
||||
label = ToUpper(label);
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ class keymapper_panel : public ui_panel
|
||||
public:
|
||||
keymapper_panel();
|
||||
|
||||
void render() override;
|
||||
void render_contents() override;
|
||||
bool key(int key);
|
||||
|
||||
private:
|
||||
driverkeyboard_input keyboard;
|
||||
|
||||
user_command bind_active = user_command::none;
|
||||
const std::string panelname = (title.empty() ? m_name : title) + "###" + m_name;
|
||||
};
|
||||
} // namespace ui
|
||||
|
||||
@@ -23,9 +23,7 @@ bool launcher_mode::update()
|
||||
void launcher_mode::enter()
|
||||
{
|
||||
Application.set_cursor( GLFW_CURSOR_NORMAL );
|
||||
|
||||
simulation::is_ready = false;
|
||||
|
||||
Application.set_title(Global.AppName);
|
||||
}
|
||||
|
||||
@@ -36,7 +34,10 @@ void launcher_mode::exit()
|
||||
|
||||
void launcher_mode::on_key(const int Key, const int Scancode, const int Action, const int Mods)
|
||||
{
|
||||
Global.shiftState = ( Mods & GLFW_MOD_SHIFT ) ? true : false;
|
||||
Global.ctrlState = ( Mods & GLFW_MOD_CONTROL ) ? true : false;
|
||||
m_userinterface->on_key(Key, Action);
|
||||
}
|
||||
|
||||
void launcher_mode::on_window_resize(const int w, const int h)
|
||||
{
|
||||
m_userinterface->on_window_resize(w, h);
|
||||
}
|
||||
|
||||
@@ -18,28 +18,19 @@ public:
|
||||
launcher_mode();
|
||||
// methods
|
||||
// initializes internal data structures of the mode. returns: true on success, false otherwise
|
||||
bool
|
||||
init() override;
|
||||
bool init() override;
|
||||
// mode-specific update of simulation data. returns: false on error, true otherwise
|
||||
bool
|
||||
update() override;
|
||||
bool update() override;
|
||||
// maintenance method, called when the mode is activated
|
||||
void
|
||||
enter() override;
|
||||
void enter() override;
|
||||
// maintenance method, called when the mode is deactivated
|
||||
void
|
||||
exit() override;
|
||||
void exit() override;
|
||||
// input handlers
|
||||
void
|
||||
on_key( int const Key, int const Scancode, int const Action, int const Mods );
|
||||
void
|
||||
on_cursor_pos( double const Horizontal, double const Vertical ) override { ; }
|
||||
void
|
||||
on_mouse_button( int const Button, int const Action, int const Mods ) override { ; }
|
||||
void
|
||||
on_scroll( double const Xoffset, double const Yoffset ) override { ; }
|
||||
void
|
||||
on_event_poll() override { ; }
|
||||
bool
|
||||
is_command_processor() const override { return false; }
|
||||
void on_key( int Key, int Scancode, int Action, int Mods ) override;
|
||||
void on_cursor_pos( double const Horizontal, double const Vertical ) override { ; }
|
||||
void on_mouse_button( int const Button, int const Action, int const Mods ) override { ; }
|
||||
void on_scroll( double const Xoffset, double const Yoffset ) override { ; }
|
||||
void on_window_resize( int w, int h ) override;
|
||||
void on_event_poll() override { ; }
|
||||
bool is_command_processor() const override { return false; }
|
||||
};
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#include "stdafx.h"
|
||||
#include "launcher/launcheruilayer.h"
|
||||
#include "application.h"
|
||||
#include "translation.h"
|
||||
|
||||
#include "Logs.h"
|
||||
launcher_ui::launcher_ui()
|
||||
: m_scenery_scanner(m_vehicles_bank), m_scenerylist_panel(m_scenery_scanner)
|
||||
launcher_ui::launcher_ui() : m_scenery_scanner(m_vehicles_bank), m_scenerylist_panel(m_scenery_scanner)
|
||||
{
|
||||
m_vehicles_bank.scan_textures();
|
||||
m_scenery_scanner.scan();
|
||||
@@ -13,33 +12,66 @@ launcher_ui::launcher_ui()
|
||||
add_external_panel(&m_keymapper_panel);
|
||||
add_external_panel(&m_vehiclepicker_panel);
|
||||
|
||||
open_panel(&m_vehiclepicker_panel);
|
||||
m_suppress_menu = true;
|
||||
|
||||
load_random_background();
|
||||
}
|
||||
|
||||
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))
|
||||
return true;
|
||||
|
||||
return ui_layer::on_key(Key, Action);
|
||||
}
|
||||
|
||||
void launcher_ui::on_window_resize(int w, int h)
|
||||
{
|
||||
open_panel(m_current_panel);
|
||||
}
|
||||
|
||||
void launcher_ui::render_()
|
||||
{
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse;
|
||||
ImVec2 display_size = ImGui::GetIO().DisplaySize;
|
||||
ImGui::SetNextWindowPos(ImVec2(display_size.x * 0.66f, display_size.y / 2.0f));
|
||||
ImGui::SetNextWindowSize(ImVec2(200 * Global.ui_scale, -1));
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove;
|
||||
const float topbar_height = 50 * Global.ui_scale;
|
||||
const ImVec2 topbar_button_size = ImVec2(150 * Global.ui_scale, topbar_height - 16);
|
||||
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::Button(STR_C("Scenario list"), ImVec2(-1, 0)))
|
||||
m_scenerylist_panel.is_open = !m_scenerylist_panel.is_open;
|
||||
if (ImGui::Button(STR_C("Vehicle list"), ImVec2(-1, 0)))
|
||||
m_vehiclepicker_panel.is_open = !m_vehiclepicker_panel.is_open;
|
||||
if (ImGui::Button(STR_C("Keymapper"), ImVec2(-1, 0)))
|
||||
m_keymapper_panel.is_open = !m_keymapper_panel.is_open;
|
||||
if (ImGui::Button(STR_C("Quit"), ImVec2(-1, 0)))
|
||||
if (ImGui::Button(STR_C("Scenario list"), topbar_button_size))
|
||||
open_panel(&m_scenerylist_panel);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(STR_C("Vehicle list"), topbar_button_size))
|
||||
open_panel(&m_vehiclepicker_panel);
|
||||
ImGui::SameLine();
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
||||
m_current_panel = panel;
|
||||
}
|
||||
|
||||
@@ -19,10 +19,13 @@ http://mozilla.org/MPL/2.0/.
|
||||
class launcher_ui : public ui_layer {
|
||||
public:
|
||||
launcher_ui();
|
||||
bool on_key(const int Key, const int Action) override;
|
||||
bool on_key(int Key, int Action) override;
|
||||
void on_window_resize(int w, int h) override;
|
||||
|
||||
private:
|
||||
void render_() override;
|
||||
void close_panels();
|
||||
void open_panel(ui_panel *panel);
|
||||
|
||||
ui::vehicles_bank m_vehicles_bank;
|
||||
scenery_scanner m_scenery_scanner;
|
||||
@@ -30,4 +33,6 @@ private:
|
||||
ui::scenerylist_panel m_scenerylist_panel;
|
||||
ui::keymapper_panel m_keymapper_panel;
|
||||
ui::vehiclepicker_panel m_vehiclepicker_panel;
|
||||
|
||||
ui_panel *m_current_panel;
|
||||
};
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
#include "imgui/imgui.h"
|
||||
#include "utilities.h"
|
||||
#include "renderer.h"
|
||||
#include "McZapkie/MOVER.h"
|
||||
#include "application.h"
|
||||
#include "Logs.h"
|
||||
#include "translation.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner)
|
||||
@@ -13,34 +14,53 @@ 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()
|
||||
{
|
||||
std::string prev_prefix;
|
||||
bool collapse_open = false;
|
||||
|
||||
// Draw all the scenarios which are not assigned to any category.
|
||||
for (auto &desc : scanner.scenarios) {
|
||||
std::string name = desc.path.stem().string();
|
||||
std::string prefix = name.substr(0, name.find_first_of("-_"));
|
||||
std::string prefix = desc.category;
|
||||
if (prefix.empty())
|
||||
prefix = name;
|
||||
|
||||
bool just_opened = false;
|
||||
if (prefix != prev_prefix) {
|
||||
collapse_open = ImGui::CollapsingHeader(prefix.c_str());
|
||||
just_opened = ImGui::IsItemDeactivated();
|
||||
prev_prefix = prefix;
|
||||
}
|
||||
|
||||
if (collapse_open) {
|
||||
if (just_opened)
|
||||
selected_scenery = &desc;
|
||||
|
||||
ImGui::Indent(10.0f);
|
||||
{
|
||||
if (ImGui::Selectable(name.c_str(), &desc == selected_scenery)) {
|
||||
selected_scenery = &desc;
|
||||
selected_trainset = nullptr;
|
||||
}
|
||||
ImGui::Unindent(10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Render all aggregated scenarios inside categories.
|
||||
bool collapse_open = false;
|
||||
for (auto category : scanner.categories)
|
||||
{
|
||||
collapse_open = ImGui::CollapsingHeader(category.first.c_str());
|
||||
if (collapse_open) {
|
||||
for (auto desc : category.second)
|
||||
{
|
||||
std::string name = desc->path.stem().string();
|
||||
|
||||
ImGui::Indent(10.0f);
|
||||
if (ImGui::Selectable(name.c_str(), desc == selected_scenery)) {
|
||||
selected_scenery = desc;
|
||||
selected_trainset = nullptr;
|
||||
}
|
||||
ImGui::Unindent(10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -352,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)
|
||||
: popup(panel), dynamic(dynamic)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "driverkeyboardinput.h"
|
||||
#include "uilayer.h"
|
||||
#include "scenery_scanner.h"
|
||||
#include "widgets/popup.h"
|
||||
@@ -35,8 +36,11 @@ class scenerylist_panel : public ui_panel
|
||||
scenerylist_panel(scenery_scanner &scanner);
|
||||
|
||||
void render_contents() override;
|
||||
bool on_key(int key, int action);
|
||||
|
||||
private:
|
||||
driverkeyboard_input keyboard;
|
||||
|
||||
struct vehicle_moved {
|
||||
trainset_desc &source;
|
||||
dynamic_desc &dynamic;
|
||||
@@ -63,5 +67,6 @@ private:
|
||||
void open_link(const std::string &link);
|
||||
void draw_trainset(trainset_desc &trainset);
|
||||
void draw_droptarget(trainset_desc &trainset, int position);
|
||||
void purge_selected_trainset();
|
||||
};
|
||||
} // namespace ui
|
||||
|
||||
@@ -22,6 +22,8 @@ void scenery_scanner::scan()
|
||||
|
||||
std::sort(scenarios.begin(), scenarios.end(),
|
||||
[](const scenery_desc &a, const scenery_desc &b) { return a.path < b.path; });
|
||||
|
||||
build_categories();
|
||||
}
|
||||
|
||||
void scenery_scanner::scan_scn(std::filesystem::path path)
|
||||
@@ -57,6 +59,8 @@ void scenery_scanner::scan_scn(std::filesystem::path path)
|
||||
desc.name = win1250_to_utf8(line.substr(5));
|
||||
else if (line[3] == 'd')
|
||||
desc.description += win1250_to_utf8(line.substr(5)) + '\n';
|
||||
else if (line[3] == 'l')
|
||||
desc.category = win1250_to_utf8(line.substr(5));
|
||||
else if (line[3] == 'f') {
|
||||
std::string lang;
|
||||
std::string file;
|
||||
@@ -154,3 +158,14 @@ void scenery_scanner::parse_trainset(cParser &parser)
|
||||
|
||||
trainset.file_bounds.second = parser.Line();
|
||||
}
|
||||
|
||||
void scenery_scanner::build_categories()
|
||||
{
|
||||
for (auto &desc : scenarios) {
|
||||
std::string name = desc.path.stem().string();
|
||||
std::string prefix = desc.category;
|
||||
// If the scenario does have a category, add it to the list so we can render it later in a group.
|
||||
if (!prefix.empty())
|
||||
categories[prefix].push_back(&desc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ struct scenery_desc {
|
||||
std::filesystem::path path;
|
||||
std::string name;
|
||||
std::string description;
|
||||
std::string category;
|
||||
std::string image_path;
|
||||
texture_handle image = 0;
|
||||
|
||||
@@ -58,12 +59,14 @@ public:
|
||||
scenery_scanner(ui::vehicles_bank &bank);
|
||||
|
||||
std::vector<scenery_desc> scenarios;
|
||||
std::map<std::string, std::vector<scenery_desc*>> categories;
|
||||
|
||||
void scan();
|
||||
|
||||
private:
|
||||
void scan_scn(std::filesystem::path path);
|
||||
void parse_trainset(cParser &parser);
|
||||
void build_categories();
|
||||
|
||||
ui::vehicles_bank &bank;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "launcher/vehicle_picker.h"
|
||||
#include "renderer.h"
|
||||
#include "translation.h"
|
||||
|
||||
ui::vehiclepicker_panel::vehiclepicker_panel()
|
||||
: ui_panel(STR("Select vehicle"), false), placeholder_mini("textures/mini/other")
|
||||
@@ -8,195 +9,170 @@ ui::vehiclepicker_panel::vehiclepicker_panel()
|
||||
bank.scan_textures();
|
||||
}
|
||||
|
||||
void ui::vehiclepicker_panel::render()
|
||||
void ui::vehiclepicker_panel::render_contents()
|
||||
{
|
||||
if (!is_open)
|
||||
return;
|
||||
ImGui::Columns(3);
|
||||
|
||||
static 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") }
|
||||
};
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.0f, 0.5f));
|
||||
|
||||
if (ImGui::Begin(m_name.c_str(), &is_open)) {
|
||||
ImGui::Columns(3);
|
||||
if (ImGui::BeginChild("box1")) {
|
||||
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")) {
|
||||
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::TextUnformatted(STR_C("Group by: "));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton(STR_C("type"), !display_by_groups))
|
||||
display_by_groups = false;
|
||||
ImGui::SameLine();
|
||||
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))
|
||||
selected_type = e.first;
|
||||
std::vector<const skin_set*> skinset_list;
|
||||
|
||||
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: "));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton(STR_C("type"), !display_by_groups))
|
||||
display_by_groups = false;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton(STR_C("texture group"), display_by_groups))
|
||||
display_by_groups = true;
|
||||
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];
|
||||
|
||||
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) {
|
||||
std::vector<const std::string*> model_list;
|
||||
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 &kv : bank.group_map) {
|
||||
const std::string &group = kv.first;
|
||||
for (auto const &v : bank.vehicles) {
|
||||
auto desc = v.second;
|
||||
|
||||
bool model_added = false;
|
||||
bool can_break = false;
|
||||
bool map_sel_eq = (selected_group && group == *selected_group);
|
||||
if (selected_type == desc->type && desc->matching_skinsets.size() > 0)
|
||||
model_list.push_back(desc);
|
||||
|
||||
for (auto const &vehicle : kv.second) {
|
||||
if (vehicle->type != selected_type)
|
||||
continue;
|
||||
if (selected_vehicle == desc && selected_type == desc->type) {
|
||||
for (auto &skin : desc->matching_skinsets)
|
||||
skinset_list.push_back(skin.get());
|
||||
}
|
||||
}
|
||||
|
||||
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 (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];
|
||||
|
||||
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;
|
||||
const deferred_image *image = nullptr;
|
||||
for (auto const &skinset : desc->matching_skinsets) {
|
||||
if (skinset->mini) {
|
||||
image = &skinset->mini;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
std::string label = desc->path.stem().string();
|
||||
if (selectable_image(label.c_str(), desc == selected_vehicle, image))
|
||||
selected_vehicle = desc;
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "uilayer.h"
|
||||
#include "textures_scanner.h"
|
||||
#include "translation.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
@@ -10,7 +11,7 @@ class vehiclepicker_panel : public ui_panel
|
||||
public:
|
||||
vehiclepicker_panel();
|
||||
|
||||
void render() override;
|
||||
void render_contents() override;
|
||||
|
||||
private:
|
||||
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;
|
||||
deferred_image placeholder_mini;
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user