mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 05:09:20 +02:00
refactor(editor): stored bindings read apart from their registration, one way to open a profile route
This commit is contained in:
@@ -545,6 +545,7 @@ class editor_mode : public application_mode, private editor_track::observer
|
||||
void render_profile_issues();
|
||||
void profile_open(TTrack *From, TTrack *To);
|
||||
void profile_open_run(TTrack &Track);
|
||||
void profile_take(editor_track::route Route, TTrack *From, TTrack *To);
|
||||
void profile_resample();
|
||||
void profile_recognize();
|
||||
void profile_check();
|
||||
|
||||
@@ -459,12 +459,130 @@ double turn_of(infra::binding const &Binding, double const Yaw)
|
||||
return clamp_circular(Yaw - infra::heading(axis.forward));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// the objects which the stored bindings can name, by their locations
|
||||
struct bindable_objects
|
||||
{
|
||||
point_grid<TTrack *> paths;
|
||||
point_grid<TAnimModel *> models;
|
||||
point_grid<TTraction *> traction;
|
||||
point_grid<scene::basic_node *> logic;
|
||||
point_grid<scene::instance_handle> includes;
|
||||
|
||||
bindable_objects()
|
||||
{
|
||||
for (auto *track : simulation::Paths.sequence())
|
||||
if (track != nullptr && false == track->m_editorremoved)
|
||||
for (auto const &path : track->m_paths)
|
||||
paths.add(path.points[segment_data::point::start], track);
|
||||
for (auto *model : simulation::Instances.sequence())
|
||||
if (model != nullptr && false == model->from_template() && model->Model() != nullptr)
|
||||
models.add(model->location(), model);
|
||||
for (auto *piece : simulation::Traction.sequence())
|
||||
if (piece != nullptr && false == piece->from_template())
|
||||
traction.add(piece->pPoint1, piece);
|
||||
for (auto *memcell : simulation::Memory.sequence())
|
||||
if (memcell != nullptr && false == memcell->from_template())
|
||||
logic.add(memcell->location(), memcell);
|
||||
for (auto *launcher : simulation::Events.launchers())
|
||||
if (launcher != nullptr && false == launcher->from_template())
|
||||
logic.add(launcher->location(), launcher);
|
||||
for (scene::instance_handle handle = 1; handle <= scene::Layers.instance_count(); ++handle)
|
||||
{
|
||||
include_place place;
|
||||
if (include_place_of(handle, place))
|
||||
includes.add(include_location(place), handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// format of the lines, coordinates in the space of the file:
|
||||
// <kind> <category> <x y z of the object> <file or name, - if none> <turns 0/1> <anchor count> { <path> <start x y z> <end x y z> }
|
||||
// the object is the model, the include (position from its parameters), the traction piece (its first point), the memory
|
||||
// cell or the event launcher found at the location; the anchors name the paths by their ends
|
||||
std::optional<infra::binding> read_binding(std::string const &Text, scene::layer_context const &Context, bindable_objects const &Objects)
|
||||
{
|
||||
double const tolerance{0.05};
|
||||
std::istringstream line{Text};
|
||||
std::string kindname, key;
|
||||
int group{0}, turns{0}, count{0};
|
||||
glm::dvec3 location;
|
||||
line >> kindname >> group >> location.x >> location.y >> location.z >> key >> turns >> count;
|
||||
if (line.fail() || count < 1 || count > 4)
|
||||
return std::nullopt;
|
||||
location = Context.to_world(location);
|
||||
infra::binding binding;
|
||||
binding.group = static_cast<infra::category>(std::clamp(group, 0, static_cast<int>(infra::category::other)));
|
||||
binding.turns = (turns != 0);
|
||||
auto found{false};
|
||||
if (kindname == infra::name(infra::kind::model))
|
||||
{
|
||||
binding.type = infra::kind::model;
|
||||
auto const model{Objects.models.find(location, tolerance, [&](TAnimModel *Model) { return Model->Model()->NameGet() == key; })};
|
||||
if ((found = model.has_value()))
|
||||
binding.node = *model;
|
||||
}
|
||||
else if (kindname == infra::name(infra::kind::include))
|
||||
{
|
||||
binding.type = infra::kind::include;
|
||||
auto const handle{Objects.includes.find(location, tolerance, [&](scene::instance_handle Handle) { return *scene::Layers.instance(Handle).file == key; })};
|
||||
if ((found = handle.has_value()))
|
||||
binding.include = *handle;
|
||||
}
|
||||
else if (kindname == infra::name(infra::kind::traction))
|
||||
{
|
||||
binding.type = infra::kind::traction;
|
||||
auto const piece{Objects.traction.find(location, tolerance, [](TTraction *) { return true; })};
|
||||
if ((found = piece.has_value()))
|
||||
binding.node = *piece;
|
||||
}
|
||||
else if (kindname == infra::name(infra::kind::memcell) || kindname == infra::name(infra::kind::launcher))
|
||||
{
|
||||
binding.type = (kindname == infra::name(infra::kind::memcell) ? infra::kind::memcell : infra::kind::launcher);
|
||||
auto const node{Objects.logic.find(location, tolerance, [&](scene::basic_node *Node) {
|
||||
auto const ismemcell{dynamic_cast<TMemCell *>(Node) != nullptr};
|
||||
return ismemcell == (binding.type == infra::kind::memcell) && (key == "-" || Node->name() == key);
|
||||
})};
|
||||
if ((found = node.has_value()))
|
||||
binding.node = *node;
|
||||
}
|
||||
std::vector<glm::dvec3> points;
|
||||
std::optional<double> yaw;
|
||||
if (false == found || false == object_points(binding, points, yaw))
|
||||
return std::nullopt;
|
||||
for (int i = 0; i < count && found; ++i)
|
||||
{
|
||||
int path{0};
|
||||
glm::dvec3 start, end;
|
||||
line >> path >> start.x >> start.y >> start.z >> end.x >> end.y >> end.z;
|
||||
start = Context.to_world(start);
|
||||
end = Context.to_world(end);
|
||||
auto const track{Objects.paths.find(start, tolerance, [&](TTrack *Track) {
|
||||
return path >= 0 && path < static_cast<int>(Track->m_paths.size()) &&
|
||||
glm::distance(Track->m_paths[path].points[segment_data::point::start], start) <= tolerance &&
|
||||
glm::distance(Track->m_paths[path].points[segment_data::point::end], end) <= tolerance;
|
||||
})};
|
||||
if (line.fail() || false == track.has_value())
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
auto const &point{points[std::min<std::size_t>(i, points.size() - 1)]};
|
||||
double s;
|
||||
bool interior;
|
||||
infra::project((*track)->m_paths[path], point, s, interior);
|
||||
binding.anchors.push_back(infra::make_anchor({*track, path, s}, point));
|
||||
}
|
||||
if (false == found || binding.anchors.size() != points.size())
|
||||
return std::nullopt;
|
||||
binding.turns = binding.turns && yaw.has_value();
|
||||
if (binding.turns)
|
||||
binding.yaw = turn_of(binding, *yaw);
|
||||
binding.label = object_label(binding);
|
||||
return binding;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void editor_mode::infra_load()
|
||||
{
|
||||
if (m_bindings_loaded || scene::Layers.empty())
|
||||
@@ -474,35 +592,7 @@ void editor_mode::infra_load()
|
||||
if (marked.empty())
|
||||
return;
|
||||
|
||||
point_grid<TTrack *> paths;
|
||||
for (auto *track : simulation::Paths.sequence())
|
||||
if (track != nullptr && false == track->m_editorremoved)
|
||||
for (auto const &path : track->m_paths)
|
||||
paths.add(path.points[segment_data::point::start], track);
|
||||
point_grid<TAnimModel *> models;
|
||||
for (auto *model : simulation::Instances.sequence())
|
||||
if (model != nullptr && false == model->from_template() && model->Model() != nullptr)
|
||||
models.add(model->location(), model);
|
||||
point_grid<TTraction *> traction;
|
||||
for (auto *piece : simulation::Traction.sequence())
|
||||
if (piece != nullptr && false == piece->from_template())
|
||||
traction.add(piece->pPoint1, piece);
|
||||
point_grid<scene::basic_node *> logic;
|
||||
for (auto *memcell : simulation::Memory.sequence())
|
||||
if (memcell != nullptr && false == memcell->from_template())
|
||||
logic.add(memcell->location(), memcell);
|
||||
for (auto *launcher : simulation::Events.launchers())
|
||||
if (launcher != nullptr && false == launcher->from_template())
|
||||
logic.add(launcher->location(), launcher);
|
||||
point_grid<scene::instance_handle> includes;
|
||||
for (scene::instance_handle handle = 1; handle <= scene::Layers.instance_count(); ++handle)
|
||||
{
|
||||
include_place place;
|
||||
if (include_place_of(handle, place))
|
||||
includes.add(include_location(place), handle);
|
||||
}
|
||||
|
||||
double const tolerance{0.05};
|
||||
bindable_objects const objects;
|
||||
auto resolved{0};
|
||||
for (auto const layer : marked)
|
||||
{
|
||||
@@ -511,93 +601,13 @@ void editor_mode::infra_load()
|
||||
{
|
||||
if (text.empty() || text.front() == '#')
|
||||
continue;
|
||||
std::istringstream line{text};
|
||||
std::string kindname, key;
|
||||
int group{0}, turns{0}, count{0};
|
||||
glm::dvec3 location;
|
||||
line >> kindname >> group >> location.x >> location.y >> location.z >> key >> turns >> count;
|
||||
auto const keep = [&]() { m_bindings_unresolved.emplace_back(layer, text); };
|
||||
if (line.fail() || count < 1 || count > 4)
|
||||
auto binding{read_binding(text, context, objects)};
|
||||
if (false == binding.has_value())
|
||||
{
|
||||
keep();
|
||||
m_bindings_unresolved.emplace_back(layer, text);
|
||||
continue;
|
||||
}
|
||||
location = context.to_world(location);
|
||||
infra::binding binding;
|
||||
binding.group = static_cast<infra::category>(std::clamp(group, 0, static_cast<int>(infra::category::other)));
|
||||
binding.turns = (turns != 0);
|
||||
auto found{false};
|
||||
if (kindname == infra::name(infra::kind::model))
|
||||
{
|
||||
binding.type = infra::kind::model;
|
||||
auto const model{models.find(location, tolerance, [&](TAnimModel *Model) { return Model->Model()->NameGet() == key; })};
|
||||
if ((found = model.has_value()))
|
||||
binding.node = *model;
|
||||
}
|
||||
else if (kindname == infra::name(infra::kind::include))
|
||||
{
|
||||
binding.type = infra::kind::include;
|
||||
auto const handle{includes.find(location, tolerance, [&](scene::instance_handle Handle) { return *scene::Layers.instance(Handle).file == key; })};
|
||||
if ((found = handle.has_value()))
|
||||
binding.include = *handle;
|
||||
}
|
||||
else if (kindname == infra::name(infra::kind::traction))
|
||||
{
|
||||
binding.type = infra::kind::traction;
|
||||
auto const piece{traction.find(location, tolerance, [](TTraction *) { return true; })};
|
||||
if ((found = piece.has_value()))
|
||||
binding.node = *piece;
|
||||
}
|
||||
else if (kindname == infra::name(infra::kind::memcell) || kindname == infra::name(infra::kind::launcher))
|
||||
{
|
||||
binding.type = (kindname == infra::name(infra::kind::memcell) ? infra::kind::memcell : infra::kind::launcher);
|
||||
auto const node{logic.find(location, tolerance, [&](scene::basic_node *Node) {
|
||||
auto const ismemcell{dynamic_cast<TMemCell *>(Node) != nullptr};
|
||||
return ismemcell == (binding.type == infra::kind::memcell) && (key == "-" || Node->name() == key);
|
||||
})};
|
||||
if ((found = node.has_value()))
|
||||
binding.node = *node;
|
||||
}
|
||||
std::vector<glm::dvec3> points;
|
||||
std::optional<double> yaw;
|
||||
if (false == found || false == object_points(binding, points, yaw))
|
||||
{
|
||||
keep();
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < count && found; ++i)
|
||||
{
|
||||
int path{0};
|
||||
glm::dvec3 start, end;
|
||||
line >> path >> start.x >> start.y >> start.z >> end.x >> end.y >> end.z;
|
||||
start = context.to_world(start);
|
||||
end = context.to_world(end);
|
||||
auto const track{paths.find(start, tolerance, [&](TTrack *Track) {
|
||||
return path >= 0 && path < static_cast<int>(Track->m_paths.size()) &&
|
||||
glm::distance(Track->m_paths[path].points[segment_data::point::start], start) <= tolerance &&
|
||||
glm::distance(Track->m_paths[path].points[segment_data::point::end], end) <= tolerance;
|
||||
})};
|
||||
if (line.fail() || false == track.has_value())
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
auto const &point{points[std::min<std::size_t>(i, points.size() - 1)]};
|
||||
double s;
|
||||
bool interior;
|
||||
infra::project((*track)->m_paths[path], point, s, interior);
|
||||
binding.anchors.push_back(infra::make_anchor({*track, path, s}, point));
|
||||
}
|
||||
if (false == found || binding.anchors.size() != points.size())
|
||||
{
|
||||
keep();
|
||||
continue;
|
||||
}
|
||||
binding.turns = binding.turns && yaw.has_value();
|
||||
if (binding.turns)
|
||||
binding.yaw = turn_of(binding, *yaw);
|
||||
binding.label = object_label(binding);
|
||||
m_bindings.push_back(std::move(binding));
|
||||
m_bindings.push_back(std::move(*binding));
|
||||
++resolved;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,14 +347,7 @@ void editor_mode::profile_open(TTrack *From, TTrack *To)
|
||||
editor_track::route route;
|
||||
if (false == editor_track::find_route(From, To, route, state.error))
|
||||
return;
|
||||
state.from = state.picked_from = From;
|
||||
state.to = state.picked_to = To;
|
||||
state.route = std::move(route);
|
||||
state.selected = -1;
|
||||
profile_resample();
|
||||
if (false == profile_restore())
|
||||
profile_recognize();
|
||||
profile_fit_view();
|
||||
profile_take(std::move(route), From, To);
|
||||
}
|
||||
|
||||
void editor_mode::profile_open_run(TTrack &Track)
|
||||
@@ -369,9 +362,17 @@ void editor_mode::profile_open_run(TTrack &Track)
|
||||
state.error = "The path can't carry a profile";
|
||||
return;
|
||||
}
|
||||
state.route = std::move(route);
|
||||
state.from = state.picked_from = state.route.spans.front().track;
|
||||
state.to = state.picked_to = state.route.spans.back().track;
|
||||
auto *from{route.spans.front().track};
|
||||
auto *to{route.spans.back().track};
|
||||
profile_take(std::move(route), from, to);
|
||||
}
|
||||
|
||||
void editor_mode::profile_take(editor_track::route Route, TTrack *From, TTrack *To)
|
||||
{
|
||||
auto &state{m_profile};
|
||||
state.from = state.picked_from = From;
|
||||
state.to = state.picked_to = To;
|
||||
state.route = std::move(Route);
|
||||
state.selected = -1;
|
||||
profile_resample();
|
||||
if (false == profile_restore())
|
||||
|
||||
Reference in New Issue
Block a user