17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-20 16:14:52 +02:00

fix(editor): putting the scenery onto the terrain model no longer leaves deleted models in the scene

The lift moved the models of the includes it remade a moment later, so
the cells kept the old ones after they were destroyed and the next look
at the ground there (a zoom) crashed. They stay as they are now, and the
models already waiting to be destroyed are skipped too. The self-test
gets danglers, which counts the models the cells hold past their end.
This commit is contained in:
maj00r
2026-10-19 19:25:25 +02:00
parent af9e836632
commit e3ea6a766e
2 changed files with 34 additions and 4 deletions

View File

@@ -1030,13 +1030,18 @@ void editor_mode::nmt_lift_scenery(double const Offset)
item.yaw = standing.yaw;
moves.emplace_back(standing, item);
}
if (move_templates(moves) > 0 && m_history.size() >= 2)
m_history.back().joined = true;
// the models, a group as a whole
// the includes moved by the place in their parameters are made anew there: their models aren't moved on their own, nor are
// the models left behind by earlier changes, deleted a moment later: moved, they'd get into the scene again
std::set<scene::instance_handle> remade;
for (auto const &move : moves)
if (scene::Layers.tracked(move.first.instance) && scene::Layers.removable(move.first.instance))
remade.insert(move.first.instance);
// the models, a group as a whole, ahead of the includes, which retire theirs
std::set<int> groups;
for (auto *instance : simulation::Instances.sequence())
{
if (instance == nullptr)
if (instance == nullptr || remade.contains(instance->m_instance) ||
std::any_of(m_retired.begin(), m_retired.end(), [&](std::pair<TAnimModel *, int> const &Retired) { return Retired.first == instance; }))
continue;
if (instance->group() > 1 && false == groups.insert(instance->group()).second)
continue;
@@ -1044,6 +1049,8 @@ void editor_mode::nmt_lift_scenery(double const Offset)
m_history.back().joined = true;
m_editor.translate(instance, instance->location() + shift, true);
}
if (move_templates(moves) > 0 && m_history.size() >= 2)
m_history.back().joined = true;
WriteLog(format("Editor: NMT - the scenery moved %+.2f m: %zu tracks, %zu includes, the models", Offset, lifted, moves.size()), logtype::generic);
}

View File

@@ -231,6 +231,29 @@ editor_mode::selftest_result editor_mode::selftest_terrain(std::string const &co
WriteLog("SELFTEST nmtwait: " + m_nmt_state.status + (m_nmt_state.error.empty() ? std::string{} : " (" + m_nmt_state.error + ")"));
return selftest_result::handled;
}
if (command == "danglers")
{
// models the cells hold which aren't in the scene any more, or are about to be destroyed
std::set<TAnimModel const *> const alive{simulation::Instances.sequence().begin(), simulation::Instances.sequence().end()};
std::size_t held{0}, gone{0}, retired{0};
for (auto const *section : simulation::Region->m_sections)
{
if (section == nullptr)
continue;
for (auto const &cell : section->m_cells)
for (auto const *sequence : {&cell.m_instancesopaque, &cell.m_instancetranslucent})
for (auto const *instance : *sequence)
{
++held;
if (false == alive.contains(instance))
++gone;
else if (std::any_of(m_retired.begin(), m_retired.end(), [&](std::pair<TAnimModel *, int> const &Retired) { return Retired.first == instance; }))
++retired;
}
}
WriteLog(format("SELFTEST danglers: %zu held, %zu gone, %zu retired, %zu waiting", held, gone, retired, m_retired.size()));
return selftest_result::handled;
}
if (command == "terrainmode")
{
m_terrain_open = true;