17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-21 01:36:02 +02:00
Files
maszyna/editor/editorSettings.cpp
maj00r d1dbd40566 feat(editor): the top view of the tracks draws the terrain to the corners of the screen, the ballast optional
- In the top view of the tracks work area, the renderer's reach is the half diagonal of the screen. It used to be three extents, which cut wide windows short.
- Cells far from the camera no longer draw only their tracks: the terrain shapes are drawn too. Models keep their own ranges.
- In that view, the heightmap streamer loads chunks as far as the corners, up to 50 km. The detail comes from the size of a pixel, not from the distance.
- The walk over the chunks around the camera is skipped while it would ask for nothing, so a wide reach costs little.
- A setting, kept in the editor settings, leaves out the ballast of the railway in the top view, so the ground under the tracks shows. It is in the View menu and next to the extent slider.
- Self-test: ortho <extent> [noballast|ballast], orthophoto off.
2026-10-19 17:10:27 +02:00

180 lines
5.4 KiB
C++

/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "editor/editorSettings.hpp"
#include "utilities/Logs.h"
#include "utilities/utilities.h"
#include <cctype>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <locale>
#include <sstream>
editorSettings EditorSettings;
namespace
{
namespace fs = std::filesystem;
fs::path settings_path()
{
fs::path p = user_config_path("eu07_editor.ini");
return p.empty() ? fs::path("eu07_editor.ini") : p;
}
const char *scheme_to_string(editorSettings::movement_scheme scheme)
{
return scheme == editorSettings::movement_scheme::legacy ? "legacy" : "wsad";
}
// numbers are stored locale-independent
template <typename Type_> void parse(std::string const &Text, Type_ &Out)
{
std::istringstream stream(Text);
stream.imbue(std::locale::classic());
Type_ value;
if (stream >> value)
Out = value;
}
const std::string origin_prefix{"ortho_origin@"};
// settings are whitespace separated key/value pairs, so the scenery name used in the key can't contain spaces
std::string origin_key(std::string const &Scenery)
{
std::string key = origin_prefix + Scenery;
for (char &c : key)
if (std::isspace(static_cast<unsigned char>(c)))
c = '_';
return key;
}
}
bool editorSettings::load()
{
const fs::path path = settings_path();
std::error_code ec;
if (!fs::exists(path, ec))
return false;
std::ifstream stream(path);
if (!stream.is_open())
return false;
std::string key, value;
while (stream >> key >> value)
{
if (key == "movement_scheme")
m_movement = (value == "legacy") ? movement_scheme::legacy : movement_scheme::wsad;
else if (key == "ortho_radius")
parse(value, m_orthophoto.radius);
else if (key == "ortho_height")
parse(value, m_orthophoto.height);
else if (key == "ortho_opacity")
parse(value, m_orthophoto.opacity);
else if (key == "ortho_year")
parse(value, m_orthophoto.year);
else if (key == "ortho_4k")
m_orthophoto.hires = (value == "1");
else if (key == "ortho_drape")
m_orthophoto.drape = (value == "1");
else if (key == "ortho_lift")
parse(value, m_orthophoto.lift);
else if (key == "ortho_in_scene")
m_orthophoto.in_scene = (value == "1");
else if (key == "platform_edge")
parse(value, m_platform_edge);
else if (key == "signal_offset")
parse(value, m_signal_offset);
else if (key == "nodebank_previews")
m_nodebank_previews = (value == "1");
else if (key == "nodebank_card")
parse(value, m_nodebank_card);
else if (key == "colours")
parse(value, m_palette);
else if (key == "first_steps")
m_first_steps = (value == "1");
else if (key == "terrain_offer")
m_terrain_offer = (value == "1");
else if (key == "track_tools_all")
m_track_tools_more = (value == "1");
else if (key == "top_ballast")
m_top_ballast = (value == "1");
else if (key.rfind(origin_prefix, 0) == 0)
{
// northing;easting
auto const separator = value.find(';');
if (separator == std::string::npos)
continue;
double north{0.0}, east{0.0};
parse(value.substr(0, separator), north);
parse(value.substr(separator + 1), east);
m_orthophoto_origins[key] = {north, east};
}
}
return true;
}
bool editorSettings::save()
{
const fs::path path = settings_path();
std::error_code ec;
fs::create_directories(path.parent_path(), ec);
std::ofstream stream(path, std::ios::trunc);
if (!stream.is_open())
{
ErrorLog("failed to save editor settings");
return false;
}
stream.imbue(std::locale::classic());
stream << "movement_scheme " << scheme_to_string(m_movement) << "\n";
stream << "ortho_radius " << m_orthophoto.radius << "\n";
stream << "ortho_height " << m_orthophoto.height << "\n";
stream << "ortho_opacity " << m_orthophoto.opacity << "\n";
stream << "ortho_year " << m_orthophoto.year << "\n";
stream << "ortho_4k " << (m_orthophoto.hires ? 1 : 0) << "\n";
stream << "ortho_drape " << (m_orthophoto.drape ? 1 : 0) << "\n";
stream << "ortho_lift " << m_orthophoto.lift << "\n";
stream << "ortho_in_scene " << (m_orthophoto.in_scene ? 1 : 0) << "\n";
stream << "platform_edge " << m_platform_edge << "\n";
stream << "signal_offset " << m_signal_offset << "\n";
stream << "nodebank_previews " << (m_nodebank_previews ? 1 : 0) << "\n";
stream << "nodebank_card " << m_nodebank_card << "\n";
stream << "colours " << m_palette << "\n";
stream << "first_steps " << (m_first_steps ? 1 : 0) << "\n";
stream << "terrain_offer " << (m_terrain_offer ? 1 : 0) << "\n";
stream << "track_tools_all " << (m_track_tools_more ? 1 : 0) << "\n";
stream << "top_ballast " << (m_top_ballast ? 1 : 0) << "\n";
stream << std::fixed << std::setprecision(3);
for (auto const &origin : m_orthophoto_origins)
stream << origin.first << " " << origin.second.first << ";" << origin.second.second << "\n";
return true;
}
bool editorSettings::orthophoto_origin(std::string const &Scenery, double &North, double &East) const
{
auto const lookup = m_orthophoto_origins.find(origin_key(Scenery));
if (lookup == m_orthophoto_origins.end())
return false;
North = lookup->second.first;
East = lookup->second.second;
return true;
}
void editorSettings::orthophoto_origin(std::string const &Scenery, double North, double East)
{
m_orthophoto_origins[origin_key(Scenery)] = {North, East};
}