mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 14:29:20 +02:00
feat(editor): a model or an include standing by a track bent along it (B, or the Bend along the track section of the toolset): it stays where it stood and follows the track, through the joined tracks as far as it reaches; reference point at its start, origin, middle, end or a point picked on the model, across at its origin, the side facing the track, the far side or its middle, up at its origin, bottom, top or the top of its edge by the track; the blue cross of a bent model dragged for its offset, with Shift for its height and with Ctrl along the track, the values shown at the cursor; a bent model clicked to edit; one step of the undo history; scale of the model kept, parts lit only at night left out; edges of platforms told by the name of the model and by the overhang of their edge over the foot: put 1.725 m from the axis at the height the name gives, turned with the edge to the track when they stood the other way; platforms stand on the plane of the rail heads carried on to their edge (PKP PLK ST-T2), the gauge widening led in from the tracks beyond the ends and from the other path of a switch; gaps between the pieces of a sweep filled with the paths which join them; Platforms and models tab left out of the track editor; laid track eased into the curvature of the one it joins with a transition curve; File > Open scenery... starts the editor again with the scenery picked from a list; the camera saved with the scenery; T and Shift+T turn each turntable to its next and previous position by event launchers written on each save; a turntable track deleted with its template; a scenery with no trainset gets a WMB10 on its first track; vehicle placed where the track is clicked; gauge check takes in the bent models; Polish translation of the editor
This commit is contained in:
@@ -19,6 +19,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "rendering/renderer.h"
|
||||
#include "simulation/simulation.h"
|
||||
#include "utilities/Logs.h"
|
||||
#include "world/Sweep.h"
|
||||
#include "world/Track.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "utilities/translation.h"
|
||||
@@ -324,6 +325,33 @@ template <typename Visitor> void visit_triangles(TSubModel *Submodel, glm::dmat4
|
||||
}
|
||||
}
|
||||
|
||||
// the triangle enters the gauge when any point of a grid spread over it does; the deepest such point goes to the hit
|
||||
void scan_triangle(corridor const &Space, glm::dvec3 const &A, glm::dvec3 const &B, glm::dvec3 const &C, editor_mode::gauge_hit &Hit)
|
||||
{
|
||||
auto const middle{(A + B + C) / 3.0};
|
||||
if (false == Space.close(middle, std::max({glm::distance(middle, A), glm::distance(middle, B), glm::distance(middle, C)})))
|
||||
return;
|
||||
auto const edge{std::max({glm::distance(A, B), glm::distance(B, C), glm::distance(C, A)})};
|
||||
auto const steps{std::clamp(static_cast<int>(std::ceil(edge / 0.5)), 1, 24)};
|
||||
for (int u = 0; u <= steps; ++u)
|
||||
for (int v = 0; u + v <= steps; ++v)
|
||||
{
|
||||
auto const point{A + (B - A) * (static_cast<double>(u) / steps) + (C - A) * (static_cast<double>(v) / steps)};
|
||||
auto const found{Space.intrusion(point)};
|
||||
if (found.depth <= 0.0)
|
||||
continue;
|
||||
if (found.depth > Hit.depth)
|
||||
{
|
||||
Hit.depth = found.depth;
|
||||
Hit.point = point;
|
||||
Hit.track = found.span->track;
|
||||
Hit.path = found.span->path;
|
||||
Hit.direction = found.direction;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// the deepest place of the model in the gauge, added to the hits when it enters it
|
||||
void scan_model(corridor const &Space, TAnimModel &Instance, std::vector<editor_mode::gauge_hit> &Hits)
|
||||
{
|
||||
@@ -332,31 +360,23 @@ void scan_model(corridor const &Space, TAnimModel &Instance, std::vector<editor_
|
||||
if (false == Space.nearby(Instance.location(), Instance.radius()))
|
||||
return;
|
||||
editor_mode::gauge_hit hit{Instance.name(), Instance.location()};
|
||||
// the triangle enters the gauge when any point of a grid spread over it does
|
||||
visit_triangles(Instance.Model()->GetSMRoot(), placement(Instance), [&](glm::dvec3 const &A, glm::dvec3 const &B, glm::dvec3 const &C) {
|
||||
auto const middle{(A + B + C) / 3.0};
|
||||
if (false == Space.close(middle, std::max({glm::distance(middle, A), glm::distance(middle, B), glm::distance(middle, C)})))
|
||||
return;
|
||||
auto const edge{std::max({glm::distance(A, B), glm::distance(B, C), glm::distance(C, A)})};
|
||||
auto const steps{std::clamp(static_cast<int>(std::ceil(edge / 0.5)), 1, 24)};
|
||||
for (int u = 0; u <= steps; ++u)
|
||||
for (int v = 0; u + v <= steps; ++v)
|
||||
{
|
||||
auto const point{A + (B - A) * (static_cast<double>(u) / steps) + (C - A) * (static_cast<double>(v) / steps)};
|
||||
auto const found{Space.intrusion(point)};
|
||||
if (found.depth <= 0.0)
|
||||
continue;
|
||||
if (found.depth > hit.depth)
|
||||
{
|
||||
hit.depth = found.depth;
|
||||
hit.point = point;
|
||||
hit.track = found.span->track;
|
||||
hit.path = found.span->path;
|
||||
hit.direction = found.direction;
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
visit_triangles(Instance.Model()->GetSMRoot(), placement(Instance), [&](glm::dvec3 const &A, glm::dvec3 const &B, glm::dvec3 const &C) { scan_triangle(Space, A, B, C, hit); });
|
||||
if (hit.depth > 0.0)
|
||||
Hits.push_back(std::move(hit));
|
||||
}
|
||||
|
||||
// the same for the copies of a model laid along a curve
|
||||
void scan_sweep(corridor const &Space, sweep_node &Sweep, std::vector<editor_mode::gauge_hit> &Hits)
|
||||
{
|
||||
if (Sweep.m_editorremoved || false == Space.nearby(Sweep.location(), Sweep.radius()))
|
||||
return;
|
||||
editor_mode::gauge_hit hit{Sweep.name(), Sweep.location()};
|
||||
for (auto const &shape : Sweep.create_shapes())
|
||||
{
|
||||
auto const &vertices{shape.data().vertices};
|
||||
for (std::size_t i = 0; i + 2 < vertices.size(); i += 3)
|
||||
scan_triangle(Space, vertices[i].position, vertices[i + 1].position, vertices[i + 2].position, hit);
|
||||
}
|
||||
if (hit.depth > 0.0)
|
||||
Hits.push_back(std::move(hit));
|
||||
}
|
||||
@@ -372,6 +392,9 @@ void scan_models(corridor const &Space, std::vector<editor_mode::gauge_hit> &Hit
|
||||
for (auto *instance : simulation::Instances.sequence())
|
||||
if (instance != nullptr)
|
||||
scan_model(Space, *instance, Hits);
|
||||
for (auto *sweep : simulation::Sweeps.sequence())
|
||||
if (sweep != nullptr)
|
||||
scan_sweep(Space, *sweep, Hits);
|
||||
sort_hits(Hits);
|
||||
}
|
||||
|
||||
@@ -579,14 +602,22 @@ void editor_mode::step_gauge_map()
|
||||
{
|
||||
auto &scan{*m_gauge.scan};
|
||||
auto const &instances{simulation::Instances.sequence()};
|
||||
auto const &sweeps{simulation::Sweeps.sequence()};
|
||||
auto const total{instances.size() + sweeps.size()};
|
||||
auto const until{std::chrono::steady_clock::now() + gauge_slice};
|
||||
while (scan.next < instances.size() && std::chrono::steady_clock::now() < until)
|
||||
while (scan.next < total && std::chrono::steady_clock::now() < until)
|
||||
{
|
||||
if (auto *instance{instances[scan.next++]})
|
||||
scan_model(*scan.space, *instance, m_gauge.map.hits);
|
||||
auto const next{scan.next++};
|
||||
if (next < instances.size())
|
||||
{
|
||||
if (auto *instance{instances[next]})
|
||||
scan_model(*scan.space, *instance, m_gauge.map.hits);
|
||||
}
|
||||
else if (auto *sweep{sweeps[next - instances.size()]})
|
||||
scan_sweep(*scan.space, *sweep, m_gauge.map.hits);
|
||||
}
|
||||
scan.progress = instances.empty() ? 1.f : static_cast<float>(scan.next) / instances.size();
|
||||
if (scan.next >= instances.size())
|
||||
scan.progress = total == 0 ? 1.f : static_cast<float>(scan.next) / total;
|
||||
if (scan.next >= total)
|
||||
finish_gauge_map();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user