Added tracks connection logic

+Added connectTracks scenery parsing function that links Track objects together in the scenery model, including support for one‑to‑many connections (for switches)
This commit is contained in:
izawartka 2025-07-11 01:06:02 +02:00
parent 6ce9d75f28
commit db45de37b9
5 changed files with 96 additions and 2 deletions

View File

@ -23,6 +23,7 @@ const Constants = {
attachSignsMaxDistanceX: 0.2,
attachSignsGridSize: 10,
logAttachedSigns: false,
connectTracks: true,
},
warnings: {
all: false, // enable all warnings
@ -51,7 +52,7 @@ const Constants = {
attachSignsOutOfBounds: true,
signalElemsUnknownSign: true,
signalElemsUnknownSignText: true,
connectTracksFailed: true,
},
errors: {
invalidSceneryInfo: true

View File

@ -0,0 +1,70 @@
import SceneryParserLog from "./scenery-parser-log";
import TrackConnection, { TrackConnectionType } from "./track-connection";
export function connectTracks(scenery) {
const tracks = scenery.objects['tracks'] || {};
Object.values(tracks).forEach(track => {
connectTrack(scenery, track, false);
connectTrack(scenery, track, true);
});
}
function connectTrack(scenery, track, isPrev) {
const vNext = isPrev ? track.previd : track.nextid;
if (!vNext) return;
const vNextTrackId = scenery.getTrackIdByAlias(vNext);
const vNextTrack = scenery.getObject('tracks', vNextTrackId);
if (!vNextTrack) {
SceneryParserLog.warn('connectTracks', `Track ${track.id} has non-existing ${isPrev ? 'previous' : 'next'} track: ${isPrev ? track.previd : track.nextid} (${vNextTrackId})`);
return;
}
const vNextTrackNextId = scenery.getTrackIdByAlias(vNextTrack.nextid);
const vNextTrackPrevId = scenery.getTrackIdByAlias(vNextTrack.previd);
const isConnectedAsNext = vNextTrackPrevId === track.id || track.aliases.includes(vNextTrackPrevId);
const isConnectedAsPrev = vNextTrackNextId === track.id || track.aliases.includes(vNextTrackNextId);
let otherConnectionType = isConnectedAsNext ? TrackConnectionType.START : TrackConnectionType.END;
let addReverseConnection = false;
if (!isConnectedAsNext && !isConnectedAsPrev) {
// switch connection
if(!track.switch) {
SceneryParserLog.warn('connectTracksFailed', `${isPrev ? 'Previous' : 'Next'} track ${vNextTrackId} is not connected back to track ${track.id} (${track.previd} / ${track.nextid}). Cannot connect tracks`);
return;
}
const switchId = track.switch.id;
const isConnectedAsSwitchNext = vNextTrackNextId.slice(0, -1) === switchId;
const isConnectedAsSwitchPrev = vNextTrackPrevId.slice(0, -1) === switchId;
if(!isConnectedAsSwitchNext && !isConnectedAsSwitchPrev) {
SceneryParserLog.warn('connectTracksFailed', `${isPrev ? 'Previous' : 'Next'} track ${vNextTrackId} is not connected back to switch track ${track.id} (${track.previd} / ${track.nextid}). Cannot connect tracks`);
return;
}
otherConnectionType = isConnectedAsSwitchNext ? TrackConnectionType.START : TrackConnectionType.END;
addReverseConnection = true;
}
const mainConnectionType = isPrev ? TrackConnectionType.START : TrackConnectionType.END;
track.connections.push(new TrackConnection(
track,
vNextTrack,
mainConnectionType,
otherConnectionType
));
if(!addReverseConnection) return;
vNextTrack.connections.push(new TrackConnection(
vNextTrack,
track,
otherConnectionType,
mainConnectionType
));
}

View File

@ -19,6 +19,7 @@ import NEVP from './track-objects/nevp';
import Derailer from './track-objects/derailer';
import SpawnPoint from './track-objects/spawn-point';
import { attachSigns } from './attach-signs';
import { connectTracks } from './connect-tracks';
/*
TODO: add support for WorldRotation and WorldTranslation
@ -44,8 +45,9 @@ export default class SceneryParser {
scenery.applyObjects();
if(Constants.parser.resolveElectrification) ElectrificationResolver.resolveScenery(scenery);
if(Constants.parser.runTracksConnectionTest) tracksConnectionTest(scenery);
if(Constants.parser.connectTracks) connectTracks(scenery);
if(Constants.parser.resolveElectrification) ElectrificationResolver.resolveScenery(scenery);
if(Constants.parser.attachSigns) attachSigns(scenery);
if(Constants.parser.logSceneryAfterFinished) console.log(scenery);

View File

@ -0,0 +1,20 @@
export const TrackConnectionType = {
END: 0,
START: 1,
}
export default class TrackConnection {
tracks;
otherTrack;
type;
otherType;
constructor(track, otherTrack, type, otherType) {
Object.assign(this, {
track,
otherTrack,
type,
otherType
});
}
}

View File

@ -20,6 +20,7 @@ export default class Track extends SceneryObject {
switch = null;
electrificationStatus = ElectrificationStatus.NOT_CHECKED;
hasNEVP = false;
connections = [];
constructor(id, pos, rot, len, r, nextid, previd, id_station, start_slope, end_slope, id_isolation, prefab_name, maxspeed, derailspeed) {
super(id, pos, rot);