diff --git a/CMakeLists.txt b/CMakeLists.txt index 719832c0..4deb6e07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,6 @@ set(SOURCES "simulationstateserializer.cpp" "precipitation.cpp" "texturewindow.cpp" -"map.cpp" "network/network.cpp" "network/message.cpp" @@ -125,6 +124,7 @@ set(SOURCES "network/backend/asio.cpp" "widgets/vehiclelist.cpp" +"widgets/map.cpp" "ref/glad/src/glad.c" diff --git a/Globals.cpp b/Globals.cpp index 0fd5daca..e8b1c098 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -787,11 +787,6 @@ global_settings::ConfigParse(cParser &Parser) { { Parser.getTokens(1); Parser >> gfx_shadergamma; - } - else if (token == "map.enabled") - { - Parser.getTokens(1); - Parser >> map_enabled; } else if (token == "python.displaywindows") { diff --git a/Globals.h b/Globals.h index 0881ca19..2fd84ad3 100644 --- a/Globals.h +++ b/Globals.h @@ -185,7 +185,6 @@ struct global_settings { bool python_mipmaps = true; bool python_displaywindows = false; bool python_threadedupload = true; - bool map_enabled = true; int gfx_framebuffer_width = -1; int gfx_framebuffer_height = -1; diff --git a/application.cpp b/application.cpp index 0a8f24b5..cf84a256 100644 --- a/application.cpp +++ b/application.cpp @@ -591,7 +591,7 @@ eu07_application::init_glfw() { if (!Global.gfx_usegles) { - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); } diff --git a/driveruilayer.cpp b/driveruilayer.cpp index 5e86884b..7d97298d 100644 --- a/driveruilayer.cpp +++ b/driveruilayer.cpp @@ -28,6 +28,7 @@ driver_ui::driver_ui() { push_back( &m_transcriptspanel ); //push_back( &m_vehiclelist ); + push_back( &m_mappanel ); push_back( &m_logpanel ); m_logpanel.is_open = false; @@ -45,11 +46,12 @@ driver_ui::driver_ui() { void driver_ui::render_menu_contents() { ui_layer::render_menu_contents(); - if (ImGui::BeginMenu(locale::strings[locale::string::ui_mode_windows].c_str())) + if (ImGui::BeginMenu(locale::strings[locale::string::ui_mode_windows].c_str())) { ImGui::MenuItem(m_aidpanel.title.c_str(), "F1", &m_aidpanel.is_open); ImGui::MenuItem(m_timetablepanel.title.c_str(), "F2", &m_timetablepanel.is_open); ImGui::MenuItem(m_debugpanel.get_name().c_str(), "F12", &m_debugpanel.is_open); + ImGui::MenuItem(m_mappanel.get_name().c_str(), "Tab", &m_mappanel.is_open); ImGui::EndMenu(); } } @@ -62,6 +64,7 @@ driver_ui::on_key( int const Key, int const Action ) { switch( Key ) { + case GLFW_KEY_TAB: case GLFW_KEY_F1: case GLFW_KEY_F2: case GLFW_KEY_F10: @@ -83,6 +86,12 @@ driver_ui::on_key( int const Key, int const Action ) { switch (Key) { + case GLFW_KEY_TAB: { + m_mappanel.is_open = !m_mappanel.is_open; + + return true; + } + case GLFW_KEY_F1: { // basic consist info auto state = ( diff --git a/driveruilayer.h b/driveruilayer.h index a7a34ade..9ddf8101 100644 --- a/driveruilayer.h +++ b/driveruilayer.h @@ -11,8 +11,10 @@ http://mozilla.org/MPL/2.0/. #include "uilayer.h" #include "driveruipanels.h" +#include "command.h" #include "widgets/vehiclelist.h" +#include "widgets/map.h" class driver_ui : public ui_layer { @@ -55,4 +57,5 @@ private: command_relay m_relay; ui::vehiclelist_panel m_vehiclelist; + ui::map_panel m_mappanel; }; diff --git a/map.cpp b/map.cpp deleted file mode 100644 index d948b510..00000000 --- a/map.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "stdafx.h" -#include "map.h" -#include "imgui/imgui.h" -#include "Logs.h" -#include "Train.h" -#include "Camera.h" -#include "simulation.h" - -bool map::init() -{ - WriteLog("initializing map gfx..."); - - gl::shader vert("map.vert"); - gl::shader frag("map.frag"); - gl::program *prog = new gl::program({vert, frag}); - m_shader = std::unique_ptr(prog); - - m_tex = std::make_unique(); - m_tex->alloc_rendertarget(GL_RGB8, GL_RGB, fb_size, fb_size); - - m_fb = std::make_unique(); - m_fb->attach(*m_tex, GL_COLOR_ATTACHMENT0); - - m_fb->setup_drawing(1); - - if (!m_fb->is_complete()) - { - ErrorLog("map framebuffer incomplete"); - return false; - } - - if (Global.iMultisampling) - { - m_msaa_rb = std::make_unique(); - m_msaa_rb->alloc(GL_RGB8, fb_size, fb_size, 1 << Global.iMultisampling); - - m_msaa_fb = std::make_unique(); - m_msaa_fb->attach(*m_msaa_rb, GL_COLOR_ATTACHMENT0); - - m_msaa_fb->setup_drawing(1); - - if (!m_msaa_fb->is_complete()) - { - ErrorLog("map multisampling framebuffer incomplete"); - return false; - } - } - - scene_ubo = std::make_unique(sizeof(gl::scene_ubs), 0); - - WriteLog("map init ok"); - - return true; -} - -float map::get_vehicle_rotation() -{ - const TDynamicObject *vehicle = simulation::Train->Dynamic(); - glm::vec3 front = glm::dvec3(vehicle->VectorFront()) * (vehicle->DirectionGet() > 0 ? 1.0 : -1.0); - glm::vec2 f2(front.x, front.z); - glm::vec2 north_ptr(0.0f, 1.0f); - return glm::atan(f2.y, f2.x) - glm::atan(north_ptr.y, north_ptr.x); -} - -void map::render(scene::basic_region *Region) -{ - if (!map_opened) - return; - - if (!scene_ubo) - if (!init()) - { - map_opened = false; - return; - } - - ImGui::SetNextWindowSizeConstraints(ImVec2(200, 200), ImVec2(fb_size, fb_size)); - if (ImGui::Begin("Map", &map_opened, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) - { - float prevzoom = zoom; - - if (ImGui::Button("-")) - zoom /= 2; - ImGui::SameLine(); - if (ImGui::Button("+")) - zoom *= 2; - ImGui::SameLine(); - - float x = zoom / prevzoom; - translate *= x; - - glm::mat4 transform; - transform[0][0] = -1.0f; - - static int mode = 0; - ImGui::RadioButton("manual", &mode, 0); ImGui::SameLine(); - ImGui::RadioButton("cam", &mode, 1); ImGui::SameLine(); - ImGui::RadioButton("vehicle", &mode, 2); - - if (mode == 2 && simulation::Train && simulation::Train->Dynamic()) - { - float rot = get_vehicle_rotation(); - - transform = glm::rotate(transform, rot, glm::vec3(0.0f, 1.0f, 0.0f)); - - glm::dvec3 vpos = simulation::Train->Dynamic()->GetPosition(); - translate = glm::vec2(vpos.x, vpos.z) * -zoom; - } - else if (mode == 1) - { - float rot; - if (FreeFlyModeFlag) - rot = glm::pi() - Global.pCamera.Angle.y; - else - rot = get_vehicle_rotation() - Global.pCamera.Angle.y; - - transform = glm::rotate(transform, rot, glm::vec3(0.0f, 1.0f, 0.0f)); - - glm::dvec3 vpos = Global.pCamera.Pos; - translate = glm::vec2(vpos.x, vpos.z) * -zoom; - } - - ImVec2 size = ImGui::GetContentRegionAvail(); - - transform = glm::translate(transform, glm::vec3(translate.x, 0.0f, translate.y)); - transform = glm::scale(transform, glm::vec3(zoom)); - - frustum.calculate(transform, glm::mat4()); - - m_section_handles.clear(); - - for (int row = 0; row < scene::EU07_REGIONSIDESECTIONCOUNT; row++) - { - for (int column = 0; column < scene::EU07_REGIONSIDESECTIONCOUNT; column++) - { - scene::basic_section *s = Region->get_section(row * scene::EU07_REGIONSIDESECTIONCOUNT + column); - if (s && frustum.sphere_inside(s->area().center, s->area().radius) > 0.f) - { - const gfx::geometrybank_handle handle = s->get_map_geometry(); - if (handle != null_handle) - m_section_handles.push_back(handle); - } - } - } - - scene_ubs.projection = transform; - scene_ubo->update(scene_ubs); - scene_ubo->bind_uniform(); - - glDisable(GL_DEPTH_TEST); - if (Global.iMultisampling) - { - m_msaa_fb->clear(GL_COLOR_BUFFER_BIT); - m_msaa_fb->bind(); - } - else - { - m_fb->clear(GL_COLOR_BUFFER_BIT); - m_fb->bind(); - } - - m_shader->bind(); - glLineWidth(1.5f); - glViewport(0, 0, size.x, size.y); - - GfxRenderer.Draw_Geometry(m_section_handles.begin(), m_section_handles.end()); - - if (Global.iMultisampling) - m_fb->blit_from(m_msaa_fb.get(), size.x, size.y, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0); - - gl::framebuffer::unbind(); - m_shader->unbind(); - - ImGui::ImageButton(reinterpret_cast(m_tex->id), size, ImVec2(0, size.y / fb_size), ImVec2(size.x / fb_size, 0), 0); - - if (mode == 0 && ImGui::IsItemHovered() && ImGui::IsMouseDragging()) - { - ImVec2 ivdelta = ImGui::GetMouseDragDelta(); - ImGui::ResetMouseDragDelta(); - - glm::vec2 delta(ivdelta.x, ivdelta.y); - delta.x /= size.x; - delta.y /= size.y; - - translate -= delta * 2.0f; - } - } - ImGui::End(); -} - -void map::toggle_window() -{ - map_opened = !map_opened; -} diff --git a/network/network.cpp b/network/network.cpp index d78a77ac..030e1b59 100644 --- a/network/network.cpp +++ b/network/network.cpp @@ -4,6 +4,7 @@ #include "sn_utils.h" #include "Timer.h" #include "application.h" +#include "Globals.h" // connection diff --git a/shaders/map.frag b/shaders/map.frag index 6d8ec416..ebeb99eb 100644 --- a/shaders/map.frag +++ b/shaders/map.frag @@ -4,5 +4,5 @@ layout(location = 0) out vec4 out_color; void main() { - out_color = vec4(1.0f); + out_color = vec4(0.5f); } diff --git a/simulationstateserializer.cpp b/simulationstateserializer.cpp index 67951ecf..02ad1928 100644 --- a/simulationstateserializer.cpp +++ b/simulationstateserializer.cpp @@ -116,8 +116,7 @@ state_serializer::deserialize_continue(std::shared_ptr state deserialize_firstinit( Input, Scratchpad ); } - if (Global.map_enabled) - Region->create_map_geometry(); + Region->create_map_geometry(); if( ( false == state->scratchpad.binary.terrain ) && ( state->scenariofile != "$.scn" ) ) { diff --git a/uilayer.cpp b/uilayer.cpp index f8fd8aa1..b28c23da 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -27,11 +27,8 @@ http://mozilla.org/MPL/2.0/. GLFWwindow *ui_layer::m_window{nullptr}; ImGuiIO *ui_layer::m_imguiio{nullptr}; -std::unique_ptr ui_layer::m_map; bool ui_layer::m_cursorvisible; -#define LOC_STR(x) locale::strings[locale::string::x].c_str() - ui_panel::ui_panel(std::string const &Identifier, bool const Isopen) : name(Identifier), is_open(Isopen) {} void ui_panel::render() @@ -39,12 +36,15 @@ void ui_panel::render() if (false == is_open) return; - auto flags = ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoCollapse | (size.x > 0 ? ImGuiWindowFlags_NoResize : 0); + int flags = window_flags; + if (flags == -1) + flags = ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoCollapse | + ((size.x > 0 || size_min.x > 0) ? ImGuiWindowFlags_NoResize : 0); if (size.x > 0) ImGui::SetNextWindowSize(ImVec2(size.x, size.y)); - else - ImGui::SetNextWindowSize(ImVec2(0, 0)); + else if (size_min.x == -1) + ImGui::SetNextWindowSize(ImVec2(0, 0)); if (size_min.x > 0) ImGui::SetNextWindowSizeConstraints(ImVec2(size_min.x, size_min.y), ImVec2(size_max.x, size_max.y)); @@ -130,9 +130,6 @@ bool ui_layer::init(GLFWwindow *Window) m_imguiio->Fonts->AddFontFromFileTTF("fonts/dejavusansmono.ttf", 13.0f, nullptr, &ranges[0]); - if (Global.map_enabled) - m_map = std::make_unique(); - ImGui::StyleColorsDark(); ImGui_ImplGlfw_InitForOpenGL(m_window); #ifdef EU07_USEIMGUIIMPLOPENGL2 @@ -169,13 +166,6 @@ bool ui_layer::on_key(int const Key, int const Action) { if (Action == GLFW_PRESS) { - if (Key == GLFW_KEY_TAB) { - if (m_map) - m_map->toggle_window(); - - return true; - } - if (Key == GLFW_KEY_PRINT_SCREEN) { Application.queue_screenshot(); return true; @@ -236,9 +226,6 @@ void ui_layer::render() render_menu(); render_quit_widget(); - if (m_map && simulation::is_ready) - m_map->render(simulation::Region); - // template method implementation render_(); @@ -366,8 +353,6 @@ void ui_layer::render_menu_contents() if (ImGui::BeginMenu(LOC_STR(ui_windows))) { ImGui::MenuItem(LOC_STR(ui_log), "F9", &m_logpanel.is_open); - if (Global.map_enabled && m_map) - ImGui::MenuItem(LOC_STR(ui_map), "Tab", &m_map->map_opened); if (DebugModeFlag) ImGui::MenuItem("Headlight config", nullptr, &GfxRenderer.debug_ui_active); ImGui::EndMenu(); diff --git a/uilayer.h b/uilayer.h index 945934f4..597582a1 100644 --- a/uilayer.h +++ b/uilayer.h @@ -11,10 +11,12 @@ http://mozilla.org/MPL/2.0/. #include #include "Texture.h" -#include "map.h" +#include "translation.h" // GuiLayer -- basic user interface class. draws requested information on top of openGL screen +#define LOC_STR(x) locale::strings[locale::string::x].c_str() + class ui_panel { public: @@ -38,10 +40,12 @@ public: // members std::string title; bool is_open; + glm::ivec2 size { -1, -1 }; glm::ivec2 size_min { -1, -1 }; glm::ivec2 size_max { -1, -1 }; std::deque text_lines; + int window_flags = -1; std::string get_name() { return name; } @@ -160,7 +164,6 @@ private: void render_quit_widget(); - static std::unique_ptr m_map; // draws a quad between coordinates x,y and z,w with uv-coordinates spanning 0-1 void quad( glm::vec4 const &Coordinates, glm::vec4 const &Color ); diff --git a/widgets/map.cpp b/widgets/map.cpp new file mode 100644 index 00000000..5f354f28 --- /dev/null +++ b/widgets/map.cpp @@ -0,0 +1,207 @@ +#include "stdafx.h" +#include "widgets/map.h" +#include "imgui/imgui.h" +#include "Logs.h" +#include "Train.h" +#include "Camera.h" +#include "simulation.h" +#include "Driver.h" + +ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false) +{ + size_min = { 200, 200 }; + size_max = { fb_size, fb_size }; + window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse; + + gl::shader vert("map.vert"); + gl::shader frag("map.frag"); + gl::program *prog = new gl::program({vert, frag}); + m_shader = std::unique_ptr(prog); + + m_tex = std::make_unique(); + m_tex->alloc_rendertarget(GL_RGB8, GL_RGB, fb_size, fb_size); + + m_fb = std::make_unique(); + m_fb->attach(*m_tex, GL_COLOR_ATTACHMENT0); + + m_fb->setup_drawing(1); + + if (!m_fb->is_complete()) + { + ErrorLog("map framebuffer incomplete"); + return; + } + + if (Global.iMultisampling) + { + m_msaa_rb = std::make_unique(); + m_msaa_rb->alloc(GL_RGB8, fb_size, fb_size, 1 << Global.iMultisampling); + + m_msaa_fb = std::make_unique(); + m_msaa_fb->attach(*m_msaa_rb, GL_COLOR_ATTACHMENT0); + + m_msaa_fb->setup_drawing(1); + + if (!m_msaa_fb->is_complete()) + { + ErrorLog("map multisampling framebuffer incomplete"); + return; + } + } + + scene_ubo = std::make_unique(sizeof(gl::scene_ubs), 0); + + init_done = true; +} + +float ui::map_panel::get_vehicle_rotation() +{ + const TDynamicObject *vehicle = simulation::Train->Dynamic(); + glm::vec3 front = glm::dvec3(vehicle->VectorFront()) * (vehicle->DirectionGet() > 0 ? 1.0 : -1.0); + glm::vec2 f2(front.x, front.z); + glm::vec2 north_ptr(0.0f, 1.0f); + return glm::atan(f2.y, f2.x) - glm::atan(north_ptr.y, north_ptr.x); +} + +void ui::map_panel::render_contents() +{ + if (!init_done) + return; + + scene::basic_region *Region = simulation::Region; + + float prevzoom = zoom; + + if (ImGui::Button("-")) + zoom /= 2; + ImGui::SameLine(); + if (ImGui::Button("+")) + zoom *= 2; + ImGui::SameLine(); + + float x = zoom / prevzoom; + translate *= x; + + glm::mat4 transform; + transform[0][0] = -1.0f; + + static int mode = 0; + ImGui::RadioButton("manual", &mode, 0); ImGui::SameLine(); + ImGui::RadioButton("cam", &mode, 1); ImGui::SameLine(); + ImGui::RadioButton("vehicle", &mode, 2); + + ImVec2 size = ImGui::GetContentRegionAvail(); + + float aspectx = size.y / size.x; + float aspectz = size.x / size.y; + + if (aspectx > aspectz) + transform = glm::scale(transform, glm::vec3(aspectx, 1.0f, 1.0f)); + else + transform = glm::scale(transform, glm::vec3(1.0f, 1.0f, aspectz)); + + if (mode == 2 && simulation::Train && simulation::Train->Dynamic()) + { + float rot = get_vehicle_rotation(); + + transform = glm::rotate(transform, rot, glm::vec3(0.0f, 1.0f, 0.0f)); + + glm::dvec3 vpos = simulation::Train->Dynamic()->GetPosition(); + translate = glm::vec2(vpos.x, vpos.z) * -zoom; + } + else if (mode == 1) + { + float rot; + if (FreeFlyModeFlag) + rot = glm::pi() - Global.pCamera.Angle.y; + else + rot = get_vehicle_rotation() - Global.pCamera.Angle.y; + + transform = glm::rotate(transform, rot, glm::vec3(0.0f, 1.0f, 0.0f)); + + glm::dvec3 vpos = Global.pCamera.Pos; + translate = glm::vec2(vpos.x, vpos.z) * -zoom; + } + + transform = glm::translate(transform, glm::vec3(translate.x, 0.0f, translate.y)); + transform = glm::scale(transform, glm::vec3(zoom)); + + frustum.calculate(transform, glm::mat4()); + + m_section_handles.clear(); + + for (int row = 0; row < scene::EU07_REGIONSIDESECTIONCOUNT; row++) + { + for (int column = 0; column < scene::EU07_REGIONSIDESECTIONCOUNT; column++) + { + scene::basic_section *s = Region->get_section(row * scene::EU07_REGIONSIDESECTIONCOUNT + column); + if (s && frustum.sphere_inside(s->area().center, s->area().radius) > 0.f) + { + const gfx::geometrybank_handle handle = s->get_map_geometry(); + if (handle != null_handle) + m_section_handles.push_back(handle); + } + } + } + + scene_ubs.projection = transform; + scene_ubo->update(scene_ubs); + scene_ubo->bind_uniform(); + + glDisable(GL_DEPTH_TEST); + if (Global.iMultisampling) + { + m_msaa_fb->clear(GL_COLOR_BUFFER_BIT); + m_msaa_fb->bind(); + } + else + { + m_fb->clear(GL_COLOR_BUFFER_BIT); + m_fb->bind(); + } + + m_shader->bind(); + glLineWidth(1.5f); + glViewport(0, 0, size.x, size.y); + + GfxRenderer.Draw_Geometry(m_section_handles.begin(), m_section_handles.end()); + + if (Global.iMultisampling) + m_fb->blit_from(m_msaa_fb.get(), size.x, size.y, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0); + + gl::framebuffer::unbind(); + m_shader->unbind(); + + ImVec2 origin = ImGui::GetCursorPos(); + ImGui::ImageButton(reinterpret_cast(m_tex->id), size, ImVec2(0, size.y / fb_size), ImVec2(size.x / fb_size, 0), 0); + if (mode == 0 && ImGui::IsItemHovered() && ImGui::IsMouseDragging()) + { + ImVec2 ivdelta = ImGui::GetMouseDragDelta(); + ImGui::ResetMouseDragDelta(); + + glm::vec2 delta(ivdelta.x, ivdelta.y); + delta.x /= size.x; + delta.y /= size.y; + + translate -= delta * 2.0f; + } + + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 1.0f, 0.7f, 1.0f)); + for (TDynamicObject *vehicle : simulation::Vehicles.sequence()) { + if (vehicle->Prev()) + continue; + + glm::vec4 pos = transform * glm::vec4(glm::vec3(vehicle->GetPosition()), 1.0f); + if (glm::abs(pos.x) > 1.0f || glm::abs(pos.z) > 1.0f) + continue; + + glm::vec2 textpos = (glm::vec2(pos.x, -pos.z) / 2.0f + 0.5f) * glm::vec2(size.x, size.y); + + const char *desc = vehicle->Mechanik->TrainName().c_str(); + ImVec2 textsize = ImGui::CalcTextSize(desc); + ImGui::SetCursorPos(ImVec2(origin.x + textpos.x - textsize.x / 2.0f, + origin.y + textpos.y - textsize.y / 2.0f)); + ImGui::TextUnformatted(desc); + } + ImGui::PopStyleColor(); +} diff --git a/map.h b/widgets/map.h similarity index 74% rename from map.h rename to widgets/map.h index 6940bb93..425b71ab 100644 --- a/map.h +++ b/widgets/map.h @@ -3,10 +3,12 @@ #include "gl/shader.h" #include "renderer.h" #include "Texture.h" +#include "uilayer.h" -class map -{ - std::unique_ptr m_shader; +namespace ui { + +class map_panel : public ui_panel { + std::unique_ptr m_shader; std::unique_ptr m_msaa_fb; std::unique_ptr m_msaa_rb; @@ -23,12 +25,13 @@ class map glm::vec2 translate; float zoom = 1.0f / 1000.0f; float get_vehicle_rotation(); - - bool init(); - cFrustum frustum; + + bool init_done = false; + public: - bool map_opened = false; - void render(scene::basic_region *Region); - void toggle_window(); + map_panel(); + void render_contents() override; }; + +}