mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-10 16:03:16 +01:00
Merge branch 'master' into feat/renderers-cleanup
This commit is contained in:
@@ -295,7 +295,7 @@ void eu07_application::DiscordRPCService()
|
||||
if (currentMode != mode::driver)
|
||||
{
|
||||
// the editor and the other modes: nothing to tell, without spinning a core on it
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(250));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -715,19 +715,29 @@ void eu07_application::release_python_lock()
|
||||
void eu07_application::exit()
|
||||
{
|
||||
Global.applicationQuitOrder = true;
|
||||
// each step of the closing in the log, to tell from it where a closing that hangs stops
|
||||
auto const closing{std::chrono::steady_clock::now()};
|
||||
auto const step = [closing](char const *What) {
|
||||
WriteLog(std::format("Closing: {} at {} ms", What, std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - closing).count()));
|
||||
};
|
||||
step("the modes");
|
||||
for (auto &mode : m_modes)
|
||||
mode.reset();
|
||||
|
||||
step("the renderer");
|
||||
GfxRenderer->Shutdown();
|
||||
m_network.reset();
|
||||
|
||||
// SafeDelete( simulation::Train );
|
||||
step("the scenery");
|
||||
SafeDelete(simulation::Region);
|
||||
|
||||
step("the ui and the python workers");
|
||||
ui_layer::shutdown();
|
||||
|
||||
// the python workers detach their GL context on the way out, so they have to be done before the windows they use are destroyed
|
||||
m_taskqueue.exit();
|
||||
step("the windows");
|
||||
for (auto *window : m_windows)
|
||||
{
|
||||
glfwDestroyWindow(window);
|
||||
@@ -738,6 +748,8 @@ void eu07_application::exit()
|
||||
if (!Global.exec_on_exit.empty())
|
||||
system(Global.exec_on_exit.c_str());
|
||||
|
||||
step("done");
|
||||
StopLogService();
|
||||
auto it = Global.threads.find("LogService");
|
||||
if (it != Global.threads.end())
|
||||
{
|
||||
|
||||
@@ -74,9 +74,9 @@ void driver_ui::render_menu_contents()
|
||||
if (ImGui::BeginMenu(STR_C("Mode windows")))
|
||||
{
|
||||
ImGui::MenuItem(m_aidpanel.title.c_str(), "F1", &m_aidpanel.is_open);
|
||||
ImGui::MenuItem(m_scenariopanel.title.c_str(), "F1", &m_aidpanel.is_open);
|
||||
ImGui::MenuItem(STR_C("Timetable"), "F2", &m_timetablepanel.is_open);
|
||||
ImGui::MenuItem(m_debugpanel.name().c_str(), "F12", &m_debugpanel.is_open);
|
||||
ImGui::MenuItem(m_scenariopanel.title.c_str(), "F3", &m_scenariopanel.is_open);
|
||||
ImGui::MenuItem(m_debugpanel.name().c_str(), "Shift+F12", &m_debugpanel.is_open);
|
||||
ImGui::MenuItem(m_mappanel.name().c_str(), "Tab", &m_mappanel.is_open);
|
||||
ImGui::MenuItem(m_vehiclelist.name().c_str(), nullptr, &m_vehiclelist.is_open);
|
||||
ImGui::MenuItem(m_trainingcardpanel.name().c_str(), nullptr, &m_trainingcardpanel.is_open);
|
||||
|
||||
@@ -1067,6 +1067,7 @@ class editor_mode : public application_mode, private editor_track::observer, pri
|
||||
void track_gizmo_length(TTrack &Track, double Length);
|
||||
void track_gizmo_end(TTrack &Track);
|
||||
bool m_track_dirty{false};
|
||||
bool m_track_drag_on_the_way{false}; // committed, but not as the end of the drag
|
||||
std::chrono::steady_clock::time_point m_track_last_commit;
|
||||
editor_track::state m_track_field_before;
|
||||
// the event to add to the path, typed
|
||||
|
||||
@@ -126,8 +126,8 @@ bool is_curved(segment_data const &Path)
|
||||
|
||||
void copy_text(char *Buffer, std::size_t const Size, std::string const &Text)
|
||||
{
|
||||
std::strncpy(Buffer, Text.c_str(), Size - 1);
|
||||
Buffer[Size - 1] = 0;
|
||||
// as much of the text as fits, always terminated
|
||||
Buffer[Text.copy(Buffer, Size - 1)] = 0;
|
||||
}
|
||||
|
||||
std::string lower_case(std::string Text)
|
||||
|
||||
@@ -263,12 +263,14 @@ void editor_mode::draw_track_overlay() const
|
||||
|
||||
void editor_mode::commit_track_drag(bool const Force)
|
||||
{
|
||||
if (false == m_track_dirty || m_track_drag.empty())
|
||||
// on letting go the rest of what follows the dragged tracks is yet to come, even with all of the drag committed
|
||||
if ((false == m_track_dirty && false == (Force && m_track_drag_on_the_way)) || m_track_drag.empty())
|
||||
return;
|
||||
auto const now = std::chrono::steady_clock::now();
|
||||
if (false == Force && now - m_track_last_commit < std::chrono::milliseconds(100))
|
||||
return;
|
||||
editor_track::commit(m_track_drag);
|
||||
editor_track::commit(m_track_drag, false == Force);
|
||||
m_track_drag_on_the_way = false == Force;
|
||||
m_track_dirty = false;
|
||||
m_track_last_commit = now;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "scene/scenelayers.h"
|
||||
#include "simulation/simulation.h"
|
||||
#include "utilities/Globals.h"
|
||||
#include "utilities/Logs.h"
|
||||
#include "utilities/translation.h"
|
||||
#include "utilities/utilities.h"
|
||||
#include "world/Track.h"
|
||||
@@ -174,6 +175,20 @@ void label(screen_projection const &Projection, glm::dvec3 const &Point, std::st
|
||||
drawlist->AddText(ImVec2(at.x + 12.f, at.y), IM_COL32(255, 255, 255, 235), Text.c_str());
|
||||
}
|
||||
|
||||
// the first line of the file of the turntable controls, which tells it from the files of the scenery made by hand
|
||||
char const *const kControlsHeader{"// made by the scenery editor on each save: T turns each turntable to its next position, Shift+T to the previous one"};
|
||||
|
||||
// true if the file is one of the turntable controls the editor writes
|
||||
bool controls_file(std::string const &Path)
|
||||
{
|
||||
std::ifstream input{Path, std::ios_base::binary};
|
||||
std::string first;
|
||||
std::getline(input, first);
|
||||
if (false == first.empty() && first.back() == '\r')
|
||||
first.pop_back();
|
||||
return first == kControlsHeader;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool editor_mode::scan_turntables(bool const Wait)
|
||||
@@ -1215,7 +1230,7 @@ bool editor_mode::turntable_controls(std::vector<std::string> &Rootstatements)
|
||||
auto const exists{std::filesystem::exists(path, error)};
|
||||
if (tables == 0 && false == exists)
|
||||
return false;
|
||||
auto const content{"// made by the scenery editor on each save: T turns each turntable to its next position, Shift+T to the previous one\r\n" + text.str()};
|
||||
auto const content{std::string{kControlsHeader} + "\r\n" + text.str()};
|
||||
std::string current;
|
||||
{
|
||||
std::ifstream input{path, std::ios_base::binary};
|
||||
@@ -1226,6 +1241,21 @@ bool editor_mode::turntable_controls(std::vector<std::string> &Rootstatements)
|
||||
std::ofstream output{path, std::ios_base::binary | std::ios_base::trunc};
|
||||
output << content;
|
||||
}
|
||||
// the controls written for this scenery under another name, the file it was copied from, give way to these: with both
|
||||
// included each turntable would have its events twice. their files stay on the disk, for the scenery they were made for
|
||||
for (std::size_t handle = 1; handle <= scene::Layers.size(); ++handle)
|
||||
{
|
||||
auto const layer{static_cast<scene::layer_handle>(handle)};
|
||||
if (false == scene::Layers.listed(layer) || scene::Layers.layer(layer).removed)
|
||||
continue;
|
||||
auto name{scene::Layers.layer(layer).name};
|
||||
std::replace(name.begin(), name.end(), '\\', '/');
|
||||
auto const lower{ToLower(name)};
|
||||
if (lower == ToLower(file) || lower.ends_with("/" + ToLower(file)) || false == lower.ends_with("_obrotnice.scm"))
|
||||
continue;
|
||||
if (controls_file(Global.asCurrentSceneryPath + scene::Layers.layer(layer).name) && scene::Layers.remove(layer))
|
||||
WriteLog("Editor: " + name + " left out of the scenery, the turntable controls are in " + file + " now");
|
||||
}
|
||||
auto included{m_turntable_included};
|
||||
for (std::size_t handle = 1; handle <= scene::Layers.size() && false == included; ++handle)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "utilities/translation.h"
|
||||
#include "audio/audiorenderer.h"
|
||||
|
||||
#include <format>
|
||||
|
||||
scenarioloader_mode::scenarioloader_mode() {
|
||||
m_userinterface = std::make_shared<scenarioloader_ui>();
|
||||
}
|
||||
@@ -52,8 +54,9 @@ bool scenarioloader_mode::update() {
|
||||
try {
|
||||
state = simulation::State.deserialize_begin(Global.SceneryFile);
|
||||
}
|
||||
catch (std::exception const &e) {
|
||||
ErrorLog("Bad init: scenario \"" + Global.SceneryFile + "\" couldn't be opened (" + e.what() + ")");
|
||||
// the file it can't read, as the parser and the scenery opening it report it
|
||||
catch (std::runtime_error const &e) {
|
||||
ErrorLog(std::format("Bad init: scenario \"{}\" couldn't be opened ({})", Global.SceneryFile, e.what()));
|
||||
state.reset();
|
||||
Global.SceneryFile.clear();
|
||||
Application.pop_mode();
|
||||
@@ -67,8 +70,13 @@ bool scenarioloader_mode::update() {
|
||||
return true;
|
||||
}
|
||||
catch (invalid_scenery_exception &e) {
|
||||
// back to the launcher as when the scenario can't be opened, not on to the driver mode with the scenery half loaded
|
||||
ErrorLog( "Bad init: scenario loading failed" );
|
||||
state.reset();
|
||||
Global.SceneryFile.clear();
|
||||
Application.pop_mode();
|
||||
Application.push_mode(eu07_application::mode::launcher);
|
||||
return true;
|
||||
}
|
||||
// the loading state holds the scenario file open, which on some systems keeps the file from being replaced
|
||||
// when the scenery is saved in the editor. it'd also get in the way of another load
|
||||
|
||||
@@ -407,14 +407,21 @@ bool ui_layer::init(GLFWwindow *Window)
|
||||
}
|
||||
|
||||
// panels can be docked together, and dragged out of the simulator window into windows of their own (e.g. on another monitor)
|
||||
// when both backends can do it. glfw can't place windows under wayland. both flags have to be set before the first frame
|
||||
// when both backends can do it. glfw can't place windows under wayland. gamescope does not work well with popup windows.
|
||||
// both flags have to be set before the first frame
|
||||
m_imguiio->ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
const char* desktop = std::getenv("XDG_CURRENT_DESKTOP");
|
||||
const char* gamepadui = std::getenv("SteamGamepadUI");
|
||||
if (!desktop) desktop = "";
|
||||
if (!gamepadui) gamepadui = "";
|
||||
auto const viewportsupport{(m_imguiio->BackendFlags & ImGuiBackendFlags_PlatformHasViewports) && (m_imguiio->BackendFlags & ImGuiBackendFlags_RendererHasViewports) &&
|
||||
glfwGetPlatform() != GLFW_PLATFORM_WAYLAND};
|
||||
glfwGetPlatform() != GLFW_PLATFORM_WAYLAND && std::string_view{desktop} != "gamescope" && std::string_view{gamepadui} != "1"};
|
||||
if (Global.ui_viewports && viewportsupport)
|
||||
{
|
||||
m_imguiio->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
m_imguiio->ConfigViewportsNoTaskBarIcon = true;
|
||||
// only dragging a panel with the cursor past the main window takes it out, not resizing it or placing it at the edge
|
||||
m_imguiio->ConfigViewportsNoAutoDetach = true;
|
||||
auto &platformio{ImGui::GetPlatformIO()};
|
||||
imgui_create_window = platformio.Platform_CreateWindow;
|
||||
platformio.Platform_CreateWindow = create_viewport_window;
|
||||
|
||||
Reference in New Issue
Block a user