17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-17 06:19:19 +02:00
Files
maszyna/world/Track.h

563 lines
26 KiB
C++

/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <string>
#include <vector>
#include <deque>
#include <array>
#include <glm/glm.hpp>
#include <glm/mat4x4.hpp>
#include "utilities/Classes.h"
#include "world/Segment.h"
#include "model/material.h"
#include "scene/scenenode.h"
#include "utilities/Names.h"
namespace scene {
class basic_cell;
}
enum TTrackType {
tt_Unknown,
tt_Normal,
tt_Switch,
tt_Table,
tt_Cross,
tt_Tributary
};
// McZapkie-100502
enum TEnvironmentType {
e_unknown = -1,
e_flat = 0,
e_mountains,
e_canyon,
e_tunnel,
e_bridge,
e_bank
};
// Ra: opracować alternatywny system cieni/świateł z definiowaniem koloru oświetlenia w halach
class basic_event;
class TTrack;
class TGroundNode;
class TSubRect;
class TTraction;
class TSwitchExtension
{ // dodatkowe dane do toru, który jest zwrotnicą
public:
TSwitchExtension(TTrack *owner, int const what);
~TSwitchExtension();
std::shared_ptr<TSegment> Segments[6]; // dwa tory od punktu 1, pozosta³e dwa od 2? Ra 140101: 6 po³¹czeñ dla skrzy¿owañ
TTrack *pNexts[2]; // tory do³¹czone do punktów 2 i 4
TTrack *pPrevs[2]; // tory do³¹czone do punktów 1 i 3
int iNextDirection[2]; // to te¿ z [2]+[2] przerobiæ na [4]
int iPrevDirection[2];
int CurrentIndex = 0; // dla zwrotnicy
float
fOffset{ 0.f },
fDesiredOffset{ 0.f }; // aktualne i docelowe położenie napędu iglic
float fOffsetSpeed = 0.1f; // prędkość liniowa ruchu iglic
float fOffsetDelay = 0.05f; // opóźnienie ruchu drugiej iglicy względem pierwszej // dodatkowy ruch drugiej iglicy po zablokowaniu pierwszej na opornicy
union
{
struct
{ // zmienne potrzebne tylko dla zwrotnicy
float fOffset1,
fOffset2; // przesunięcia iglic - 0=na wprost
bool RightSwitch; // czy zwrotnica w prawo
};
struct
{ // zmienne potrzebne tylko dla obrotnicy/przesuwnicy
// TAnimContainer *pAnim; //animator modelu dla obrotnicy
TAnimModel *pModel; // na razie model
};
struct
{ // zmienne dla skrzyżowania
int iRoads; // ile dróg się spotyka?
glm::vec3 *vPoints; // tablica wierzchołków nawierzchni, generowana przez pobocze
bool bPoints; // czy utworzone?
};
};
bool bMovement = false; // czy w trakcie animacji
scene::basic_cell *pOwner = nullptr; // TODO: convert this to observer pattern
TTrack *pNextAnim = nullptr; // następny tor do animowania
basic_event *evPlus = nullptr,
*evMinus = nullptr; // zdarzenia sygnalizacji rozprucia
float fVelocity = -1.0; // maksymalne ograniczenie prędkości (ustawianej eventem)
glm::dvec3 vTrans; // docelowa translacja przesuwnicy
material_handle m_material3 = 0; // texture of auto generated switch trackbed
gfx::geometry_handle Geometry3; // geometry of auto generated switch trackbed
bool m_frogs { false }; // the frog and check rails are made from the rails, for switches with no model of them in their includes
gfx::geometrybank_handle map_geometry[6]; // geometry for map visualisation
};
class TIsolated
{ // obiekt zbierający zajętości z kilku odcinków
public:
// constructors
TIsolated(const std::string &n, TIsolated *i);
// methods
static void DeleteAll();
static TIsolated * Find(const std::string &n); // znalezienie obiektu albo utworzenie nowego
void AssignEvents();
void Modify(int i, TDynamicObject *o); // dodanie lub odjęcie osi
inline
bool
Busy() {
return iAxles > 0; };
inline
static TIsolated *
Root() {
return pRoot; };
inline
TIsolated *
Next() {
return pNext; };
inline
void
parent( TIsolated *Parent ) {
pParent = Parent; }
inline
TIsolated *
parent() const {
return pParent; }
// members
std::string asName; // nazwa obiektu, baza do nazw eventów
basic_event *evBusy { nullptr }; // zdarzenie wyzwalane po zajęciu grupy
basic_event *evFree { nullptr }; // zdarzenie wyzwalane po całkowitym zwolnieniu zajętości grupy
basic_event *evInc { nullptr }; // wyzwalane po wjeździe na grupę
basic_event *evDec { nullptr }; // wyzwalane po zjazdu z grupy
TMemCell *pMemCell { nullptr }; // automatyczna komórka pamięci, która współpracuje z odcinkiem izolowanym
private:
// members
int iAxles { 0 }; // ilość osi na odcinkach obsługiwanych przez obiekt
TIsolated *pNext { nullptr }; // odcinki izolowane są trzymane w postaci listy jednikierunkowej
TIsolated *pParent { nullptr }; // optional parent piece, receiving data from its children
static TIsolated *pRoot; // początek listy
};
// trajektoria ruchu - opakowanie
class TTrack : public scene::basic_node
{
friend opengl_renderer;
friend opengl33_renderer;
// NOTE: temporary arrangement
friend itemproperties_panel;
friend class editor_track;
public:
std::vector<TIsolated*> Isolated; // obwód izolowany obsługujący zajęcia/zwolnienia grupy torów
std::shared_ptr<TSwitchExtension> SwitchExtension; // dodatkowe dane do toru, który jest zwrotnicą
std::shared_ptr<TSegment> Segment;
TTrack * trNext = nullptr; // odcinek od strony punktu 2 - to powinno być w segmencie
TTrack * trPrev = nullptr; // odcinek od strony punktu 1
// McZapkie-070402: dodalem zmienne opisujace rozmiary tekstur
int iTrapezoid = 0; // 0-standard, 1-przechyłka, 2-trapez, 3-oba
double fRadiusTable[ 2 ] = { 0.0, 0.0 }; // dwa promienie, drugi dla zwrotnicy
float fVerticalRadius { 0.f }; // y-axis track radius (currently not supported)
float fTexLength = 4.0f; // długość powtarzania tekstury w metrach
float fTexRatio1 = 1.0f; // proporcja boków tekstury nawierzchni (żeby zaoszczędzić na rozmiarach tekstur...)
float fTexRatio2 = 1.0f; // proporcja boków tekstury chodnika (żeby zaoszczędzić na rozmiarach tekstur...)
float fTexHeight1 = 0.6f; // wysokość brzegu względem trajektorii
float fTexHeightOffset = 0.f; // potential adjustment to account for the path roll
float fTexWidth = 0.9f; // szerokość boku
float fTexSlope = 0.9f;
glm::dvec3 m_origin;
// TODO: store material names as strings, for lossless serialization and export
material_handle m_material1 = 0; // tekstura szyn albo nawierzchni
material_handle m_material2 = 0; // tekstura automatycznej podsypki albo pobocza
std::pair<std::string, int> m_profile1 {}; // profile of geometry chunks textured with texture 1
using geometryhandle_sequence = std::vector<gfx::geometry_handle>;
geometryhandle_sequence Geometry1; // geometry chunks textured with texture 1
geometryhandle_sequence Geometry2; // geometry chunks textured with texture 2
material_handle m_materialcut1 = 0; // matte variant of texture 1, for the cut faces of rails
material_handle m_materialcut2 = 0; // matte variant of texture 2, for the cut faces of rails of the other switch path
geometryhandle_sequence GeometryCut1; // cut faces of rails textured with texture 1, the blade tip first for a switch
geometryhandle_sequence GeometryCut2; // cut faces of rails textured with texture 2, the blade tip first
struct tread_geometry {
material_handle material { 0 };
material_handle matte { 0 };
geometryhandle_sequence geometry;
geometryhandle_sequence cuts;
};
std::vector<tread_geometry> GeometryTreads;
std::vector<segment_data> m_paths; // source data for owned paths
bool m_editorremoved { false };
std::vector<TTrack *> m_crossings; // tracks whose rails cross the rails of this one, found when its geometry was made
scene::basic_node *m_road { nullptr }; // road or road junction which generated this path. such path is one-way, and isn't saved nor edited on its own
std::array<float, 3> m_routeweights { 0.f, 0.f, 0.f }; // odds of each route through a crossroads being picked by a driver, by the number of the route. all zero: even odds
int iterate_stamp = 0;
// sleepermodel optional parameter -------------------------------------------------
// Repeats a model along the path at fixed intervals (typically rail sleepers).
// Defined in scenery file as:
// sleepermodel <frequency> <model> <skin> <offsetX> <offsetY> <offsetZ> <ballastZ>
// The renderer draws the model instances via GPU instancing and skips them entirely
// once the camera-to-track distance exceeds Global.SleeperDistance.
bool m_sleeper_enabled { false };
float m_sleeper_frequency { 0.6f }; // spacing along the path, in meters
std::string m_sleeper_model_name; // path to the e3d sleeper model (as written in the .scn)
std::string m_sleeper_skin_name; // replacable skin path, or "none" for default
glm::vec3 m_sleeper_offset { 0.f, 0.f, 0.f }; // local offset from track centerline (x: left/right, y: forward/back, z: up/down)
float m_sleeper_ballast_z { 0.f }; // vertical offset applied to the trackbed (ballast) profile
TModel3d *m_sleeper_model { nullptr }; // resolved on init; nullptr means no model / failed to load
material_handle m_sleeper_skin { 0 }; // resolved replacable skin handle, 0 = use model defaults
// precomputed local-space transforms (relative to m_origin) for every sleeper instance along the path.
// Each matrix is translate(world_pos - m_origin) * rotate(direction, roll) * translate(local_offset).
// The renderer composes this with (view * translate(m_origin - camera_pos)) per draw.
std::vector<glm::mat4> m_sleeper_local_transforms;
public:
using dynamics_sequence = std::deque<TDynamicObject *>;
using event_sequence = std::vector<std::pair<std::string, basic_event *> >;
dynamics_sequence Dynamics;
event_sequence
m_events0all,
m_events1all,
m_events2all,
m_events0,
m_events1,
m_events2;
bool m_events { false }; // Ra: flaga informująca o obecności eventów
std::pair<std::string, TMemCell *> m_friction { "", nullptr };
int iNextDirection = 0; // 0:Point1, 1:Point2, 3:do odchylonego na zwrotnicy
int iPrevDirection = 0; // domyślnie wirtualne odcinki dołączamy stroną od Point1
TTrackType eType = tt_Normal; // domyślnie zwykły
int iCategoryFlag = 1; // 0x100 - usuwanie pojazów // 1-tor, 2-droga, 4-rzeka, 8-samolot?
float fTrackWidth = 1.435f; // szerokość w punkcie 1 // rozstaw toru, szerokość nawierzchni
float fTrackWidth2 = 0.0f; // szerokość w punkcie 2 (głównie drogi i rzeki)
float fFriction = 0.15f; // współczynnik tarcia
float fSoundDistance = -1.0f;
int iQualityFlag = 20;
int iDamageFlag = 0;
TEnvironmentType eEnvironment = e_flat; // dźwięk i oświetlenie
int iAction = 0; // czy modyfikowany eventami (specjalna obsługa przy skanowaniu)
float fOverhead = -1.0; // można normalnie pobierać prąd (0 dla jazdy bezprądowej po danym odcinku, >0-z opuszczonym i ograniczeniem prędkości)
private:
double fVelocity = -1.0; // ograniczenie prędkości // prędkość dla AI (powyżej rośnie prawdopowobieństwo wykolejenia)
public:
// McZapkie-100502:
// double fTrackLength = 100.0; // długość z wpisu, nigdzie nie używana
double fRadius = 0.0; // promień, dla zwrotnicy kopiowany z tabeli
bool ScannedFlag = false; // McZapkie: do zaznaczania kolorem torów skanowanych przez AI
TGroundNode *nFouling[ 2 ] = { nullptr, nullptr }; // współrzędne ukresu albo oporu kozła
explicit TTrack( scene::node_data const &Nodedata );
virtual ~TTrack();
void Init();
static bool sort_by_material( TTrack const *Left, TTrack const *Right );
static TTrack * Create400m(int what, double dx);
TTrack * NullCreate(int dir);
inline bool IsEmpty() {
return Dynamics.empty(); };
void ConnectPrevPrev(TTrack *pNewPrev, int typ);
void ConnectPrevNext(TTrack *pNewPrev, int typ);
void ConnectNextPrev(TTrack *pNewNext, int typ);
void ConnectNextNext(TTrack *pNewNext, int typ);
material_handle copy_adjacent_trackbed_material( TTrack const *Exclude = nullptr );
inline double Length() const {
return Segment->GetLength(); };
inline std::shared_ptr<TSegment> CurrentSegment() const {
return Segment; };
inline TTrack *CurrentNext() const {
return trNext; };
inline TTrack *CurrentPrev() const {
return trPrev; };
TTrack *Connected(int s, double &d) const;
bool SetConnections(int i);
bool Switch(int i, float const t = -1.f, float const d = -1.f);
bool SwitchForced(int i, TDynamicObject *o);
int CrossSegment(int from, int into);
inline int GetSwitchState() {
return SwitchExtension ? SwitchExtension->CurrentIndex : -1; };
// returns number of different routes possible to take from given point
// TODO: specify entry point, number of routes for switches can vary
inline
int
RouteCount() const {
return SwitchExtension != nullptr ? SwitchExtension->iRoads - 1 : 1; }
// picks one of the routes through a crossroads for a driver heading for it. the routes are numbered from 1
int RouteDraw() const;
void Load(cParser *parser, glm::dvec3 const &pOrigin);
void init_segments( bool const Initial );
// where the inner rails of the two paths of a switch cross, found from their gauge lines behind the blades
struct switch_frog {
bool valid { false };
int side[ 2 ] {}; // rail profile of the crossing rail of each path, 1 right, -1 left
double at[ 2 ] {}; // distance of the crossing along each path
double blades[ 2 ] {}; // distance the blades take along each path
double angle { 0.0 };
};
switch_frog frog() const;
// where a rail of this track crosses a rail of another one, found from their gauge lines
struct rail_crossing {
TTrack *track { nullptr };
int path { 0 };
int side { 0 }; // rail profile of the crossing rail, 1 right, -1 left
double at { 0.0 }; // distance of the crossing along the path, past the ends where the track goes on
double angle { 0.0 };
double into { 0.0 }; // the path direction against the gauge normal of the other rail, above zero: going into the other track
double facing { 0.0 }; // the gauge normals of both rails against each other, below zero: an acute frog
bool nose { false }; // at an acute frog the rail goes on as the nose rail, the other one as the rail beside it
int otherpath { 0 };
int otherside { 0 }; // rail profile of the other rail, 1 right, -1 left
double otherat { 0.0 }; // distance of the crossing along the other path
bool aligned { true }; // both paths run the same way at the crossing
TTrack *owner { nullptr };
};
std::vector<rail_crossing> rail_crossings( bool const Joined = true );
// the size of the rail profile, out from the gauge face: positive outwards, the side of the head away from the track
struct rail_size {
double head { 0.0735 }; // how far the head reaches out
double height { 0.172 };
double low { -0.0385 }; // the reach of the profile inwards
double high { 0.1115 }; // the reach of the profile outwards
bool grooved { false };
double groove { 0.0 };
double lip { 0.0 };
double rim { 0.0 };
double crown { 0.0 };
double liptop { 0.0 };
double crest { 0.0 };
double tread { 0.0735 };
double ledge { 0.0 };
double web { 0.0365 };
double neck { -0.0467 };
};
rail_size rail_dimensions() const;
// a check rail beside a rail, how far its ends turn away from the running rail
struct check_rail {
double from { 0.0 };
double to { 0.0 };
double flarefrom { 0.0 };
double flareto { 0.0 };
double frombend { 0.0 };
double tobend { 0.0 };
};
using check_rail_set = std::array<std::array<std::vector<check_rail>, 2>, 2>; // path, right side
// the check rails beside the rails of each path, kept clear of the blades and the rails of other paths running inside them
check_rail_set check_rails( std::vector<rail_crossing> const &Crossings );
// a rail broken where another one crosses it: the part coming from below ends at end, the part going on starts at start
struct rail_cut {
double at { 0.0 };
double end { 0.0 };
double start { 0.0 };
std::vector<glm::dvec2> endoffsets, endextents, startoffsets, startextents;
std::vector<glm::dvec2> endrolled, startrolled; // how far out from the gauge line the wheels roll on the head, of the part coming from below and of the part going on
glm::dvec2 endmiter { 0.0 };
glm::dvec2 startmiter { 0.0 };
double endbend { 0.0 };
double startbend { 0.0 };
std::vector<glm::dvec2> endinner, startinner;
bool endcap { true };
bool startcap { true };
};
struct rail_plan {
std::vector<rail_cut> cuts;
};
// guard rails of a crossing at a wide angle: the rail profile laid inside the running rail across the flangeway, broken like the rails
struct guard_rail {
double from { 0.0 };
double to { 0.0 };
rail_plan plan;
bool flarefrom { true };
bool flareto { true };
glm::dvec2 frommiter { 0.0 };
glm::dvec2 tomiter { 0.0 };
};
struct rail_band {
double at { 0.0 };
double into { 0.0 };
double facing { 0.0 };
double from { 0.0 };
double to { 0.0 };
bool whole { true };
};
struct rail_fill {
double from { 0.0 };
double to { 0.0 };
std::vector<glm::dvec2> inner, outer;
bool capfrom { false };
bool capto { false };
double lift { 0.0 };
bool web { false };
};
struct rail_tread {
double from { 0.0 };
double to { 0.0 };
material_handle material { 0 };
int anchor { 0 };
std::vector<glm::dvec2> edge;
std::vector<glm::dvec2> gauge;
bool below { false };
};
struct rail_layout {
rail_plan plans[ 2 ][ 2 ]; // path, right side
std::vector<rail_band> bands[ 2 ][ 2 ];
std::vector<rail_fill> fills[ 2 ][ 2 ];
std::vector<glm::dvec2> blocks[ 2 ][ 2 ];
std::vector<rail_tread> treads[ 2 ][ 2 ];
std::vector<guard_rail> guards[ 2 ][ 2 ];
std::vector<glm::dvec2> wingends[ 2 ][ 2 ]; // ends of the wing rails of other rails running along each rail, and which way they run there
check_rail_set checks;
std::vector<TTrack *> crossed; // tracks whose rails cross the rails of this one
};
rail_layout plan_rails( bool const Crossings );
void update_location();
bool AssignEvents();
bool AssignForcedEvents(basic_event *NewEventPlus, basic_event *NewEventMinus);
void QueueEvents( event_sequence const &Events, TDynamicObject const *Owner );
void QueueEvents( event_sequence const &Events, TDynamicObject const *Owner, double const Delaylimit );
bool CheckDynamicObject(TDynamicObject *Dynamic);
bool AddDynamicObject(TDynamicObject *Dynamic);
bool RemoveDynamicObject(TDynamicObject *Dynamic);
// set origin point
void
origin( glm::dvec3 Origin ) {
m_origin = Origin; }
// retrieves list of the track's end points
std::vector<glm::dvec3>
endpoints() const;
gfx::geometrybank_handle extra_map_geometry; // handle for map highlighting
TTrack *Next(TTrack *visitor);
double ActiveLength();
void create_geometry( gfx::geometrybank_handle const &Bank ); // wypełnianie VBO
void rebuild_geometry( gfx::geometrybank_handle const &Bank );
void create_map_geometry(std::vector<gfx::basic_vertex> &Bank, const gfx::geometrybank_handle Extra);
void get_map_active_paths(map_colored_paths &handles);
void get_map_paths_for_state(map_colored_paths &handles, int state);
void get_map_future_paths(map_colored_paths &handles);
glm::vec3 get_nearest_point(const glm::dvec3 &point) const;
void RenderDynSounds(); // odtwarzanie dźwięków pojazdów jest niezależne od ich wyświetlania
void RaOwnerSet( scene::basic_cell *o ) {
if( SwitchExtension ) { SwitchExtension->pOwner = o; } };
bool InMovement(); // czy w trakcie animacji?
void RaAssign( TAnimModel *am, basic_event *done, basic_event *joined );
void RaAnimListAdd(TTrack *t);
TTrack * RaAnimate();
void RadioStop();
void AxleCounter(int i, TDynamicObject *o) {
for (TIsolated *iso : Isolated)
iso->Modify(i, o); }; // dodanie lub odjęcie osi
std::string RemoteIsolatedName();
void AddIsolated(TIsolated *iso) {
Isolated.push_back(iso);
}
double WidthTotal();
bool IsGroupable();
int TestPoint(const glm::dvec3 *Point);
void MovedUp1(float const dh);
void VelocitySet(float v);
double VelocityGet();
float Friction() const;
void ConnectionsLog();
bool DoubleSlip() const;
static void fetch_default_profiles();
std::string tooltip() const override;
private:
// types
using profiles_array = std::vector<gfx::vertex_array>;
using profiles_map = std::unordered_map<std::string, int>;
// methods
// radius() subclass details, calculates node's bounding radius
float radius_();
// serialize() subclass details, sends content of the subclass to provided stream
void serialize_( std::ostream &Output ) const;
// deserialize() subclass details, restores content of the subclass from provided stream
void deserialize_( std::istream &Input );
// export() subclass details, sends basic content of the class in legacy (text) format to provided stream
void export_as_text_( std::ostream &Output ) const;
// locates specified profile in the profile database, potentially loading it from a file
static std::pair<std::string, int> fetch_track_rail_profile( std::string const &Profile );
// loads content of specified file and converts it into a vertex array
static gfx::vertex_array deserialize_profile( std::string const &Profile );
// provides direct access to vertex data of specified profile
static gfx::vertex_array const & track_rail_profile( int const Profile );
// returns texture length for specified material
float texture_length( material_handle const Material );
// creates profile for a part of current path
void create_switch_trackbed( gfx::vertex_array &Output );
void create_track_rail_profile( gfx::vertex_array &Right, gfx::vertex_array &Left, gfx::vertex_array const *Shape = nullptr );
void create_track_blade_profile( gfx::vertex_array &Right, gfx::vertex_array &Left );
void profile_rolls( float &Roll1, float &Roll2 ) const;
void share_joints();
void create_track_bed_profile( gfx::vertex_array &Output, TTrack const *Previous, TTrack const *Next );
void create_road_profile( gfx::vertex_array &Output, bool const Forcetransition = false );
void create_road_side_profile( gfx::vertex_array &Right, gfx::vertex_array &Left, gfx::vertex_array const &Road, bool const Forcetransition = false );
/// <summary>
/// resolves the sleeper model/skin via the model and material managers, and fills
/// m_sleeper_local_transforms by walking the active segment(s) at m_sleeper_frequency.
/// Safe to call multiple times; clears any previously cached transforms first.
/// </summary>
void build_sleeper_transforms();
struct rail_drawing {
gfx::geometrybank_handle bank;
rail_size size;
float halfwidth { 0.f };
gfx::vertex_array checkshapes[ 2 ];
gfx::vertex_array plates[ 2 ];
gfx::vertex_array fillers[ 2 ];
float platetexture { 0.f };
};
rail_drawing make_rail_drawing( gfx::geometrybank_handle const &Bank );
// a rail along a path from a distance on, in parts where other rails cross it, and the check rails beside it. false: no crossing, the rail is laid whole as before
bool lay_rail( rail_layout const &Layout, rail_drawing const &Drawing, int const Path, gfx::vertex_array const &Profile, int const Side, float const Texturelength, double const From, bool const Openstart, bool const Openend, geometryhandle_sequence &Geometry, geometryhandle_sequence &Cuts );
int blade_side( int const Path ) const;
material_handle rail_material( int const Path ) const;
glm::vec2 tread_band() const;
material_handle shared_tread( int const Path, TTrack const &Other, int const Otherpath ) const;
void loft_blade( int const Path, gfx::vertex_array const &Rail, gfx::vertex_array const &Blade, float const Texturelength, gfx::vertex_array &Vertices ) const;
// members
static profiles_array m_profiles; // shared database of path element profiles
static profiles_map m_profilesmap;
};
// collection of virtual tracks and roads present in the scene
class path_table : public basic_table<TTrack> {
public:
~path_table();
// legacy method, initializes tracks after deserialization from scenario file
void
InitTracks();
// legacy method, sends list of occupied paths over network
void
TrackBusyList() const;
// legacy method, sends list of occupied path sections over network
void
IsolatedBusyList() const;
// legacy method, sends state of specified path section over network
void
IsolatedBusy( std::string const &Name ) const;
};
//---------------------------------------------------------------------------