mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-05 20:39:09 +01:00
fix(editor): the drive of a switch follows the switch: moved, turned, its grade or cant changed with the gizmo or any other change of the switch, the include gets the new position, direction and rot.x/rot.z of the start of the switch, in the same undo step; self-test drives prints the parameters of the drive
This commit is contained in:
@@ -1407,6 +1407,9 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
std::vector<standing_template> standing_templates(std::function<bool(std::string const &)> const &Accept) const;
|
std::vector<standing_template> standing_templates(std::function<bool(std::string const &)> const &Accept) const;
|
||||||
bool find_switch_drive(TTrack const &Switch, standing_template &Drive, int &Family, int &Index);
|
bool find_switch_drive(TTrack const &Switch, standing_template &Drive, int &Family, int &Index);
|
||||||
bool replace_switch_drive(TTrack &Switch, int Family, bool Flip);
|
bool replace_switch_drive(TTrack &Switch, int Family, bool Flip);
|
||||||
|
bool switch_drive_spot(TTrack const &Switch, glm::dvec3 &Location, double &Yaw, glm::dvec2 &Tilt, bool &Rightswitch) const;
|
||||||
|
void switch_drive_captured(TTrack const &Track);
|
||||||
|
void switch_drives_committed(std::vector<TTrack *> const &Tracks);
|
||||||
// places them in the active layer, as one step of the undo. returns: how many were placed
|
// places them in the active layer, as one step of the undo. returns: how many were placed
|
||||||
std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error);
|
std::size_t place_templates(std::vector<template_item> const &Items, std::string &Error);
|
||||||
// moves them, as one step of the undo
|
// moves them, as one step of the undo
|
||||||
@@ -1940,6 +1943,7 @@ class editor_mode : public application_mode, private editor_track::observer
|
|||||||
std::vector<std::pair<scene::layer_handle, std::string>> m_bindings_unresolved; // lines kept as they are
|
std::vector<std::pair<scene::layer_handle, std::string>> m_bindings_unresolved; // lines kept as they are
|
||||||
bool m_bindings_loaded{false};
|
bool m_bindings_loaded{false};
|
||||||
std::vector<infra::object_state> m_infra_buffer; // states of the objects before the change in progress
|
std::vector<infra::object_state> m_infra_buffer; // states of the objects before the change in progress
|
||||||
|
std::vector<std::pair<scene::instance_handle, std::string>> m_drive_buffer;
|
||||||
bool m_infra_suspended{false};
|
bool m_infra_suspended{false};
|
||||||
void infra_load();
|
void infra_load();
|
||||||
void infra_store();
|
void infra_store();
|
||||||
|
|||||||
@@ -1128,6 +1128,7 @@ void editor_mode::infra_buffer(infra::binding const &Binding, bool const Refresh
|
|||||||
void editor_mode::track_captured(TTrack const &Track)
|
void editor_mode::track_captured(TTrack const &Track)
|
||||||
{
|
{
|
||||||
sweeps_captured(Track);
|
sweeps_captured(Track);
|
||||||
|
switch_drive_captured(Track);
|
||||||
if (m_infra_suspended || false == m_infra.follow)
|
if (m_infra_suspended || false == m_infra.follow)
|
||||||
return;
|
return;
|
||||||
infra_load();
|
infra_load();
|
||||||
@@ -1166,6 +1167,7 @@ void editor_mode::track_captured(TTrack const &Track)
|
|||||||
void editor_mode::tracks_committed(std::vector<TTrack *> const &Tracks)
|
void editor_mode::tracks_committed(std::vector<TTrack *> const &Tracks)
|
||||||
{
|
{
|
||||||
sweeps_committed(Tracks);
|
sweeps_committed(Tracks);
|
||||||
|
switch_drives_committed(Tracks);
|
||||||
if (m_infra_suspended || false == m_infra.follow)
|
if (m_infra_suspended || false == m_infra.follow)
|
||||||
return;
|
return;
|
||||||
infra_load();
|
infra_load();
|
||||||
|
|||||||
@@ -413,7 +413,11 @@ void editor_mode::selftest_step()
|
|||||||
std::string files;
|
std::string files;
|
||||||
for (auto const &standing : standing_templates([](std::string const &File) { return File.find("napedy/") != std::string::npos; }))
|
for (auto const &standing : standing_templates([](std::string const &File) { return File.find("napedy/") != std::string::npos; }))
|
||||||
if (false == standing.values.empty() && standing.values[0] == name)
|
if (false == standing.values.empty() && standing.values[0] == name)
|
||||||
|
{
|
||||||
files += " " + standing.file;
|
files += " " + standing.file;
|
||||||
|
for (std::size_t i = 1; i < standing.values.size(); ++i)
|
||||||
|
files += (i == 1 ? " (" : " ") + standing.values[i] + (i + 1 == standing.values.size() ? ")" : "");
|
||||||
|
}
|
||||||
for (scene::instance_handle handle = 1; handle <= scene::Layers.instance_count(); ++handle)
|
for (scene::instance_handle handle = 1; handle <= scene::Layers.instance_count(); ++handle)
|
||||||
if (scene::Layers.tracked(handle) && scene::Layers.instance(handle).file != nullptr && scene::Layers.instance(handle).file->find("napedy") != std::string::npos)
|
if (scene::Layers.tracked(handle) && scene::Layers.instance(handle).file != nullptr && scene::Layers.instance(handle).file->find("napedy") != std::string::npos)
|
||||||
files += format(" [%d %s removed %d dead %d]", static_cast<int>(handle), scene::Layers.instance(handle).file->c_str(), scene::Layers.instance(handle).removed ? 1 : 0, scene::Layers.instance(handle).dead ? 1 : 0);
|
files += format(" [%d %s removed %d dead %d]", static_cast<int>(handle), scene::Layers.instance(handle).file->c_str(), scene::Layers.instance(handle).removed ? 1 : 0, scene::Layers.instance(handle).dead ? 1 : 0);
|
||||||
|
|||||||
@@ -1239,6 +1239,8 @@ void editor_mode::push_track_snapshot(std::vector<std::pair<TTrack *, editor_tra
|
|||||||
infra_attach(snap);
|
infra_attach(snap);
|
||||||
snap.alignments = alignment_store::take_changes();
|
snap.alignments = alignment_store::take_changes();
|
||||||
snap.switch_records = switch_store::take_changes();
|
snap.switch_records = switch_store::take_changes();
|
||||||
|
snap.directives.insert(snap.directives.end(), m_drive_buffer.begin(), m_drive_buffer.end());
|
||||||
|
m_drive_buffer.clear();
|
||||||
m_history.push_back(std::move(snap));
|
m_history.push_back(std::move(snap));
|
||||||
g_redo.clear();
|
g_redo.clear();
|
||||||
}
|
}
|
||||||
@@ -1478,6 +1480,7 @@ void editor_mode::restore_track_snapshot(EditorSnapshot const &Snapshot, std::ve
|
|||||||
for (auto const &entry : Snapshot.infra)
|
for (auto const &entry : Snapshot.infra)
|
||||||
infra_restore_state(entry);
|
infra_restore_state(entry);
|
||||||
m_infra_buffer.clear();
|
m_infra_buffer.clear();
|
||||||
|
m_drive_buffer.clear();
|
||||||
m_infra_suspended = false;
|
m_infra_suspended = false;
|
||||||
if (false == m_route.chain.tracks.empty())
|
if (false == m_route.chain.tracks.empty())
|
||||||
{
|
{
|
||||||
@@ -6649,22 +6652,106 @@ std::string editor_mode::switch_name_for_new() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool editor_mode::switch_drive_spot(TTrack const &Switch, glm::dvec3 &Location, double &Yaw, glm::dvec2 &Tilt, bool &Rightswitch) const
|
||||||
|
{
|
||||||
|
if (Switch.eType != tt_Switch || Switch.m_paths.size() < 2)
|
||||||
|
return false;
|
||||||
|
auto const &main{Switch.m_paths[0]};
|
||||||
|
auto const &diverging{Switch.m_paths[1]};
|
||||||
|
auto const start{main.points[segment_data::point::start]};
|
||||||
|
auto const &control{main.points[segment_data::point::control1]};
|
||||||
|
auto const along{control != glm::dvec3{} ? control : main.points[segment_data::point::end] - start};
|
||||||
|
auto heading{plan_of(along)};
|
||||||
|
if (glm::length(heading) < 1e-9)
|
||||||
|
return false;
|
||||||
|
heading = glm::normalize(heading);
|
||||||
|
glm::dvec2 const right{-heading.y, heading.x};
|
||||||
|
Rightswitch = glm::dot(plan_of(diverging.points[segment_data::point::end] - start), right) > 0.0;
|
||||||
|
Location = start;
|
||||||
|
auto const yaw{glm::degrees(std::atan2(heading.x, heading.y))};
|
||||||
|
Yaw = yaw < 0.0 ? yaw + 360.0 : yaw;
|
||||||
|
auto const run{glm::length(plan_of(along))};
|
||||||
|
auto const roll{static_cast<double>(main.rolls[0])};
|
||||||
|
Tilt = {-glm::degrees(std::atan(along.y / run)), roll};
|
||||||
|
if (Global.bRollFix)
|
||||||
|
Location.y += 0.75 * std::abs(std::sin(glm::radians(roll)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void editor_mode::switch_drive_captured(TTrack const &Track)
|
||||||
|
{
|
||||||
|
if (Track.eType != tt_Switch || m_infra_suspended)
|
||||||
|
return;
|
||||||
|
standing_template drive;
|
||||||
|
int family{-1};
|
||||||
|
int variant{0};
|
||||||
|
if (false == find_switch_drive(Track, drive, family, variant))
|
||||||
|
return;
|
||||||
|
if (std::any_of(m_drive_buffer.begin(), m_drive_buffer.end(), [&](auto const &Entry) { return Entry.first == drive.instance; }))
|
||||||
|
return;
|
||||||
|
m_drive_buffer.emplace_back(drive.instance, scene::Layers.directive(drive.instance));
|
||||||
|
}
|
||||||
|
|
||||||
|
void editor_mode::switch_drives_committed(std::vector<TTrack *> const &Tracks)
|
||||||
|
{
|
||||||
|
if (m_infra_suspended)
|
||||||
|
return;
|
||||||
|
for (auto *track : Tracks)
|
||||||
|
{
|
||||||
|
if (track == nullptr || track->m_editorremoved || track->eType != tt_Switch)
|
||||||
|
continue;
|
||||||
|
standing_template drive;
|
||||||
|
int family{-1};
|
||||||
|
int variant{0};
|
||||||
|
glm::dvec3 location;
|
||||||
|
double yaw;
|
||||||
|
glm::dvec2 tilt;
|
||||||
|
bool rightswitch;
|
||||||
|
if (false == find_switch_drive(*track, drive, family, variant) || false == switch_drive_spot(*track, location, yaw, tilt, rightswitch))
|
||||||
|
continue;
|
||||||
|
auto const &included{scene::Layers.instance(drive.instance)};
|
||||||
|
include_info info;
|
||||||
|
std::string error;
|
||||||
|
if (included.file == nullptr || false == editor_includes::load(*included.file, info, error))
|
||||||
|
continue;
|
||||||
|
auto const local{location - included.context.offset};
|
||||||
|
auto values{drive.values};
|
||||||
|
for (auto const ¶meter : info.parameters)
|
||||||
|
{
|
||||||
|
if (parameter.id < 1 || parameter.id > static_cast<int>(values.size()))
|
||||||
|
continue;
|
||||||
|
auto &value{values[parameter.id - 1]};
|
||||||
|
if (parameter.role == "pos.x")
|
||||||
|
value = editor_includes::number(local.x);
|
||||||
|
else if (parameter.role == "pos.y")
|
||||||
|
value = editor_includes::number(local.y);
|
||||||
|
else if (parameter.role == "pos.z")
|
||||||
|
value = editor_includes::number(local.z);
|
||||||
|
else if (parameter.role == "rot.y")
|
||||||
|
value = editor_includes::number(yaw);
|
||||||
|
else if (parameter.role == "rot.x")
|
||||||
|
value = editor_includes::number(tilt.x);
|
||||||
|
else if (parameter.role == "rot.z")
|
||||||
|
value = editor_includes::number(tilt.y);
|
||||||
|
}
|
||||||
|
auto const directive{editor_includes::compose_directive(*included.file, values)};
|
||||||
|
if (directive != scene::Layers.directive(drive.instance))
|
||||||
|
set_include_directive(drive.instance, directive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool editor_mode::place_switch_drive(TTrack &Switch)
|
bool editor_mode::place_switch_drive(TTrack &Switch)
|
||||||
{
|
{
|
||||||
auto &tool{m_switch};
|
auto &tool{m_switch};
|
||||||
scan_switch_drives();
|
scan_switch_drives();
|
||||||
if (tool.drive < 0 || tool.drive >= static_cast<int>(tool.drives.size()) || Switch.eType != tt_Switch || Switch.m_paths.size() < 2)
|
if (tool.drive < 0 || tool.drive >= static_cast<int>(tool.drives.size()) || Switch.eType != tt_Switch || Switch.m_paths.size() < 2)
|
||||||
return false;
|
return false;
|
||||||
auto const &main{Switch.m_paths[0]};
|
glm::dvec3 location;
|
||||||
auto const &diverging{Switch.m_paths[1]};
|
double yaw;
|
||||||
auto const start{main.points[segment_data::point::start]};
|
glm::dvec2 tilt;
|
||||||
auto const &control{main.points[segment_data::point::control1]};
|
bool rightswitch;
|
||||||
auto heading{plan_of(control != glm::dvec3{} ? control : main.points[segment_data::point::end] - start)};
|
if (false == switch_drive_spot(Switch, location, yaw, tilt, rightswitch))
|
||||||
if (glm::length(heading) < 1e-9)
|
|
||||||
return false;
|
return false;
|
||||||
heading = glm::normalize(heading);
|
|
||||||
glm::dvec2 const right{-heading.y, heading.x};
|
|
||||||
bool const rightswitch{glm::dot(plan_of(diverging.points[segment_data::point::end] - start), right) > 0.0};
|
|
||||||
bool const driveright{(tool.drive_side == 0) == rightswitch};
|
bool const driveright{(tool.drive_side == 0) == rightswitch};
|
||||||
auto const &family{tool.drives[tool.drive]};
|
auto const &family{tool.drives[tool.drive]};
|
||||||
template_item item;
|
template_item item;
|
||||||
@@ -6674,19 +6761,11 @@ bool editor_mode::place_switch_drive(TTrack &Switch)
|
|||||||
tool.status = format(STR_C("The drive %s has no variant for a %s switch with the drive on the %s"), family.name.c_str(), rightswitch ? STR_C("right") : STR_C("left"), driveright ? STR_C("right") : STR_C("left"));
|
tool.status = format(STR_C("The drive %s has no variant for a %s switch with the drive on the %s"), family.name.c_str(), rightswitch ? STR_C("right") : STR_C("left"), driveright ? STR_C("right") : STR_C("left"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
item.location = start;
|
item.location = location;
|
||||||
auto yaw{glm::degrees(std::atan2(heading.x, heading.y))};
|
item.yaw = yaw;
|
||||||
item.yaw = yaw < 0.0 ? yaw + 360.0 : yaw;
|
|
||||||
item.described = true;
|
item.described = true;
|
||||||
item.track = Switch.name();
|
item.track = Switch.name();
|
||||||
{
|
item.tilt = tilt;
|
||||||
auto const along{control != glm::dvec3{} ? control : main.points[segment_data::point::end] - start};
|
|
||||||
auto const run{glm::length(plan_of(along))};
|
|
||||||
auto const roll{static_cast<double>(main.rolls[0])};
|
|
||||||
item.tilt = {run > 1e-9 ? -glm::degrees(std::atan(along.y / run)) : 0.0, roll};
|
|
||||||
if (Global.bRollFix)
|
|
||||||
item.location.y += 0.75 * std::abs(std::sin(glm::radians(roll)));
|
|
||||||
}
|
|
||||||
standing_template standing;
|
standing_template standing;
|
||||||
int present{-1};
|
int present{-1};
|
||||||
int variant{0};
|
int variant{0};
|
||||||
|
|||||||
Reference in New Issue
Block a user