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:
@@ -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");
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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]{};
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user