17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-26 04:29:29 +01:00

feat(editor): Straight and Curve are one Plan tool (G, also C) right after Lay track, a straight opens with its grips, a curve or a line with its vertices; digits no longer type a length while extending from a free end; the scenery wizard chooses realistic or fictional, a realistic one gets //$g and //$o and opens with the orthophoto in the top view, a fictional one only the top view with the grid; the orthophoto settings are kept in the scenery as //$o (on, year, opacity, radius, height, drape, lift, hires, scene, origin) and survive the new formats; self-test command mapstate

This commit is contained in:
maj00r
2026-10-12 02:21:29 +02:00
parent 653d206a54
commit 16c90eb674
12 changed files with 209 additions and 85 deletions

View File

@@ -2197,6 +2197,14 @@ void editor_mode::load_orthophoto_settings()
config.north = m_georeference_origin.x;
config.east = m_georeference_origin.y;
}
auto enabled{m_orthophoto.enabled()};
m_orthophoto_mark.clear();
if (auto const marked{scene::Layers.empty() ? std::vector<std::string>{} : scene::Layers.marked(scene::layer_handle{1}, "//$o")}; false == marked.empty() && editor_orthophoto::read_mark(marked.front(), config, enabled))
{
m_orthophoto_mark = marked.front();
m_orthophoto.enabled(enabled);
WriteLog(format("Editor: the map settings of the scenery, orthophoto %s", enabled ? "on" : "off"));
}
m_orthophoto.settings(config);
m_orthophoto_origin_edit = {config.north, config.east};
}
@@ -2934,6 +2942,11 @@ bool editor_mode::save()
m_saved_camera = std::make_pair(glm::dvec3{Camera.Pos}, glm::vec3{Camera.Angle});
scene::Layers.mark(scene::layer_handle{1}, "//$c", {format("%.3f %.3f %.3f %.5f %.5f", Camera.Pos.x, Camera.Pos.y, Camera.Pos.z, Camera.Angle.x, Camera.Angle.y)});
}
if (auto const map{editor_orthophoto::mark(m_orthophoto.settings(), m_orthophoto.enabled(), m_orthophoto.settings().north != 0.0 || m_orthophoto.settings().east != 0.0)}; false == m_orthophoto_scenery.empty() && map != m_orthophoto_mark && (m_orthophoto.enabled() || false == m_orthophoto_mark.empty()))
{
m_orthophoto_mark = map;
scene::Layers.mark(scene::layer_handle{1}, "//$o", {map});
}
auto const terrainadded{false == rootstatements.empty()};
auto const controls{turntable_controls(rootstatements)};
std::vector<std::string> trailing;
@@ -4707,7 +4720,7 @@ void editor_mode::render_shortcuts_window()
{"Tracks",
{{"Esc", "Select tool; cancels what's going on first"},
{"L / T / U", "Lay track / switch / turntable"},
{"G / C", "Straight / curve"},
{"G (C)", "Plan: a straight, its ends and the middle; a curve, its vertex and radius"},
{"H / B", "Signals / objects along the track"},
{"P / V / J / I", "Profile / speed / joints / infrastructure"},
{"Ctrl+F", "Find a track by its name"},
@@ -5236,10 +5249,15 @@ void editor_mode::enter()
{
std::vector<char> found;
auto const ground{ground_heights({glm::dvec3{0.0, 5000.0, 0.0}}, true, &found).front()};
Camera.Pos = glm::dvec3{0.0, (found.front() != 0 ? ground : 0.0) + 60.0, 60.0};
Camera.Pos = glm::dvec3{0.0, (found.front() != 0 ? ground : 0.0) + 60.0, 0.0};
Camera.Angle = glm::vec3(glm::radians(-45.0f), 0.0f, 0.0f);
Camera.m_owner = nullptr;
FreeFlyModeFlag = true;
if (false == Global.EditorOrtho)
{
Global.EditorOrthoExtent = 150.0f;
toggle_ortho();
}
Global.pCamera = Camera;
choose_work_area(work_area::tracks);
WriteLog("Editor: camera over the origin of the empty scenery");

View File

@@ -521,6 +521,7 @@ class editor_mode : public application_mode, private editor_track::observer
void save_orthophoto_settings();
editor_orthophoto m_orthophoto;
std::string m_orthophoto_scenery; // scenery whose origin is loaded
std::string m_orthophoto_mark;
glm::dvec2 m_orthophoto_origin_edit{0.0}; // origin being typed in (northing, easting); applied when editing ends
// hierarchy management
@@ -1206,7 +1207,9 @@ class editor_mode : public application_mode, private editor_track::observer
track_tab tab;
char const *tooltip;
};
static std::array<track_mode, 13> const &track_modes();
static std::array<track_mode, 12> const &track_modes();
bool track_plan_tab() const { return m_track_tab == track_tab::straights || m_track_tab == track_tab::route; }
track_tab plan_tab_for(TTrack const *Track) const;
// the objects along the track: a tab for each tool
int m_lineside_tab{0};
void render_lineside_ui();
@@ -1217,7 +1220,7 @@ class editor_mode : public application_mode, private editor_track::observer
// the track tools in the tool options window, and the selected path in the inspector
void render_track_tool_options();
void render_track_selection();
void show_track_tab(track_tab const Tab);
void show_track_tab(track_tab const Wanted);
bool track_analysis_tab() const { return m_track_tab == track_tab::profile || m_track_tab == track_tab::speed || m_track_tab == track_tab::joints || m_track_tab == track_tab::infra; }
bool track_shortcut(int const Key);
bool track_busy() const; // something going on in the mode, which Esc drops before it leaves the mode
@@ -1878,7 +1881,6 @@ class editor_mode : public application_mode, private editor_track::observer
char const *typed_meaning() const;
std::vector<double> typed_values() const;
bool typed_key(int const Key);
void typed_extend();
glm::dvec3 typed_lay(glm::dvec3 const &Mouse) const;
void typed_turn();
bool m_route_tab{true};

View File

@@ -149,6 +149,12 @@ editor_mode::selftest_result editor_mode::selftest_scene(std::string const &comm
save();
return selftest_result::handled;
}
if (command == "mapstate")
{
auto const marked{scene::Layers.empty() ? std::vector<std::string>{} : scene::Layers.marked(scene::layer_handle{1}, "//$o")};
WriteLog(format("SELFTEST mapstate orthophoto %d top %d extent %.0f mark %s", m_orthophoto.enabled() ? 1 : 0, Global.EditorOrtho ? 1 : 0, Global.EditorOrthoExtent, marked.empty() ? "-" : marked.front().c_str()));
return selftest_result::handled;
}
if (command == "trainset")
{
std::string name;
@@ -2426,6 +2432,7 @@ editor_mode::selftest_result editor_mode::selftest_terrain(std::string const &co
// checkspans logs whether the text the scenery files hold at each node's place starts and ends it
// spread <track> <stop 0..2> <reach> logs the paths the spread from the track takes
// newscenery the editor starts again with the wizard of a new scenery
// mapstate logs the orthophoto, the top view and the //$o line of the scenery
// trainset <track> <vehicle path> <skin> <facing> [km/h] the trainset tool puts the vehicle in the middle of the track
// vehicles logs each vehicle: its head, facing, and what its couplers hold
// terrainmode the terrain field of work, with its texture browser

View File

@@ -259,12 +259,17 @@ void editor_mode::select_track(scene::basic_node *Node)
return;
m_track_window_open = true;
m_track_mode_notice.clear();
if (track_plan_tab() && plan_tab_for(track) != m_track_tab)
{
show_track_tab(plan_tab_for(track));
return;
}
// the mode stays as it is, the path is taken up by it if it can be
switch (m_track_tab)
{
case track_tab::straights:
if (track->eType == tt_Switch || false == editor_track::is_straight(*track, m_straights.tolerance))
m_track_mode_notice = STR_C("The selected path isn't straight: C edits it as a curve, Esc goes back to Select");
if (track->eType == tt_Switch)
m_track_mode_notice = STR_C("Switches aren't a part of a line: T edits the switch, Esc goes back to Select");
break;
case track_tab::route:
if (std::find(m_route.chain.tracks.begin(), m_route.chain.tracks.end(), track) != m_route.chain.tracks.end())
@@ -522,16 +527,15 @@ void editor_mode::restore_track_snapshot(EditorSnapshot const &Snapshot, std::ve
profile_restore();
}
std::array<editor_mode::track_mode, 13> const &editor_mode::track_modes()
std::array<editor_mode::track_mode, 12> const &editor_mode::track_modes()
{
static std::array<track_mode, 13> const modes{{
static std::array<track_mode, 12> const modes{{
{"Select", "Esc", track_tab::path, "LMB on a path selects it: its points, control vectors and parameters"},
{"Lay track", "L", track_tab::lay, "Lays new track through the clicked points, on the ground or from a free end of a track"},
{"Plan", "G", track_tab::straights, "The plan of the line laid: LMB on a straight drags its ends or the middle, on a curve its vertex and radius. C works too"},
{"Switch", "T", track_tab::turnout, "Puts switches into the selected straight or curve, edits the geometry of the selected switch"},
{"Parallel", "N", track_tab::parallel, "A second track beside a straight: LMB on the straight, then the side and the spacing"},
{"Turntable", "U", track_tab::turntable, "Places a turntable, leads tracks out of it and fits the tracks around to it"},
{"Straight", "G", track_tab::straights, "The whole straight through the selected path: drag its ends or the middle, break it, shift it"},
{"Curve", "C", track_tab::route, "The line through the path, switch to switch: vertices with the radii, transitions and cant of the curves"},
{"Signals", "H", track_tab::signals, "Signals by the track, from the templates of the scenery, with the event the train reads them by"},
{"Objects", "B", track_tab::lineside, "Along the track: hectometre posts, fouling point markers, trainsets"},
{"Profile", "P", track_tab::profile, "Vertical profile (grade line) along the line"},
@@ -542,8 +546,9 @@ std::array<editor_mode::track_mode, 13> const &editor_mode::track_modes()
return modes;
}
void editor_mode::show_track_tab(track_tab const Tab)
void editor_mode::show_track_tab(track_tab const Wanted)
{
auto const Tab{Wanted == track_tab::straights || Wanted == track_tab::route ? plan_tab_for(selected_track()) : Wanted};
m_track_window_open = true;
m_roadtool.window = false;
if (Tab == m_track_tab)
@@ -567,8 +572,8 @@ void editor_mode::show_track_tab(track_tab const Tab)
arm_switch();
break;
case track_tab::straights:
if (track != nullptr && (track->eType == tt_Switch || false == editor_track::is_straight(*track, m_straights.tolerance)))
m_track_mode_notice = STR_C("The selected path isn't straight: LMB on a straight");
if (track != nullptr && track->eType == tt_Switch)
m_track_mode_notice = STR_C("Switches aren't a part of a line: LMB on a plain path");
break;
case track_tab::route:
if (track != nullptr && std::find(m_route.chain.tracks.begin(), m_route.chain.tracks.end(), track) == m_route.chain.tracks.end())
@@ -615,17 +620,28 @@ void editor_mode::arm_switch()
bool editor_mode::track_shortcut(int const Key)
{
auto const key{Key == GLFW_KEY_C ? GLFW_KEY_G : Key};
for (auto const &mode : track_modes())
{
if (mode.key[1] != '\0' || Key != GLFW_KEY_A + (mode.key[0] - 'A'))
if (mode.key[1] != '\0' || key != GLFW_KEY_A + (mode.key[0] - 'A'))
continue;
// the key of the mode on leaves it
show_track_tab(m_track_window_open && m_track_tab == mode.tab ? track_tab::path : mode.tab);
auto const on{m_track_tab == mode.tab || (mode.tab == track_tab::straights && track_plan_tab())};
show_track_tab(m_track_window_open && on ? track_tab::path : mode.tab);
return true;
}
return false;
}
editor_mode::track_tab editor_mode::plan_tab_for(TTrack const *Track) const
{
if (Track == nullptr)
return track_plan_tab() ? m_track_tab : track_tab::straights;
if (Track->eType == tt_Normal && editor_track::is_supported(*Track) && false == editor_track::is_straight(*Track, m_straights.tolerance))
return track_tab::route;
return track_tab::straights;
}
bool editor_mode::track_busy() const
{
auto const &straights{m_straights};
@@ -647,13 +663,13 @@ std::string editor_mode::track_mode_name() const
return STR_C("Switch: press and drag on the selected track");
case track_tab::straights:
if (false == m_straights.detour.empty())
return STR_C("Straight: shift around, Shift+click the points");
return STR_C("Plan, straight: shift around, Shift+click the points");
if (m_straights.tool == 1)
return STR_C("Straight: break, LMB on the straight");
return STR_C("Plan, straight: break, LMB on the straight");
if (m_straights.tool == 2)
return STR_C("Straight: S-curve, LMB on the straight");
return STR_C("Straight: drag its ends or the middle");
case track_tab::route: return STR_C("Curve: drag the vertices and the radius grips");
return STR_C("Plan, straight: S-curve, LMB on the straight");
return STR_C("Plan, straight: drag its ends or the middle");
case track_tab::route: return STR_C("Plan, curve: drag the vertices and the radius grips");
case track_tab::profile: return STR_C("Vertical profile: edit the grade line in the profile window");
case track_tab::speed: return STR_C("Speed check: LMB on a row shows the path");
case track_tab::joints: return STR_C("Joints: LMB on a row shows the place");
@@ -3735,14 +3751,14 @@ std::vector<editor_mode::key_hint> editor_mode::track_key_hints(bool const All)
hints = {{"Drag the diamond", "snaps parallel at 4.00 / 4.50 / 4.75 m"}, {"Esc", "cancel"}};
}
else if (m_track_tab == track_tab::straights && m_straights.current.tracks.empty())
hints = {{"LMB on a straight track", "selects the whole straight"}};
hints = {{"LMB on a straight", "its ends and the middle to drag"}, {"LMB on a curve", "its vertex and radius to drag"}};
else if (m_track_tab == track_tab::straights)
{
hints = {{"Drag a square", "moves an end, the curves at it follow"}, {"Drag the diamond", "shifts sideways; close: snaps parallel at 4.00 / 4.50 / 4.75 m"}, {"Ctrl+drag", "breaks the straight"}, {"Shift+click x4", "shifts a piece around an obstacle"}, {"Alt+click", "adds another straight to move together"}};
gizmo = true;
}
else if (m_track_tab == track_tab::route && m_route.chain.tracks.empty())
hints = {{"LMB on a curve", "loads it with the straights at its ends"}};
hints = {{"LMB on a straight", "its ends and the middle to drag"}, {"LMB on a curve", "its vertex and radius to drag"}};
else if (m_track_tab == track_tab::route)
hints = {{"Drag yellow", "moves a vertex, the curve follows"}, {"Drag green", "changes the radius"}, {"Apply", "writes the design into the tracks"}, {"Esc", "release the vertex"}};
else if (selected == nullptr)
@@ -4070,8 +4086,7 @@ void editor_mode::update_build_tools()
{
if (pointing)
m_extend.mouse = cursor_terrain(m_extend.point.y);
typed_extend();
m_extend.snap = m_typed.empty() && m_extend.track != nullptr ? snap_free_end(m_extend.mouse, cursor, m_extend.track, m_extend.track->iCategoryFlag & 15, {m_extend.track}) : editor_track::snap_target{};
m_extend.snap = m_extend.track != nullptr ? snap_free_end(m_extend.mouse, cursor, m_extend.track, m_extend.track->iCategoryFlag & 15, {m_extend.track}) : editor_track::snap_target{};
if (m_extend.snap.track == nullptr)
m_extend.mouse.y = bed_height(m_extend.mouse, plan_of(m_extend.mouse - m_extend.point), m_extend.track);
joining(m_extend.snap);
@@ -4504,7 +4519,7 @@ std::vector<segment_data> editor_mode::join_pieces(TTrack const *From, editor_tr
void editor_mode::finish_extend()
{
auto const &io{ImGui::GetIO()};
if (glm::length(glm::vec2{io.MousePos.x, io.MousePos.y} - m_extend.pressed) < kDragPixels && m_typed.empty())
if (glm::length(glm::vec2{io.MousePos.x, io.MousePos.y} - m_extend.pressed) < kDragPixels)
{
m_extend.active = false;
if (m_lay.active && m_lay.points.empty() && m_extend.origin.track != nullptr)

View File

@@ -376,8 +376,8 @@ editor_mode::track_intent editor_mode::track_intent_at(int const Mods)
intent.position = m_hover.point;
switch (m_track_tab)
{
case track_tab::straights: return make(kind::select, "Click: the whole straight through this track");
case track_tab::route: return make(kind::select, "Click: the curve of this track with its straights");
case track_tab::straights:
case track_tab::route: return make(kind::select, m_hover.track->eType != tt_Switch && editor_track::is_straight(*m_hover.track, m_straights.tolerance) ? "Click: the whole straight through this track" : "Click: the curve of this track with its straights");
case track_tab::turnout: return make(kind::select, m_hover.track->eType == tt_Switch ? "Click: edit this switch" : m_switch.armed < 0 ? "Click: choose this track, then the type of the switch" : "Click: choose this track, then press and drag on it for the switch");
case track_tab::profile: return make(kind::select, "Click: the grade line through this track");
case track_tab::lineside: return make(kind::select, "Click: the line the objects go along");
@@ -649,10 +649,8 @@ void editor_mode::render_track_context()
ImGui::Separator();
if (ImGui::MenuItem(STR_C("Switch"), "T", false, normal || track->eType == tt_Switch))
show_track_tab(track_tab::turnout);
if (ImGui::MenuItem(STR_C("Whole straight"), "G", false, normal && editor_track::is_straight(*track, m_straights.tolerance)))
if (ImGui::MenuItem(STR_C("Plan"), "G", false, normal))
show_track_tab(track_tab::straights);
if (ImGui::MenuItem(STR_C("Curve"), "C", false, normal))
show_track_tab(track_tab::route);
if (ImGui::MenuItem(STR_C("Parallel track"), "L", false, normal))
show_track_tab(track_tab::lay);
if (ImGui::MenuItem(STR_C("Place a vehicle here")))
@@ -758,8 +756,6 @@ void editor_mode::render_track_search()
char const *editor_mode::typed_meaning() const
{
auto const &straights{m_straights};
if (m_extend.active)
return m_track_layout == track_layout::straight ? "type the length" : m_track_layout == track_layout::arc ? "type the radius, a space, the length" : "type the radius";
if (straights.dragging)
return straights.handle == 2 ? "type the shift, + to the right" : "type the length";
if (straights.tool == 1 && (straights.tool_mouse || straights.tool_dragging))
@@ -821,37 +817,6 @@ bool editor_mode::typed_key(int const Key)
return true;
}
void editor_mode::typed_extend()
{
auto const values{typed_values()};
if (values.empty())
return;
auto &tool{m_extend};
auto const &direction{tool.direction};
if (m_track_layout != track_layout::straight && m_track_layout != track_layout::arc)
return;
if (m_track_layout == track_layout::straight)
{
auto const length{std::max(0.0, values[0])};
tool.mouse = {tool.point.x + direction.x * length, tool.mouse.y, tool.point.z + direction.y * length};
return;
}
auto const radius{std::abs(values[0])};
if (radius < 1.0)
return;
glm::dvec2 const offset{tool.mouse.x - tool.point.x, tool.mouse.z - tool.point.z};
double const side{geometry::cross(direction, offset) >= 0.0 ? 1.0 : -1.0};
glm::dvec2 const point{tool.point.x, tool.point.z};
glm::dvec2 const centre{point + glm::dvec2{-direction.y, direction.x} * (side * radius)};
auto const radial{point - centre};
auto angle{values.size() > 1 ? std::abs(values[1]) / radius : side * geometry::signed_angle(radial, glm::dvec2{tool.mouse.x, tool.mouse.z} - centre)};
if (angle < 0.0)
angle += 2.0 * glm::pi<double>();
angle = std::clamp(angle, 1e-3, glm::pi<double>());
auto const end{centre + geometry::turned(radial, side * angle)};
tool.mouse = {end.x, tool.mouse.y, end.y};
}
glm::dvec3 editor_mode::typed_lay(glm::dvec3 const &Mouse) const
{
auto const values{typed_values()};

View File

@@ -163,11 +163,12 @@ void editor_mode::work_area_tools(std::vector<tool_button> &Buttons)
if (found == modes.end())
return;
// a tool chosen again gives way to the select one
auto const chosen{m_track_tab == Tab && false == (Tab == track_tab::lineside && vehicle)};
auto const chosen{(m_track_tab == Tab || (Tab == track_tab::straights && track_plan_tab())) && false == (Tab == track_tab::lineside && vehicle)};
Buttons.push_back({Picture, STR_C(found->label), found->key, STR_C(found->tooltip), chosen, [this, Tab, chosen]() { show_track_tab(chosen ? track_tab::path : Tab); }, Group});
};
add(track_tab::path, icon::select, false);
add(track_tab::lay, icon::lay_track, false);
add(track_tab::straights, icon::curve, false);
add(track_tab::turnout, icon::turnout, false);
add(track_tab::parallel, icon::parallel, false);
add(track_tab::turntable, icon::turntable, false);
@@ -177,17 +178,15 @@ void editor_mode::work_area_tools(std::vector<tool_button> &Buttons)
show_track_tab(vehicle ? track_tab::path : track_tab::lineside);
m_vehicle.expand = false == vehicle;
}});
auto const advanced{m_track_tab == track_tab::straights || m_track_tab == track_tab::route || m_track_tab == track_tab::profile || m_track_tab == track_tab::speed || m_track_tab == track_tab::joints || m_track_tab == track_tab::infra || m_gauge.open};
auto const advanced{m_track_tab == track_tab::profile || m_track_tab == track_tab::speed || m_track_tab == track_tab::joints || m_track_tab == track_tab::infra || m_gauge.open};
auto const more{EditorSettings.track_tools_more()};
Buttons.push_back({icon::more, more ? STR_C("Less") : STR_C("More"), nullptr, STR_C("The tools that correct a line already laid: straight, curve, profile, speed, joints, infrastructure, structure gauge"), more, [more]() {
Buttons.push_back({icon::more, more ? STR_C("Less") : STR_C("More"), nullptr, STR_C("The checks of a line laid: profile, speed, joints, infrastructure, structure gauge"), more, [more]() {
EditorSettings.track_tools_more(false == more);
EditorSettings.save();
}, true});
if (false == more && false == advanced)
break;
add(track_tab::straights, icon::straight, true);
add(track_tab::route, icon::curve, false);
add(track_tab::profile, icon::profile, false);
add(track_tab::profile, icon::profile, true);
add(track_tab::speed, icon::speed, false);
add(track_tab::joints, icon::joints, false);
add(track_tab::infra, icon::infra, false);

View File

@@ -677,6 +677,57 @@ bool editor_orthophoto::owns(gfx::geometry_handle const &Geometry)
return Geometry.bank != 0 && std::find(scene_banks.begin(), scene_banks.end(), Geometry.bank) != scene_banks.end();
}
std::string editor_orthophoto::mark(config const &Config, bool const Enabled, bool const Origin)
{
char text[256];
std::snprintf(text, sizeof(text), "on %d year %d opacity %.2f radius %d height %.2f drape %d lift %.2f hires %d scene %d", Enabled ? 1 : 0, Config.year, Config.opacity, Config.radius, Config.height, Config.drape ? 1 : 0, Config.lift, Config.hires ? 1 : 0, Config.in_scene ? 1 : 0);
std::string result{text};
if (Origin)
{
std::snprintf(text, sizeof(text), " origin %.2f %.2f", Config.north, Config.east);
result += text;
}
return result;
}
bool editor_orthophoto::read_mark(std::string const &Text, config &Config, bool &Enabled)
{
std::istringstream words{Text};
std::string key;
auto found{false};
while (words >> key)
{
if (key == "on")
words >> Enabled;
else if (key == "year")
words >> Config.year;
else if (key == "opacity")
words >> Config.opacity;
else if (key == "radius")
words >> Config.radius;
else if (key == "height")
words >> Config.height;
else if (key == "drape")
words >> Config.drape;
else if (key == "lift")
words >> Config.lift;
else if (key == "hires")
words >> Config.hires;
else if (key == "scene")
words >> Config.in_scene;
else if (key == "origin")
words >> Config.north >> Config.east;
else
continue;
if (words.fail())
return found;
found = true;
}
Config.radius = std::clamp(Config.radius, 0, max_radius);
Config.opacity = std::clamp(Config.opacity, 0.0f, 1.0f);
return found;
}
void editor_orthophoto::enabled(bool State)
{
if (State == m_enabled)

View File

@@ -93,6 +93,8 @@ class editor_orthophoto
// disabling drops the queue and returns the gpu memory of the resident tiles
void enabled(bool State);
config const &settings() const { return m_config; }
static std::string mark(config const &Config, bool Enabled, bool Origin);
static bool read_mark(std::string const &Text, config &Config, bool &Enabled);
// changes of year / resolution invalidate resident tiles, the rest applies immediately
void settings(config const &Config);
void ground_source(ground_query Query) { m_ground = std::move(Query); }

View File

@@ -38,26 +38,26 @@ msgstr "Rozjazd: przeciągnij, aby ustawić kierunek i stronę"
msgid "Switch: press and drag on the selected track"
msgstr "Rozjazd: wciśnij i przeciągnij na wybranym torze"
msgid "Straight: shift around, Shift+click the points"
msgstr "Prosta: objazd, Shift+klik w punkty"
msgid "Plan, straight: shift around, Shift+click the points"
msgstr "Plan, prosta: objazd, Shift+klik w punkty"
msgid "New path from the free end"
msgstr "Nowy odcinek z wolnego końca"
msgid "Straight: break, LMB on the straight"
msgstr "Prosta: załamanie, LPM na prostej"
msgid "Plan, straight: break, LMB on the straight"
msgstr "Plan, prosta: załamanie, LPM na prostej"
msgid "Straight: S-curve, LMB on the straight"
msgstr "Prosta: przesunięcie (esowanie), LPM na prostej"
msgid "Plan, straight: S-curve, LMB on the straight"
msgstr "Plan, prosta: przesunięcie (esowanie), LPM na prostej"
msgid "Straight: drag its ends or the middle"
msgstr "Prosta: przeciągaj końce lub środek"
msgid "Plan, straight: drag its ends or the middle"
msgstr "Plan, prosta: przeciągaj końce lub środek"
msgid "Select: LMB on a path"
msgstr "Wybór: LPM na odcinku"
msgid "Curve: drag the vertices and the radius grips"
msgstr "Łuk: przeciągaj wierzchołki i uchwyty promienia"
msgid "Plan, curve: drag the vertices and the radius grips"
msgstr "Plan, łuk: przeciągaj wierzchołki i uchwyty promienia"
msgid "Switch: move and turn it with the gizmo"
msgstr "Rozjazd: przesuwaj i obracaj gizmem"
@@ -5727,3 +5727,36 @@ msgstr "Nie trafi do scenerii; pojazdy zostają do ponownego wczytania scenerii"
msgid "%d trainset(s) written to the scenery"
msgstr "Zapisano %d skład(ów) do scenerii"
msgid "Plan"
msgstr "Plan"
msgid "The plan of the line laid: LMB on a straight drags its ends or the middle, on a curve its vertex and radius. C works too"
msgstr "Plan ułożonej linii: LPM na prostej – ciągniesz jej końce lub środek, na łuku – wierzchołek i promień. Działa też C"
msgid "The checks of a line laid: profile, speed, joints, infrastructure, structure gauge"
msgstr "Kontrole ułożonej linii: profil, prędkość, styki, infrastruktura, skrajnia"
msgid "its ends and the middle to drag"
msgstr "jej końce i środek do ciągnięcia"
msgid "its vertex and radius to drag"
msgstr "jego wierzchołek i promień do ciągnięcia"
msgid "G (C)"
msgstr "G (C)"
msgid "Plan: a straight, its ends and the middle; a curve, its vertex and radius"
msgstr "Plan: prosta – jej końce i środek; łuk – wierzchołek i promień"
msgid "Realistic"
msgstr "Realistyczna"
msgid "A real place: the centre is picked on the map, the editor opens with the orthophoto under it, seen from above"
msgstr "Prawdziwe miejsce: środek wybierasz na mapie, edytor otwiera się z ortofotomapą pod spodem, w widoku z góry"
msgid "Fictional"
msgstr "Fikcyjna"
msgid "No place on the map, no orthophoto: an empty plane seen from above"
msgstr "Bez miejsca na mapie i bez ortofotomapy: pusta płaszczyzna w widoku z góry"

View File

@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
#include "application/application.h"
#include "editor/editorFormat.hpp"
#include "editor/editorOrthophoto.hpp"
#include "editor/editorSettings.hpp"
#include "utilities/Globals.h"
#include "utilities/Logs.h"
#include "utilities/translation.h"
@@ -270,7 +271,18 @@ void ui::scenerywizard_panel::render_form()
{
ImGui::TextUnformatted(STR_C("New scenery"));
ImGui::Separator();
ImGui::TextWrapped("%s", STR_C("Find the place on the map: the wheel zooms, dragging moves the map. A click sets the centre of the scenery, its point 0 0 0."));
if (ImGui::RadioButton(STR_C("Realistic"), m_realistic))
m_realistic = true;
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("A real place: the centre is picked on the map, the editor opens with the orthophoto under it, seen from above"));
ImGui::SameLine();
if (ImGui::RadioButton(STR_C("Fictional"), false == m_realistic))
m_realistic = false;
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", STR_C("No place on the map, no orthophoto: an empty plane seen from above"));
ImGui::Spacing();
if (m_realistic)
ImGui::TextWrapped("%s", STR_C("Find the place on the map: the wheel zooms, dragging moves the map. A click sets the centre of the scenery, its point 0 0 0."));
ImGui::Spacing();
ImGui::SetNextItemWidth(-1.f);
@@ -293,6 +305,7 @@ void ui::scenerywizard_panel::render_form()
ImGui::InputTextWithHint("##title", STR_C("title, written in the file"), m_title, sizeof(m_title));
ImGui::Spacing();
ImGui::BeginDisabled(false == m_realistic);
ImGui::TextUnformatted(STR_C("Centre of the scenery, PUWG 1992"));
double east{m_point.x / 1000.0};
double north{m_point.y / 1000.0};
@@ -335,11 +348,13 @@ void ui::scenerywizard_panel::render_form()
}
ImGui::Spacing();
ImGui::TextWrapped("%s", STR_C("The scenery keeps the centre as its geographic reference (//$g PUWG1992): the orthophoto of the editor lies under it, in place."));
ImGui::EndDisabled();
ImGui::Spacing();
auto const ready{named && false == exists && m_picked};
auto const placed{m_picked || false == m_realistic};
auto const ready{named && false == exists && placed};
if (false == ready)
ImGui::TextDisabled("%s", m_picked ? STR_C("Give the file a name") : STR_C("Click the centre on the map"));
ImGui::TextDisabled("%s", placed ? STR_C("Give the file a name") : STR_C("Click the centre on the map"));
if (ImGui::Button(STR_C("Create and open in the editor"), ImVec2(-1.f, 0.f)) && ready)
create_scenery();
if (false == m_status.empty())
@@ -366,7 +381,23 @@ bool ui::scenerywizard_panel::create_scenery()
std::strftime(date, sizeof(date), "%Y-%m-%d", std::localtime(&now));
char reference[96];
std::snprintf(reference, sizeof(reference), "//$g PUWG1992 %.3f %.3f", m_point.x / 1000.0, m_point.y / 1000.0);
output << reference << "\r\n";
if (m_realistic)
{
auto const &stored{EditorSettings.orthophoto()};
editor_orthophoto::config map;
map.radius = stored.radius;
map.height = stored.height;
map.opacity = stored.opacity;
map.year = stored.year;
map.hires = stored.hires;
map.drape = stored.drape;
map.lift = stored.lift;
map.in_scene = stored.in_scene;
output << reference << "\r\n";
output << "//$o " << editor_orthophoto::mark(map, true, false) << "\r\n";
}
else
std::snprintf(reference, sizeof(reference), "fictional");
if (m_title[0] != '\0')
output << "// " << m_title << "\r\n";
output << "// created in the editor " << date << "\r\n\r\n";

View File

@@ -60,6 +60,7 @@ class scenerywizard_panel : public ui_panel
std::string m_map_error;
bool m_picked{false};
bool m_realistic{true};
glm::dvec2 m_point{0.0};
char m_filename[64]{};
char m_title[128]{};

View File

@@ -837,7 +837,7 @@ bool node_layers::pending() const
namespace
{
// marks of the lines the editor keeps track of
std::array<char const *, 5> const editormarks{"//$p", "//$h", "//$r", "//$b", "//$c"};
std::array<char const *, 6> const editormarks{"//$p", "//$h", "//$r", "//$b", "//$c", "//$o"};
} // namespace
void node_layers::scan(layer_handle const Layer)