mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 00:49:19 +02:00
further WIP on launcher
This commit is contained in:
@@ -13,180 +13,173 @@ ui::scenerylist_panel::scenerylist_panel(scenery_scanner &scanner)
|
||||
{
|
||||
}
|
||||
|
||||
void ui::scenerylist_panel::render()
|
||||
void ui::scenerylist_panel::render_contents()
|
||||
{
|
||||
if (!is_open)
|
||||
return;
|
||||
ImGui::Columns(3);
|
||||
|
||||
auto const panelname{(title.empty() ? m_name : title) + "###" + m_name};
|
||||
if (ImGui::BeginChild("child1", ImVec2(0, -200))) {
|
||||
std::string prev_prefix;
|
||||
bool collapse_open = false;
|
||||
|
||||
if (ImGui::Begin(panelname.c_str(), &is_open)) {
|
||||
ImGui::Columns(3);
|
||||
for (auto &desc : scanner.scenarios) {
|
||||
std::string name = desc.path.stem().string();
|
||||
std::string prefix = name.substr(0, name.find_first_of("-_"));
|
||||
if (prefix.empty())
|
||||
prefix = name;
|
||||
|
||||
if (ImGui::BeginChild("child1", ImVec2(0, -200))) {
|
||||
std::string prev_prefix;
|
||||
bool collapse_open = false;
|
||||
|
||||
for (auto &desc : scanner.scenarios) {
|
||||
std::string name = desc.path.stem().string();
|
||||
std::string prefix = name.substr(0, name.find_first_of("-_"));
|
||||
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);
|
||||
}
|
||||
bool just_opened = false;
|
||||
if (prefix != prev_prefix) {
|
||||
collapse_open = ImGui::CollapsingHeader(prefix.c_str());
|
||||
just_opened = ImGui::IsItemDeactivated();
|
||||
prev_prefix = prefix;
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
|
||||
ImGui::NextColumn();
|
||||
if (collapse_open) {
|
||||
if (just_opened)
|
||||
selected_scenery = &desc;
|
||||
|
||||
if (ImGui::BeginChild("child2", ImVec2(0, -200))) {
|
||||
if (selected_scenery) {
|
||||
ImGui::TextWrapped("%s", selected_scenery->name.c_str());
|
||||
ImGui::TextWrapped("%s", selected_scenery->description.c_str());
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto const &link : selected_scenery->links) {
|
||||
if (ImGui::Button(link.second.c_str(), ImVec2(-1, 0))) {
|
||||
std::string file = ToLower(link.first);
|
||||
#ifdef _WIN32
|
||||
system(("start \"" + file + "\"").c_str());
|
||||
#elif __linux__
|
||||
system(("xdg-open \"" + file + "\"").c_str());
|
||||
#elif __APPLE__
|
||||
system(("open \"" + file + "\"").c_str());
|
||||
#endif
|
||||
}
|
||||
ImGui::Indent(10.0f);
|
||||
if (ImGui::Selectable(name.c_str(), &desc == selected_scenery)) {
|
||||
selected_scenery = &desc;
|
||||
selected_trainset = nullptr;
|
||||
}
|
||||
ImGui::Unindent(10.0f);
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
|
||||
ImGui::NextColumn();
|
||||
|
||||
if (selected_scenery) {
|
||||
if (ImGui::BeginChild("child3", ImVec2(0, -200), false, ImGuiWindowFlags_NoScrollbar)) {
|
||||
if (!selected_scenery->image_path.empty()) {
|
||||
scenery_desc *desc = const_cast<scenery_desc*>(selected_scenery);
|
||||
desc->image = GfxRenderer.Fetch_Texture(selected_scenery->image_path, true);
|
||||
desc->image_path.clear();
|
||||
}
|
||||
|
||||
if (selected_scenery->image != null_handle) {
|
||||
opengl_texture &tex = GfxRenderer.Texture(selected_scenery->image);
|
||||
tex.create();
|
||||
|
||||
if (tex.is_ready) {
|
||||
float avail_width = ImGui::GetContentRegionAvailWidth();
|
||||
float height = avail_width / tex.width() * tex.height();
|
||||
|
||||
ImGui::Image(reinterpret_cast<void *>(tex.id), ImVec2(avail_width, height), ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
}
|
||||
ImGui::Columns();
|
||||
ImGui::Separator();
|
||||
} ImGui::EndChild();
|
||||
|
||||
if (ImGui::BeginChild("child4")) {
|
||||
if (selected_scenery) {
|
||||
if (selected_trainset)
|
||||
ImGui::Columns(2);
|
||||
ImGui::NextColumn();
|
||||
|
||||
if (ImGui::BeginChild("child5", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
ImGuiListClipper clipper(selected_scenery->trainsets.size());
|
||||
while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
auto &trainset = selected_scenery->trainsets[i];
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::Selectable("##set", selected_trainset == &trainset, 0, ImVec2(0, 30)))
|
||||
selected_trainset = &trainset;
|
||||
ImGui::SameLine();
|
||||
draw_trainset(trainset);
|
||||
ImGui::NewLine();
|
||||
ImGui::PopID();
|
||||
//ImGui::Selectable(z.c_str(), false);
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
if (ImGui::BeginChild("child2", ImVec2(0, -200))) {
|
||||
if (selected_scenery) {
|
||||
ImGui::TextWrapped("%s", selected_scenery->name.c_str());
|
||||
ImGui::TextWrapped("%s", selected_scenery->description.c_str());
|
||||
|
||||
if (selected_trainset) {
|
||||
ImGui::NextColumn();
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::TextWrapped(selected_trainset->description.c_str());
|
||||
for (auto const &link : selected_scenery->links) {
|
||||
if (ImGui::Button(link.second.c_str(), ImVec2(-1, 0))) {
|
||||
std::string file = ToLower(link.first);
|
||||
#ifdef _WIN32
|
||||
system(("start \"" + file + "\"").c_str());
|
||||
#elif __linux__
|
||||
system(("xdg-open \"" + file + "\"").c_str());
|
||||
#elif __APPLE__
|
||||
system(("open \"" + file + "\"").c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
|
||||
if (ImGui::Button(STR_C("Launch"), ImVec2(-1, 0))) {
|
||||
bool found = false;
|
||||
for (auto &veh : selected_trainset->vehicles) {
|
||||
if (veh.drivertype.size() > 0 && veh.drivertype != "nobody") {
|
||||
Global.local_start_vehicle = ToLower(veh.name);
|
||||
Global.SceneryFile = selected_scenery->path;
|
||||
ImGui::NextColumn();
|
||||
|
||||
std::string set = "trainset ";
|
||||
set += selected_trainset->name + " ";
|
||||
set += selected_trainset->track + " ";
|
||||
set += std::to_string(selected_trainset->offset) + " ";
|
||||
set += std::to_string(selected_trainset->velocity) + " ";
|
||||
for (const auto &veh : selected_trainset->vehicles) {
|
||||
set += "node -1 0 " + veh.name + " dynamic ";
|
||||
set += veh.vehicle->path.parent_path().generic_string() + " ";
|
||||
set += veh.skin->skin + " ";
|
||||
set += veh.vehicle->path.stem().generic_string() + " ";
|
||||
set += std::to_string(veh.offset) + " " + veh.drivertype + " ";
|
||||
set += std::to_string(veh.coupling);
|
||||
if (veh.params.size() > 0)
|
||||
set += "." + veh.params;
|
||||
set += " " + std::to_string(veh.loadcount) + " ";
|
||||
if (veh.loadcount > 0)
|
||||
set += veh.loadtype + " ";
|
||||
set += "enddynamic ";
|
||||
}
|
||||
set += "endtrainset";
|
||||
WriteLog(set);
|
||||
if (selected_scenery) {
|
||||
if (ImGui::BeginChild("child3", ImVec2(0, -200), false, ImGuiWindowFlags_NoScrollbar)) {
|
||||
if (!selected_scenery->image_path.empty()) {
|
||||
scenery_desc *desc = const_cast<scenery_desc*>(selected_scenery);
|
||||
desc->image = GfxRenderer.Fetch_Texture(selected_scenery->image_path, true);
|
||||
desc->image_path.clear();
|
||||
}
|
||||
|
||||
Global.trainset_overrides.push_back(std::make_pair(selected_trainset->file_bounds.first, set));
|
||||
if (selected_scenery->image != null_handle) {
|
||||
opengl_texture &tex = GfxRenderer.Texture(selected_scenery->image);
|
||||
tex.create();
|
||||
|
||||
Application.pop_mode();
|
||||
Application.push_mode(eu07_application::mode::scenarioloader);
|
||||
if (tex.is_ready) {
|
||||
float avail_width = ImGui::GetContentRegionAvailWidth();
|
||||
float height = avail_width / tex.width() * tex.height();
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
ImGui::OpenPopup("missing_driver");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("missing_driver")) {
|
||||
ImGui::TextUnformatted(STR_C("Trainset not occupied"));
|
||||
if (ImGui::Button(STR_C("OK"), ImVec2(-1, 0)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::Image(reinterpret_cast<void *>(tex.id), ImVec2(avail_width, height), ImVec2(0, 1), ImVec2(1, 0));
|
||||
}
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
}
|
||||
ImGui::Columns();
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::End();
|
||||
if (ImGui::BeginChild("child4")) {
|
||||
if (selected_scenery) {
|
||||
if (selected_trainset)
|
||||
ImGui::Columns(2);
|
||||
|
||||
if (ImGui::BeginChild("child5", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
ImGuiListClipper clipper(selected_scenery->trainsets.size());
|
||||
while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
auto &trainset = selected_scenery->trainsets[i];
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::Selectable("##set", selected_trainset == &trainset, 0, ImVec2(0, 30)))
|
||||
selected_trainset = &trainset;
|
||||
ImGui::SameLine();
|
||||
draw_trainset(trainset);
|
||||
ImGui::NewLine();
|
||||
ImGui::PopID();
|
||||
//ImGui::Selectable(z.c_str(), false);
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
|
||||
if (selected_trainset) {
|
||||
ImGui::NextColumn();
|
||||
|
||||
ImGui::TextWrapped(selected_trainset->description.c_str());
|
||||
|
||||
if (ImGui::Button(STR_C("Launch"), ImVec2(-1, 0))) {
|
||||
bool found = false;
|
||||
for (auto &veh : selected_trainset->vehicles) {
|
||||
if (veh.drivertype.size() > 0 && veh.drivertype != "nobody") {
|
||||
Global.local_start_vehicle = ToLower(veh.name);
|
||||
Global.SceneryFile = selected_scenery->path;
|
||||
|
||||
std::string set = "trainset ";
|
||||
set += selected_trainset->name + " ";
|
||||
set += selected_trainset->track + " ";
|
||||
set += std::to_string(selected_trainset->offset) + " ";
|
||||
set += std::to_string(selected_trainset->velocity) + "\n";
|
||||
for (const auto &veh : selected_trainset->vehicles) {
|
||||
set += "node -1 0 " + veh.name + " dynamic ";
|
||||
set += veh.vehicle->path.parent_path().generic_string() + " ";
|
||||
set += veh.skin->skin + " ";
|
||||
set += veh.vehicle->path.stem().generic_string() + " ";
|
||||
set += std::to_string(veh.offset) + " " + veh.drivertype + " ";
|
||||
set += std::to_string(veh.coupling);
|
||||
if (veh.params.size() > 0)
|
||||
set += "." + veh.params;
|
||||
set += " " + std::to_string(veh.loadcount) + " ";
|
||||
if (veh.loadcount > 0)
|
||||
set += veh.loadtype + " ";
|
||||
set += "enddynamic\n";
|
||||
}
|
||||
set += "endtrainset\n";
|
||||
WriteLog(set);
|
||||
|
||||
Global.trainset_overrides.emplace(selected_trainset->file_bounds.first, set);
|
||||
|
||||
Application.pop_mode();
|
||||
Application.push_mode(eu07_application::mode::scenarioloader);
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
ImGui::OpenPopup("missing_driver");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("missing_driver")) {
|
||||
ImGui::TextUnformatted(STR_C("Trainset not occupied"));
|
||||
if (ImGui::Button(STR_C("OK"), ImVec2(-1, 0)))
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
} ImGui::EndChild();
|
||||
}
|
||||
|
||||
void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset)
|
||||
{
|
||||
ImGui::SetItemAllowOverlap();
|
||||
|
||||
static std::unordered_map<coupling, std::string> coupling_names =
|
||||
{
|
||||
{ coupling::faux, STRN("faux") },
|
||||
@@ -206,7 +199,7 @@ void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset)
|
||||
draw_droptarget(trainset, position++);
|
||||
ImGui::SameLine(15.0f);
|
||||
|
||||
for (auto const &dyn_desc : trainset.vehicles) {
|
||||
for (auto &dyn_desc : trainset.vehicles) {
|
||||
deferred_image *mini = nullptr;
|
||||
|
||||
if (dyn_desc.skin && dyn_desc.skin->mini.get() != -1)
|
||||
@@ -220,7 +213,10 @@ void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset)
|
||||
float width = 30.0f / size.y * size.x;
|
||||
ImGui::Image(reinterpret_cast<void*>(mini->get()), ImVec2(width, 30), ImVec2(0, 1), ImVec2(1, 0));
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
if (ImGui::IsItemClicked(1)) {
|
||||
register_popup(std::make_unique<ui::dynamic_edit_popup>(*this, dyn_desc));
|
||||
}
|
||||
else if (ImGui::IsItemHovered()) {
|
||||
ImGui::BeginTooltip();
|
||||
std::string name = (dyn_desc.vehicle->path.parent_path() / dyn_desc.vehicle->path.stem()).string();
|
||||
std::string skin = dyn_desc.skin->skin;
|
||||
@@ -267,7 +263,6 @@ void ui::scenerylist_panel::draw_trainset(trainset_desc &trainset)
|
||||
}
|
||||
}
|
||||
|
||||
#include "Logs.h"
|
||||
void ui::scenerylist_panel::draw_droptarget(trainset_desc &trainset, int position)
|
||||
{
|
||||
ImGui::Dummy(ImVec2(15, 30));
|
||||
@@ -291,3 +286,98 @@ void ui::scenerylist_panel::draw_droptarget(trainset_desc &trainset, int positio
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
ui::dynamic_edit_popup::dynamic_edit_popup(ui_panel &panel, dynamic_desc &dynamic)
|
||||
: popup(panel), dynamic(dynamic)
|
||||
{
|
||||
prepare_str(dynamic.name, name_buf);
|
||||
prepare_str(dynamic.loadtype, load_buf);
|
||||
prepare_str(dynamic.params, param_buf);
|
||||
}
|
||||
|
||||
void ui::dynamic_edit_popup::render_content()
|
||||
{
|
||||
static std::unordered_map<coupling, std::string> coupling_names =
|
||||
{
|
||||
{ coupling::faux, STRN("faux") },
|
||||
{ coupling::coupler, STRN("coupler") },
|
||||
{ coupling::brakehose, STRN("brake hose") },
|
||||
{ coupling::control, STRN("control") },
|
||||
{ coupling::highvoltage, STRN("high voltage") },
|
||||
{ coupling::gangway, STRN("gangway") },
|
||||
{ coupling::mainhose, STRN("main hose") },
|
||||
{ coupling::heating, STRN("heating") },
|
||||
{ coupling::permanent, STRN("permanent") },
|
||||
{ coupling::uic, STRN("uic") }
|
||||
};
|
||||
|
||||
static std::vector<std::string> occupancy_names = {
|
||||
STRN("headdriver"),
|
||||
STRN("reardriver"),
|
||||
STRN("passenger"),
|
||||
STRN("nobody")
|
||||
};
|
||||
|
||||
std::string name = (dynamic.vehicle->path.parent_path() / dynamic.vehicle->path.stem()).string();
|
||||
|
||||
ImGui::Text(STR_C("Type: %s"), name.c_str());
|
||||
ImGui::NewLine();
|
||||
|
||||
if (ImGui::InputText(STR_C("Name"), name_buf.data(), name_buf.size()))
|
||||
dynamic.name = name_buf.data();
|
||||
|
||||
if (ImGui::BeginCombo(STR_C("Skin"), dynamic.skin->skin.c_str(), ImGuiComboFlags_HeightLargest))
|
||||
{
|
||||
for (auto const &skin : dynamic.vehicle->matching_skinsets) {
|
||||
bool is_selected = (skin == dynamic.skin);
|
||||
if (ImGui::Selectable(skin->skin.c_str(), is_selected))
|
||||
dynamic.skin = skin;
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::BeginCombo(STR_C("Occupancy"), Translations.lookup_c(dynamic.drivertype.c_str())))
|
||||
{
|
||||
for (auto const &str : occupancy_names) {
|
||||
bool is_selected = (str == dynamic.drivertype);
|
||||
if (ImGui::Selectable(Translations.lookup_c(str.c_str()), is_selected))
|
||||
dynamic.drivertype = str;
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::InputText(STR_C("Load type"), load_buf.data(), load_buf.size())) {
|
||||
dynamic.loadtype = load_buf.data();
|
||||
if (!load_buf[0])
|
||||
dynamic.loadtype = "none";
|
||||
}
|
||||
|
||||
if (dynamic.loadtype != "none")
|
||||
ImGui::InputInt(STR_C("Load count"), &dynamic.loadcount, 1, 10);
|
||||
else
|
||||
dynamic.loadcount = 0;
|
||||
|
||||
if (dynamic.loadcount < 0)
|
||||
dynamic.loadcount = 0;
|
||||
|
||||
if (ImGui::InputText(STR_C("Parameters"), param_buf.data(), param_buf.size()))
|
||||
dynamic.params = param_buf.data();
|
||||
|
||||
ImGui::NewLine();
|
||||
ImGui::TextUnformatted(STR_C("Coupling:"));
|
||||
|
||||
for (int i = 1; i <= 0x100; i <<= 1) {
|
||||
bool selected = dynamic.coupling & i;
|
||||
|
||||
std::string label = STRN("unknown");
|
||||
auto it = coupling_names.find(static_cast<coupling>(i));
|
||||
if (it != coupling_names.end())
|
||||
label = it->second;
|
||||
if (ImGui::Checkbox(Translations.lookup_c(label.c_str()), &selected))
|
||||
dynamic.coupling ^= i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,39 @@
|
||||
|
||||
#include "uilayer.h"
|
||||
#include "scenery_scanner.h"
|
||||
#include "widgets/popup.h"
|
||||
|
||||
namespace ui
|
||||
{
|
||||
class dynamic_edit_popup : public popup
|
||||
{
|
||||
dynamic_desc &dynamic;
|
||||
|
||||
std::array<char, 128> name_buf;
|
||||
std::array<char, 128> load_buf;
|
||||
std::array<char, 128> param_buf;
|
||||
|
||||
template <size_t n>
|
||||
void prepare_str(std::string &str, std::array<char, n> &array) {
|
||||
if (str.size() > array.size() - 1)
|
||||
str.resize(array.size() - 1);
|
||||
|
||||
std::copy(str.begin(), str.end(), array.data());
|
||||
array[str.size()] = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
dynamic_edit_popup(ui_panel &panel, dynamic_desc &dynamic);
|
||||
|
||||
virtual void render_content() override;
|
||||
};
|
||||
|
||||
class scenerylist_panel : public ui_panel
|
||||
{
|
||||
public:
|
||||
scenerylist_panel(scenery_scanner &scanner);
|
||||
|
||||
void render() override;
|
||||
void render_contents() override;
|
||||
|
||||
private:
|
||||
scenery_scanner &scanner;
|
||||
|
||||
Reference in New Issue
Block a user