mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 00:49:19 +02:00
semaphores controllable on minimap
This commit is contained in:
218
widgets/map.cpp
218
widgets/map.cpp
@@ -7,6 +7,7 @@
|
||||
#include "Camera.h"
|
||||
#include "simulation.h"
|
||||
#include "Driver.h"
|
||||
#include "AnimModel.h"
|
||||
|
||||
ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false)
|
||||
{
|
||||
@@ -115,8 +116,8 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si
|
||||
scene_ubo->update(scene_ubs);
|
||||
GfxRenderer.Draw_Geometry(m_switch_handles.begin(), m_switch_handles.end());
|
||||
|
||||
glPointSize(3.0f);
|
||||
scene_ubs.time = 0.0f;
|
||||
glPointSize(5.0f);
|
||||
scene_ubs.time = 1.0f;
|
||||
scene_ubo->update(scene_ubs);
|
||||
GfxRenderer.Draw_Geometry(simulation::Region->get_map_poi_geometry());
|
||||
|
||||
@@ -153,21 +154,7 @@ void ui::map_panel::render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (zoom > 0.005f) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 1.0f, 1.0f, 0.7f));
|
||||
for (auto sem : map::Semaphores) {
|
||||
glm::vec4 ndc_pos = transform * glm::vec4(sem->location, 1.0f);
|
||||
if (glm::abs(ndc_pos.x) > 1.0f || glm::abs(ndc_pos.z) > 1.0f)
|
||||
continue;
|
||||
|
||||
glm::vec2 gui_pos = (glm::vec2(ndc_pos.x, -ndc_pos.z) / 2.0f + 0.5f) * glm::vec2(surface_size.x, surface_size.y);
|
||||
|
||||
const char *desc = sem->name.c_str();
|
||||
ImVec2 textsize = ImGui::CalcTextSize(desc);
|
||||
ImGui::SetCursorPos(ImVec2(origin.x + gui_pos.x - textsize.x / 2.0f,
|
||||
origin.y + gui_pos.y - textsize.y / 2.0f));
|
||||
ImGui::TextUnformatted(desc);
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,19 +163,6 @@ void ui::map_panel::render_contents()
|
||||
if (!init_done)
|
||||
return;
|
||||
|
||||
if (active) {
|
||||
if (ImGui::BeginPopup("Sem")) {
|
||||
for (auto ev : active->events)
|
||||
if (ImGui::Button(ev->name().c_str())) {
|
||||
active.reset();
|
||||
command_relay relay;
|
||||
relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(ev), 0.0, GLFW_PRESS, 0);
|
||||
break;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
float prev_zoom = zoom;
|
||||
|
||||
if (ImGui::Button("-"))
|
||||
@@ -271,53 +245,169 @@ void ui::map_panel::render_contents()
|
||||
|
||||
translate -= delta * 2.0f;
|
||||
}
|
||||
if (ImGui::IsMouseClicked(1)) {
|
||||
else {
|
||||
ImVec2 screen_pos = ImGui::GetMousePos();
|
||||
glm::vec2 surface_pos(screen_pos.x - screen_origin.x, screen_pos.y - screen_origin.y);
|
||||
glm::vec2 ndc_pos = surface_pos / surface_size * 2.0f - 1.0f;
|
||||
glm::vec3 world_pos = glm::inverse(transform) * glm::vec4(ndc_pos.x, 0.0f, -ndc_pos.y, 1.0f);
|
||||
|
||||
std::vector<TEventLauncher *> launchers = simulation::Events.find_eventlaunchers(glm::vec2(world_pos.x, world_pos.z), 10.0f);
|
||||
map::sorted_object_list objects =
|
||||
map::Objects.find_in_range(glm::vec3(world_pos.x, NAN, world_pos.z), 0.03f / zoom);
|
||||
|
||||
float distx = 1000000.0f;
|
||||
if (ImGui::IsMouseClicked(1)) {
|
||||
if (objects.size() > 1)
|
||||
register_popup(std::make_unique<ui::disambiguation_popup>(*this, std::move(objects)));
|
||||
else if (objects.size() == 1)
|
||||
handle_map_object_click(*this, objects.begin()->second);
|
||||
|
||||
TEventLauncher *lau = nullptr;
|
||||
for (auto launcher : launchers) {
|
||||
float distance = glm::distance2(glm::vec2(launcher->location().x, launcher->location().z),
|
||||
glm::vec2(world_pos.x, world_pos.z));
|
||||
if (distance < distx) {
|
||||
lau = launcher;
|
||||
distx = distance;
|
||||
TTrack *nearest = simulation::Region->find_nearest_track_point(world_pos);
|
||||
if (nearest) {
|
||||
WriteLog(nearest->name());
|
||||
}
|
||||
//scene::basic_section &clicked_section = simulation::Region->section(world_pos);
|
||||
//clicked_section.
|
||||
}
|
||||
|
||||
if (lau) {
|
||||
command_relay relay;
|
||||
if (!Global.shiftState && lau->Event1)
|
||||
relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(lau->Event1), 0.0, GLFW_PRESS, 0);
|
||||
else if (lau->Event2)
|
||||
relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(lau->Event2), 0.0, GLFW_PRESS, 0);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<map::semaphore>> list;
|
||||
|
||||
for (auto entry : map::Semaphores) {
|
||||
float distance = glm::distance2(glm::vec2(entry->location.x, entry->location.z),
|
||||
glm::vec2(world_pos.x, world_pos.z));
|
||||
if (distance < 100.0f) {
|
||||
if (distance < distx) {
|
||||
list.clear();
|
||||
list.push_back(entry);
|
||||
distx = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!list.empty()) {
|
||||
ImGui::OpenPopup("Sem");
|
||||
active.emplace(*list[0].get());
|
||||
else if (!objects.empty()) {
|
||||
handle_map_object_hover(objects.begin()->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render_labels(transform, window_origin, surface_size);
|
||||
}
|
||||
|
||||
void ui::handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj)
|
||||
{
|
||||
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) {
|
||||
parent.register_popup(std::make_unique<semaphore_window>(parent, std::move(sem)));
|
||||
}
|
||||
else if (auto track = std::dynamic_pointer_cast<map::track_switch>(obj)) {
|
||||
parent.register_popup(std::make_unique<switch_window>(parent, std::move(track)));
|
||||
}
|
||||
}
|
||||
|
||||
void ui::handle_map_object_hover(std::shared_ptr<map::map_object> &obj)
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
|
||||
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) {
|
||||
for (auto &model : sem->models) {
|
||||
ImGui::PushID(model);
|
||||
ImGui::TextUnformatted(model->name().c_str());
|
||||
|
||||
for (int i = 0; i < iMaxNumLights; i++) {
|
||||
GfxRenderer.Update_AnimModel(model); // update lamp opacities
|
||||
auto state = model->LightGet(i);
|
||||
if (!state)
|
||||
continue;
|
||||
|
||||
glm::vec3 current_color = std::get<2>(*state).value_or(glm::vec3(0.5f)) * std::get<1>(*state);
|
||||
if (std::get<0>(*state) < 0.0f)
|
||||
continue;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(current_color.x, current_color.y, current_color.z, 1.0f));
|
||||
|
||||
std::string res = " ##" + std::to_string(i);
|
||||
ImGui::Button(res.c_str());
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
else if (auto sw = std::dynamic_pointer_cast<map::track_switch>(obj)) {
|
||||
ImGui::TextUnformatted(sw->name.c_str());
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ui::disambiguation_popup::disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list)
|
||||
: popup(panel), m_list(list) { }
|
||||
|
||||
void ui::disambiguation_popup::render_content()
|
||||
{
|
||||
for (auto &item : m_list) {
|
||||
if (ImGui::Button(item.second->name.c_str())) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
||||
handle_map_object_click(m_parent, item.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui::semaphore_window::semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem)
|
||||
: popup(panel), m_sem(sem) { }
|
||||
|
||||
void ui::semaphore_window::render_content()
|
||||
{
|
||||
for (auto &model : m_sem->models) {
|
||||
ImGui::PushID(model);
|
||||
ImGui::TextUnformatted(model->name().c_str());
|
||||
|
||||
for (int i = 0; i < iMaxNumLights; i++) {
|
||||
GfxRenderer.Update_AnimModel(model); // update lamp opacities
|
||||
auto state = model->LightGet(i);
|
||||
if (!state)
|
||||
continue;
|
||||
|
||||
glm::vec3 lamp_color = std::get<2>(*state).value_or(glm::vec3(0.5f));
|
||||
glm::vec3 current_color = lamp_color * std::get<1>(*state);
|
||||
float level = std::get<0>(*state);
|
||||
|
||||
if (level < 0.0f)
|
||||
continue;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(lamp_color.x, lamp_color.y, lamp_color.z, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(current_color.x, current_color.y, current_color.z, 1.0f));
|
||||
|
||||
std::string res = " ##" + std::to_string(i);
|
||||
if (ImGui::Button(res.c_str())) {
|
||||
level += 1.0f;
|
||||
if (level >= 3.0f)
|
||||
level = 0.0f;
|
||||
|
||||
int id = simulation::Instances.find_id(model->name());
|
||||
m_relay.post(user_command::setlight, (double)i, level, id, 0);
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(2);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto &item : m_sem->events) {
|
||||
std::string displayname = item->name().substr(m_sem->name.size());
|
||||
|
||||
if (displayname.size() < 2)
|
||||
continue;
|
||||
|
||||
displayname[1] = std::toupper(displayname[1]);
|
||||
|
||||
if (ImGui::Button(displayname.c_str())) {
|
||||
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(item), 0.0, GLFW_PRESS, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui::switch_window::switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw)
|
||||
: popup(panel), m_switch(sw) { }
|
||||
|
||||
void ui::switch_window::render_content()
|
||||
{
|
||||
ImGui::TextUnformatted(m_switch->name.c_str());
|
||||
|
||||
if (ImGui::Button(LOC_STR(map_straight))) {
|
||||
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->straight_event), 0.0, GLFW_PRESS, 0);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
if (ImGui::Button(LOC_STR(map_divert))) {
|
||||
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->divert_event), 0.0, GLFW_PRESS, 0);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,18 +5,37 @@
|
||||
#include "Texture.h"
|
||||
#include "uilayer.h"
|
||||
#include "widgets/map_objects.h"
|
||||
#include "widgets/popup.h"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class disambiguation_popup {
|
||||
std::string m_id;
|
||||
std::vector<map::semaphore> m_list;
|
||||
class disambiguation_popup : public popup {
|
||||
map::sorted_object_list m_list;
|
||||
|
||||
public:
|
||||
disambiguation_popup(std::string &&id, std::vector<map::semaphore> &&list)
|
||||
: m_id(id), m_list(list) {}
|
||||
disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list);
|
||||
|
||||
void render();
|
||||
virtual void render_content() override;
|
||||
};
|
||||
|
||||
class semaphore_window : public popup {
|
||||
std::shared_ptr<map::semaphore> m_sem;
|
||||
command_relay m_relay;
|
||||
|
||||
public:
|
||||
semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem);
|
||||
|
||||
virtual void render_content() override;
|
||||
};
|
||||
|
||||
class switch_window : public popup {
|
||||
std::shared_ptr<map::track_switch> m_switch;
|
||||
command_relay m_relay;
|
||||
|
||||
public:
|
||||
switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw);
|
||||
|
||||
virtual void render_content() override;
|
||||
};
|
||||
|
||||
class map_panel : public ui_panel {
|
||||
@@ -50,4 +69,6 @@ public:
|
||||
void render_contents() override;
|
||||
};
|
||||
|
||||
void handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj);
|
||||
void handle_map_object_hover(std::shared_ptr<map::map_object> &obj);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,27 @@
|
||||
#include "widgets/map_objects.h"
|
||||
|
||||
std::vector<std::shared_ptr<map::semaphore>> map::Semaphores;
|
||||
std::vector<std::shared_ptr<map::track_switch>> map::Switches;
|
||||
map::objects map::Objects;
|
||||
|
||||
map::sorted_object_list map::objects::find_in_range(glm::vec3 from, float distance)
|
||||
{
|
||||
sorted_object_list items;
|
||||
|
||||
float max_distance2 = distance * distance;
|
||||
|
||||
for (auto const entry : entries) {
|
||||
glm::vec3 entry_location = entry->location;
|
||||
glm::vec3 search_point = from;
|
||||
|
||||
if (glm::isnan(from.y)) {
|
||||
entry_location.y = 0.0f;
|
||||
search_point.y = 0.0f;
|
||||
}
|
||||
|
||||
float dist = glm::distance2(entry_location, search_point);
|
||||
if (dist < max_distance2) {
|
||||
items.emplace(dist, std::move(entry));
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -6,19 +6,35 @@
|
||||
|
||||
namespace map {
|
||||
|
||||
// semaphore description (only for minimap purposes)
|
||||
struct semaphore {
|
||||
struct map_object {
|
||||
std::string name;
|
||||
glm::vec3 location;
|
||||
|
||||
virtual ~map_object() = default;
|
||||
};
|
||||
|
||||
using object_list = std::vector<std::shared_ptr<map::map_object>>;
|
||||
using sorted_object_list = std::map<float, std::shared_ptr<map::map_object>>;
|
||||
|
||||
// semaphore description (only for minimap purposes)
|
||||
struct semaphore : public map_object {
|
||||
std::vector<TAnimModel *> models;
|
||||
|
||||
std::vector<basic_event *> events;
|
||||
};
|
||||
|
||||
// switch description (only for minimap purposes)
|
||||
struct track_switch {
|
||||
glm::vec3 location;
|
||||
struct track_switch : public map_object {
|
||||
basic_event *straight_event = nullptr;
|
||||
basic_event *divert_event = nullptr;
|
||||
};
|
||||
|
||||
extern std::vector<std::shared_ptr<semaphore>> Semaphores;
|
||||
extern std::vector<std::shared_ptr<track_switch>> Switches;
|
||||
struct objects {
|
||||
std::vector<std::shared_ptr<map_object>> entries;
|
||||
|
||||
// returns objects in range from vec3, NaN in Y ignores it
|
||||
sorted_object_list find_in_range(glm::vec3 from, float distance);
|
||||
};
|
||||
|
||||
extern objects Objects;
|
||||
}
|
||||
|
||||
29
widgets/popup.cpp
Normal file
29
widgets/popup.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "widgets/popup.h"
|
||||
|
||||
ui::popup::popup(ui_panel &panel)
|
||||
: m_parent(panel)
|
||||
{
|
||||
}
|
||||
|
||||
ui::popup::~popup()
|
||||
{
|
||||
}
|
||||
|
||||
bool ui::popup::render()
|
||||
{
|
||||
if (!m_id.size()) {
|
||||
m_id = "popup:" + std::to_string(id++);
|
||||
ImGui::OpenPopup(m_id.c_str());
|
||||
}
|
||||
|
||||
if (!ImGui::BeginPopup(m_id.c_str()))
|
||||
return true;
|
||||
|
||||
render_content();
|
||||
|
||||
ImGui::EndPopup();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ui::popup::id = 0;
|
||||
22
widgets/popup.h
Normal file
22
widgets/popup.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
class ui_panel;
|
||||
|
||||
namespace ui {
|
||||
|
||||
class popup {
|
||||
std::string m_id;
|
||||
static int id;
|
||||
|
||||
public:
|
||||
popup(ui_panel &panel);
|
||||
~popup();
|
||||
|
||||
bool render();
|
||||
|
||||
protected:
|
||||
ui_panel &m_parent;
|
||||
virtual void render_content() = 0;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user