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

feat(editor): infrastructure bound to the paths follows their changes

This commit is contained in:
maj00r
2026-10-04 00:14:03 +02:00
parent 7371b18910
commit 8778353b22
15 changed files with 2083 additions and 1 deletions

View File

@@ -503,6 +503,30 @@ basic_cell::erase( TMemCell *Memorycell ) {
std::end( m_memorycells ) );
}
void
basic_cell::erase( TTraction *Traction ) {
m_traction.erase(
std::remove( std::begin( m_traction ), std::end( m_traction ), Traction ),
std::end( m_traction ) );
}
void
basic_cell::unregister_end( TTraction *Traction ) {
m_directories.traction.erase(
std::remove( std::begin( m_directories.traction ), std::end( m_directories.traction ), Traction ),
std::end( m_directories.traction ) );
}
void
basic_cell::erase( TEventLauncher *Launcher ) {
m_eventlaunchers.erase(
std::remove( std::begin( m_eventlaunchers ), std::end( m_eventlaunchers ), Launcher ),
std::end( m_eventlaunchers ) );
}
// registers provided path in the lookup directory of the cell
void
basic_cell::register_end( TTrack *Path ) {

View File

@@ -155,6 +155,14 @@ public:
// removes provided memory cell from the cell
void
erase( TMemCell *Memorycell );
// removes provided traction piece from the cell
void
erase( TTraction *Traction );
void
unregister_end( TTraction *Traction );
// removes provided event launcher from the cell
void
erase( TEventLauncher *Launcher );
// find a vehicle located nearest to specified point, within specified radius. reurns: located vehicle and distance
std::tuple<TDynamicObject *, float>
find( glm::dvec3 const &Point, float const Radius, bool const Onlycontrolled, bool const Findbycoupler ) const;

View File

@@ -292,6 +292,11 @@ class node_layers
{
return Instance != 0 && Instance <= m_instances.size();
}
// handles of the includes run from 1 up to this number
std::size_t instance_count() const
{
return m_instances.size();
}
// grants access to specified include. NOTE: the include has to be tracked
include_instance const &instance(instance_handle const Instance) const
{

View File

@@ -14,6 +14,9 @@ http://mozilla.org/MPL/2.0/.
#include "simulation/simulation.h"
#include "model/AnimModel.h"
#include "world/MemCell.h"
#include "world/Traction.h"
#include "world/EvLaunch.h"
#include "world/Event.h"
#include "utilities/Globals.h"
#include "utilities/Logs.h"
#include "utilities/utilities.h"
@@ -233,6 +236,54 @@ bool patch_memcell(std::string &Text, glm::dvec3 const &Location, std::string &E
return true;
}
// definition layout: node <max> <min> <name> traction <supply> <voltage> <current> <resistivity> <material> <thickness> <damage>
// <point 1> <point 2> <point 3> <point 4> <minimal height> <segment length> <wires> <offset> <vis> [parallel <name>] endtraction
bool patch_traction(std::string &Text, TTraction const &Traction, glm::dvec3 const &Offset, std::string &Error)
{
auto const tokens{tokenize(Text)};
if (tokens.size() < 30 || tokens[0].text != "node" || tokens[4].text != "traction" || tokens.back().text != "endtraction")
{
Error = "unexpected layout of traction definition";
return false;
}
std::vector<text_change> changes;
std::size_t index{12};
for (auto const &point : {Traction.pPoint1, Traction.pPoint2, Traction.pPoint3, Traction.pPoint4})
{
auto const local{point - Offset};
for (auto const value : {local.x, local.y, local.z})
{
changes.push_back({tokens[index].begin, tokens[index].end, number(value)});
++index;
}
}
auto const &p1{Traction.pPoint1};
auto const &p2{Traction.pPoint2};
auto const &p3{Traction.pPoint3};
auto const &p4{Traction.pPoint4};
changes.push_back({tokens[24].begin, tokens[24].end, number((p3.y - p1.y + p4.y - p2.y) * 0.5 - Traction.fHeightDifference)});
if (Traction.iNumSections > 0)
{
// the load truncates length / segment length, the margin keeps the rounding of the number from losing a section
changes.push_back({tokens[25].begin, tokens[25].end, number(glm::length(p1 - p2) / (Traction.iNumSections + 0.001))});
}
apply(Text, changes);
return true;
}
// definition layout: node <max> <min> <name> eventlauncher <x> <y> <z> <radius> ... end
bool patch_launcher(std::string &Text, glm::dvec3 const &Location, std::string &Error)
{
auto const tokens{tokenize(Text)};
if (tokens.size() < 9 || tokens[0].text != "node" || tokens[4].text != "eventlauncher")
{
Error = "unexpected layout of event launcher definition";
return false;
}
apply(Text, {{tokens[5].begin, tokens[5].end, number(Location.x)}, {tokens[6].begin, tokens[6].end, number(Location.y)}, {tokens[7].begin, tokens[7].end, number(Location.z)}});
return true;
}
std::string detect_eol(std::string const &Text, std::string const &Fallback)
{
auto const linebreak{Text.find('\n')};
@@ -730,6 +781,63 @@ save_result node_layers::save(std::vector<std::string> const &Rootstatements)
return fail(state.error);
}
}
// traction and event launchers are rewritten when the editor moved them along with the track they belong to
std::vector<basic_node *> patchednodes;
auto const patch_node = [&](basic_node *Node, auto const &Patch) {
auto const lookup{m_sources.find(Node)};
if (lookup == m_sources.end() || false == Node->dirty())
{
return true;
}
auto const &source{lookup->second};
if (false == is_output(resolve(source.layer)) || false == writable(source.layer))
{
return true;
}
if (false == load(source.layer))
{
return false;
}
auto const &content{state.content[source.layer]};
if (source.span.end > static_cast<std::streamoff>(content.size()))
{
state.error = "definition of \"" + Node->name() + "\" is out of bounds of file \"" + layer(source.layer).name + "\"";
return false;
}
auto text{content.substr(static_cast<std::size_t>(source.span.begin), static_cast<std::size_t>(source.span.end - source.span.begin))};
std::string error;
if (false == Patch(text, source, error))
{
state.error = error + " of \"" + Node->name() + "\" in file \"" + layer(source.layer).name + "\"";
return false;
}
file_patch::edit edit;
edit.begin = source.span.begin;
edit.end = source.span.end;
edit.length = text.size();
edit.text = std::move(text);
edit.node = Node;
state.patches[source.layer].edits.emplace_back(std::move(edit));
rewritten.emplace(Node);
patchednodes.push_back(Node);
return true;
};
for (auto *traction : simulation::Traction.sequence())
{
if (traction != nullptr &&
false == patch_node(traction, [&](std::string &Text, node_source const &Source, std::string &Error) { return patch_traction(Text, *traction, Source.context.offset, Error); }))
{
return fail(state.error);
}
}
for (auto *launcher : simulation::Events.launchers())
{
if (launcher != nullptr &&
false == patch_node(launcher, [&](std::string &Text, node_source const &Source, std::string &Error) { return patch_launcher(Text, Source.context.to_local(launcher->location()), Error); }))
{
return fail(state.error);
}
}
std::vector<TTrack *> savedpaths;
std::vector<TTrack const *> droppedpaths;
auto const path_text = [](TTrack &Path, glm::dvec3 const &Offset) {
@@ -1281,6 +1389,10 @@ save_result node_layers::save(std::vector<std::string> const &Rootstatements)
{
path->m_dirty = false;
}
for (auto *node : patchednodes)
{
node->m_dirty = false;
}
for (auto const *path : droppedpaths)
{
m_sources.erase(path);