Change switch prefab definition format

This commit is contained in:
dominik-korsa 2025-07-12 00:22:38 +02:00
parent 745d31e44a
commit db273d2420
No known key found for this signature in database
GPG Key ID: 5A24D76EE0A30974
6 changed files with 405 additions and 719 deletions

5
.gitignore vendored
View File

@ -22,4 +22,7 @@ npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
public/sceneries/* public/sceneries/*
# IDEs
.idea

View File

@ -8,8 +8,6 @@ const Constants = {
forcePointerEvents: false forcePointerEvents: false
}, },
parser: { parser: {
forceAutoSwitches: false,
logNewAutoSwitches: true,
logSceneryAfterFinished: true, logSceneryAfterFinished: true,
sceneryInfoVersion: 29, sceneryInfoVersion: 29,
alwaysShowLogDialog: false, alwaysShowLogDialog: false,
@ -35,9 +33,10 @@ const Constants = {
trackAliasAlreadyExists: true, trackAliasAlreadyExists: true,
trackAliasNoTrack: true, trackAliasNoTrack: true,
switchUndefinedModel: true, switchUndefinedModel: true,
switchAutoDefFailed: true,
switchInvalidDataFormat: true, switchInvalidDataFormat: true,
switchNoModel: true, switchNoModel: true,
switchMissingTrackId: true,
switchInvalidInternalConnection: true,
signalBoxUndefinedPrefabName: true, signalBoxUndefinedPrefabName: true,
invalidSceneryInfoVersion: true, invalidSceneryInfoVersion: true,
signUndefinedPrefabName: true, signUndefinedPrefabName: true,
@ -175,4 +174,4 @@ const Constants = {
} }
}; };
export default Constants; export default Constants;

View File

@ -1,555 +1,110 @@
import Vector3 from "../vector3"; import SwitchPrefab from "../switch-descriptions/switch-prefab";
const DefinedSwitches = { const DefinedSwitches = {
"Crossing": [ // "Crossing": [
0, // 0,
0, // 0,
[0,1], // [0,1],
new Vector3(-0.919, 0, -16.59), // new Vector3(-0.919, 0, -16.59),
new Vector3(0.919, 0, -16.59), // new Vector3(0.919, 0, -16.59),
new Vector3(0.919, 0, 16.59), // new Vector3(0.919, 0, 16.59),
new Vector3(-0.919, 0, 16.59) // new Vector3(-0.919, 0, 16.59)
], // ],
"Crossing4.444": [ // "Crossing4.444": [
0, // 0,
0, // 0,
[0,1], // [0,1],
new Vector3(-1.104, 0, -9.939), // new Vector3(-1.104, 0, -9.939),
new Vector3(1.104, 0, -9.939), // new Vector3(1.104, 0, -9.939),
new Vector3(1.104, 0, 9.939), // new Vector3(1.104, 0, 9.939),
new Vector3(-1.104, 0, 9.939) // new Vector3(-1.104, 0, 9.939)
], // ],
"Rz 60E1-300-1_9 R": [ // Rkp 60E1-190-1_9 ab
0, // Rkp 60E1-190-1_9 ba
-300, // Rkpd 60E1-190-1_9
[0, 0, 3, 4, 2, 1], "Rld 60E1-1200_600-1_15 L": SwitchPrefab.fork(600.0, -1200.0, 39.95566, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-1200_600-1_15 R": SwitchPrefab.fork(-600.0, 1200.0, 39.95566, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-1200_900-1_18.5 L": SwitchPrefab.fork(900.0, -1200.0, 48.61317, 0.0),
new Vector3(0, 0, 33.231), "Rld 60E1-1200_900-1_18.5 R": SwitchPrefab.fork(-900.0, 1200.0, 48.61317, 0.0),
new Vector3(1.835, 0, 33.129) "Rld 60E1-1800_300-1_9 L": SwitchPrefab.fork(300.0, -1800.0, 33.23108, 0.0),
], "Rld 60E1-1800_300-1_9 R": SwitchPrefab.fork(-300.0, 1800.0, 33.23108, 0.0),
"Rz 60E1-300-1_9 L": [ "Rld 60E1-1800_600-1_14 L": SwitchPrefab.fork(600.0, -1800.0, 42.80262, 0.0),
0, "Rld 60E1-1800_600-1_14 R": SwitchPrefab.fork(-600.0, 1800.0, 42.80262, 0.0),
300, "Rld 60E1-1800_900-1_18.5 L": SwitchPrefab.fork(900.0, -1800.0, 48.61317, 0.0),
[0, 0, 3, 4, 2, 1], "Rld 60E1-1800_900-1_18.5 R": SwitchPrefab.fork(-900.0, 1800.0, 48.61317, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-2500_1200-1_22 L": SwitchPrefab.fork(1200.0, -2500.0, 54.51731, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-2500_1200-1_22 R": SwitchPrefab.fork(-1200.0, 2500.0, 54.51731, 0.0),
new Vector3(0, 0, 33.231), "Rld 60E1-2500_250-1_8.5 L": SwitchPrefab.fork(250.0, -2500.0, 29.31069, 0.0),
new Vector3(-1.835, 0, 33.129) "Rld 60E1-2500_250-1_8.5 R": SwitchPrefab.fork(-250.0, 2500.0, 29.31069, 0.0),
], "Rld 60E1-2500_400-1_10.5 L": SwitchPrefab.fork(400.0, -2500.0, 38.00925, 0.0),
"Rz 60E1-190-1_9 R": [ "Rld 60E1-2500_400-1_10.5 R": SwitchPrefab.fork(-400.0, 2500.0, 38.00925, 0.0),
0, "Rld 60E1-2500_600-1_14 L": SwitchPrefab.fork(600.0, -2500.0, 42.80262, 0.0),
-190, "Rld 60E1-2500_600-1_14 R": SwitchPrefab.fork(-600.0, 2500.0, 42.80262, 0.0),
[0, 0, 5, 6, 3, 4], "Rld 60E1-2500_900-1_17 L": SwitchPrefab.fork(900.0, -2500.0, 52.14928, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-2500_900-1_17 R": SwitchPrefab.fork(-900.0, 2500.0, 52.14928, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-600_300-1_9 L": SwitchPrefab.fork(300.0, -600.0, 29.92537, 0.0),
new Vector3(0, 0, 27.139), "Rld 60E1-600_300-1_9 R": SwitchPrefab.fork(-300.0, 600.0, 29.92537, 0.0),
new Vector3(1.835, 0, 27.037) "Rld 60E1-650_450-1_15 L": SwitchPrefab.fork(450.0, -650.0, 29.96674, 0.0),
], "Rld 60E1-650_450-1_15 R": SwitchPrefab.fork(-450.0, 650.0, 29.96674, 0.0),
"Rz 60E1-190-1_9 L": [ "Rld 60E1-700_190-1_7.5 L": SwitchPrefab.fork(190.0, -700.0, 25.22173, 0.0),
0, "Rld 60E1-700_190-1_7.5 R": SwitchPrefab.fork(-190.0, 700.0, 25.22173, 0.0),
190, "Rld 60E1-700_300-1_10 L": SwitchPrefab.fork(300.0, -700.0, 29.38637, 0.0),
[0, 0, 5, 6, 3, 4], "Rld 60E1-700_300-1_10 R": SwitchPrefab.fork(-300.0, 700.0, 29.38637, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-700_500-1_14 L": SwitchPrefab.fork(500.0, -700.0, 35.66885, 0.0),
new Vector3(0, 0, 0), "Rld 60E1-700_500-1_14 R": SwitchPrefab.fork(-500.0, 700.0, 35.66885, 0.0),
new Vector3(0, 0, 27.139), "Rld 60E1-900_300-1_9 L": SwitchPrefab.fork(300.0, -900.0, 33.23108, 0.0),
new Vector3(-1.835, 0, 27.037) "Rld 60E1-900_300-1_9 R": SwitchPrefab.fork(-300.0, 900.0, 33.23108, 0.0),
], "Rld 60E1-900_450-1_12 L": SwitchPrefab.fork(450.0, -900.0, 37.43512, 0.0),
"Rz 60E1-500-1_12 R": [ "Rld 60E1-900_450-1_12 R": SwitchPrefab.fork(-450.0, 900.0, 37.43512, 0.0),
0, "Rld 60E1-900_600-1_15 L": SwitchPrefab.fork(600.0, -900.0, 39.95566, 0.0),
-500, "Rld 60E1-900_600-1_15 R": SwitchPrefab.fork(-600.0, 900.0, 39.95566, 0.0),
[0, 0, 3, 4], "Rlds 60E1-1000-1000-1_23": SwitchPrefab.fork(1000.0, -1000.0, 43.45773, 0.0),
new Vector3(0, 0, 0), "Rlds 60E1-190-190-1_9": SwitchPrefab.fork(190.0, -190.0, 21.23, 0.0),
new Vector3(0, 0, 0), "Rlds 60E1-600-600-1_18.5": SwitchPrefab.fork(599.9205, -600.0, 33.22262, 0.0),
new Vector3(0, 0, 41.595), "Rlj 60E1-1200_300-1_7 L": SwitchPrefab.fork(300.0, 1200.0, 42.64069, 0.0),
new Vector3(1.727, 0, 41.523) "Rlj 60E1-1200_300-1_7 R": SwitchPrefab.fork(-300.0, -1200.0, 42.64069, 0.0),
], "Rlj 60E1-1200_600-1_9 L": SwitchPrefab.fork(600.0, 1200.0, 68.0, 0.0),
"Rz 60E1-500-1_12 L": [ "Rlj 60E1-1200_600-1_9 R": SwitchPrefab.fork(-600.0, -1200.0, 68.0, 0.0),
0, "Rlj 60E1-1500_450-1_9 L": SwitchPrefab.fork(450.0, 1500.0, 49.84663, 0.0),
500, "Rlj 60E1-1500_450-1_9 R": SwitchPrefab.fork(-450.0, -1500.0, 49.84663, 0.0),
[0, 0, 3, 4], "Rlj 60E1-1800_300-1_7.5 L": SwitchPrefab.fork(300.0, 1800.0, 39.0, 0.0),
new Vector3(0, 0, 0), "Rlj 60E1-1800_300-1_7.5 R": SwitchPrefab.fork(-300.0, -1800.0, 39.0, 0.0),
new Vector3(0, 0, 0), "Rlj 60E1-1800_450-1_9 L": SwitchPrefab.fork(450.0, 1800.0, 49.84663, 0.0),
new Vector3(0, 0, 41.595), "Rlj 60E1-1800_450-1_9 R": SwitchPrefab.fork(-450.0, -1800.0, 49.84663, 0.0),
new Vector3(-1.727, 0, 41.523) "Rlj 60E1-1800_600-1_10 L": SwitchPrefab.fork(599.48096, 1800.0, 59.85075, 0.0),
], "Rlj 60E1-1800_600-1_10 R": SwitchPrefab.fork(-599.48096, -1800.0, 59.85075, 0.0),
"Rkpd 60E1-190-1_9": [ "Rlj 60E1-600_300-1_6 L": SwitchPrefab.fork(300.0, 600.0, 48.0, 0.0),
0, "Rlj 60E1-600_300-1_6 R": SwitchPrefab.fork(-300.0, -600.0, 48.0, 0.0),
0, "Rlj 60E1-650_190-1_20 L": SwitchPrefab.fork(190.0, 650.0, 32.47971, 0.0),
[0, 1, 2, 3], "Rlj 60E1-650_190-1_20 R": SwitchPrefab.fork(-190.0, -650.0, 32.47971, 0.0),
new Vector3(-0.918, 0, -16.557), "Rlj 60E1-750_190-1_6 L": SwitchPrefab.fork(190.0, 750.0, 31.44976, 0.0),
new Vector3(0.917, 0, -16.557), "Rlj 60E1-750_190-1_6 R": SwitchPrefab.fork(-190.0, -750.0, 31.44976, 0.0),
new Vector3(0.917, 0, 16.557), "Rlj 60E1-800_250-1_6.5 L": SwitchPrefab.fork(250.0, 800.0, 38.23661, 0.0),
new Vector3(-0.917, 0, 16.557) "Rlj 60E1-800_250-1_6.5 R": SwitchPrefab.fork(-250.0, -800.0, 38.23661, 0.0),
], "Rlj 60E1-900_300-1_7.5 L": SwitchPrefab.fork(300.0, 900.0, 39.82378, 0.0),
"Rkp 60E1-190-1_9 ab": [ "Rlj 60E1-900_300-1_7.5 R": SwitchPrefab.fork(-300.0, -900.0, 39.82378, 0.0),
0, "Rlj 60E1-900_300-1_9 L": SwitchPrefab.fork(300.0, 900.0, 49.84663, 0.0),
0, "Rlj 60E1-900_300-1_9 R": SwitchPrefab.fork(-300.0, -900.0, 49.84663, 0.0),
[0, 1, 2, 3], "Rlj 60E1-900_450-1_7.5 L": SwitchPrefab.fork(450.0, 900.0, 59.0, 0.0),
new Vector3(-0.918, 0, -16.557), "Rlj 60E1-900_450-1_7.5 R": SwitchPrefab.fork(-450.0, -900.0, 59.0, 0.0),
new Vector3(0.917, 0, -16.556), "Rz 60E1-1200-1_18.5 L": SwitchPrefab.fork(1200.0, 0.0, 64.81756, 0.0),
new Vector3(0.917, 0, 16.558), "Rz 60E1-1200-1_18.5 R": SwitchPrefab.fork(-1200.0, 0.0, 64.81756, 0.0),
new Vector3(-0.921, 0, 16.558) "Rz 60E1-190-1_7.5 L": SwitchPrefab.fork(190.0, 0.0, 25.221731, 0.0),
], "Rz 60E1-190-1_7.5 R": SwitchPrefab.fork(-190.0, 0.0, 25.221731, 0.0),
"Rkp 60E1-190-1_9 ba": [ "Rz 60E1-190-1_9 L": SwitchPrefab.fork(0.0, 190.0, 21.046352, 6.0923653),
0, "Rz 60E1-190-1_9 R": SwitchPrefab.fork(0.0, -190.0, 21.046352, 6.0923653),
0, "Rz 60E1-205-1_9 L": SwitchPrefab.fork(205.0, 0.0, 22.707907, 5.42 /* added manually */),
[0, 1, 2, 3], "Rz 60E1-205-1_9 R": SwitchPrefab.fork(-205.0, 0.0, 22.707907, 5.42 /* added manually */),
new Vector3(-0.918, 0, -16.557), "Rz 60E1-2500-1_26.5 L": SwitchPrefab.fork(2500.0, 0.0, 94.30607, 0.0),
new Vector3(0.917, 0, -16.556), "Rz 60E1-2500-1_26.5 R": SwitchPrefab.fork(-2500.0, 0.0, 94.30607, 0.0),
new Vector3(0.917, 0, 16.558), "Rz 60E1-265-1_10 L": SwitchPrefab.fork(0.0, 265.0, 26.434078, 4.75 /* added manually */),
new Vector3(-0.921, 0, 16.558) "Rz 60E1-265-1_10 R": SwitchPrefab.fork(0.0, -265.0, 26.434078, 4.75 /* added manually */),
], "Rz 60E1-300-1_9 L": SwitchPrefab.fork(300.0, 0.0, 33.231083, 0.0),
"Rz 60E1-265-1_10 R": [ "Rz 60E1-300-1_9 R": SwitchPrefab.fork(-300.0, 0.0, 33.231083, 0.0),
0, "Rz 60E1-500-1_12 L": SwitchPrefab.fork(500.0, 0.0, 41.59458, 0.0),
-265, "Rz 60E1-500-1_12 R": SwitchPrefab.fork(-500.0, 0.0, 41.59458, 0.0),
[0, 0, 5, 6], "Rz 60E1-760-1_14 L": SwitchPrefab.fork(760.0, 0.0, 54.21665, 0.0),
new Vector3(0, 0, 0), "Rz 60E1-760-1_14 R": SwitchPrefab.fork(-760.0, 0.0, 54.21665, 0.0),
new Vector3(0, 0, 0), };
new Vector3(0, 0, 31.181),
new Vector3(1.789, 0, 31.094)
],
"Rz 60E1-265-1_10 L": [
0,
265,
[0, 0, 5, 6],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 31.181),
new Vector3(-1.789, 0, 31.094)
],
"Rz 60E1-760-1_14 R": [
0,
-760,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 54.217),
new Vector3(1.931, 0, 54.148)
],
"Rz 60E1-760-1_14 L": [
0,
760,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 54.217),
new Vector3(-1.931, 0, 54.148)
],
"Rz 60E1-1200-1_18.5 R": [
0,
-1200,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 64.817),
new Vector3(1.749, 0, 64.77)
],
"Rz 60E1-1200-1_18.5 L": [
0,
1200,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 64.817),
new Vector3(-1.75, 0, 64.77)
],
"Rld 60E1-700_300-1_10 R": [
700,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.616, 0, 29.377),
new Vector3(1.438, 0, 29.339)
],
"Rld 60E1-700_300-1_10 L": [
-700,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.616, 0, 29.377),
new Vector3(-1.438, 0, 29.339)
],
"Rld 60E1-1800_300-1_9 R": [
1800,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.307, 0, 33.228),
new Vector3(1.838, 0, 33.163)
],
"Rld 60E1-1800_300-1_9 L": [
-1800,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.307, 0, 33.228),
new Vector3(-1.838, 0, 33.163)
],
"Rld 60E1-2500_1200-1_22 R": [
2500,
-1200,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.586, 0, 54.51),
new Vector3(1.238, 0, 54.499)
],
"Rld 60E1-2500_1200-1_22 L": [
-2500,
1200,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.586, 0, 54.51),
new Vector3(-1.238, 0, 54.499)
],
"Rld 60E1-650_450-1_15 R": [
650,
-450,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.691, 0, 29.956),
new Vector3(0.997, 0, 29.945)
],
"Rld 60E1-650_450-1_15 L": [
-650,
450,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.691, 0, 29.956),
new Vector3(-0.997, 0, 29.945)
],
"Rld 60E1-600_300-1_9 R": [
600,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.749, 0, 29.918),
new Vector3(1.49, 0, 29.881)
],
"Rld 60E1-600_300-1_9 L": [
-600,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.749, 0, 29.918),
new Vector3(-1.49, 0, 29.881)
],
"Rz 60E1-205-1_9 R": [
0,
-205,
[0, 0, 5, 6],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 28.127),
new Vector3(1.853, 0, 28.025)
],
"Rz 60E1-205-1_9 L": [
0,
205,
[0, 0, 5, 6],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 28.127),
new Vector3(-1.853, 0, 28.025),
],
"Rz 60E1-190-1_7.5 R": [
0,
-190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 25.221),
new Vector3(1.667, 0, 25.111)
],
"Rz 60E1-190-1_7.5 L": [
0,
190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 25.221),
new Vector3(-1.667, 0, 25.111)
],
"Rz 60E1-2500-1_26.5 R": [
0,
-2500,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 94.306),
new Vector3(1.778, 0, 94.273)
],
"Rz 60E1-2500-1_26.5 L": [
0,
2500,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0, 0, 94.306),
new Vector3(-1.778, 0, 94.273)
],
"Rlds 60E1-600-600-1_18.5": [
-600,
600,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.92, 0, 33.206),
new Vector3(-0.92, 0, 33.206)
],
"Rlds 60E1-190-190-1_9": [
-190,
190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(1.184, 0, 21.186),
new Vector3(-1.185, 0, 21.186)
],
"Rlj 60E1-650_190-1_20 R": [
-650,
-190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.811, 0, 32.466),
new Vector3(2.77, 0, 32.332)
],
"Rlj 60E1-650_190-1_20 L": [
650,
190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.811, 0, 32.466),
new Vector3(-2.77, 0, 32.332)
],
"Rlj 60E1-1200_300-1_7 R": [
-1200,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.758, 0, 42.632),
new Vector3(3.025, 0, 42.498)
],
"Rlj 60E1-1200_300-1_7 L": [
1200,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.758, 0, 42.632),
new Vector3(-3.025, 0, 42.498)
],
"Rlj 60E1-750_190-1_6 R": [
-750,
-190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.66, 0, 31.44),
new Vector3(2.597, 0, 31.306)
],
"Rlj 60E1-750_190-1_6 L": [
750,
190,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.66, 0, 31.44),
new Vector3(-2.597, 0, 31.306)
],
"Rld 60E1-1200_600-1_15 R": [
1200,
-600,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.665, 0, 39.948),
new Vector3(1.33, 0, 39.926)
],
"Rld 60E1-1200_600-1_15 L": [
-1200,
600,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.665, 0, 39.948),
new Vector3(-1.33, 0, 39.926)
],
"Rld 60E1-1200_900-1_18.5 R": [
1200,
-900,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.984, 0, 48.6),
new Vector3(1.313, 0, 48.589)
],
"Rld 60E1-1200_900-1_18.5 L": [
-1200,
900,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.984, 0, 48.6),
new Vector3(-1.313, 0, 48.589)
],
"Rlj 60E1-900_300-1_7.5 R": [
-900,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.881, 0, 39.81),
new Vector3(2.639, 0, 39.706)
],
"Rlj 60E1-900_300-1_7.5 L": [
900,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.881, 0, 39.81),
new Vector3(-2.639, 0, 39.706)
],
"Rlj 60E1-600_300-1_6 R": [
-600,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(1.919, 0, 47.949),
new Vector3(3.832, 0, 47.795)
],
"Rlj 60E1-600_300-1_6 L": [
600,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-1.919, 0, 47.949),
new Vector3(-3.832, 0, 47.795)
],
"Rld 60E1-900_450-1_12 R": [
900,
-450,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.778, 0, 37.425),
new Vector3(1.556, 0, 37.392)
],
"Rld 60E1-900_450-1_12 L": [
-900,
450,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.778, 0, 37.425),
new Vector3(-1.556, 0, 37.392)
],
"Rld 60E1-700_500-1_14 R": [
700,
-500,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.909, 0, 35.653),
new Vector3(1.272, 0, 35.639)
],
"Rld 60E1-700_500-1_14 L": [
-700,
500,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.909, 0, 35.653),
new Vector3(-1.272, 0, 35.639)
],
"Rld 60E1-2500_400-1_10.5 R": [
2500,
-400,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.289, 0, 38.008),
new Vector3(1.805, 0, 37.952)
],
"Rld 60E1-2500_400-1_10.5 L": [
-2500,
400,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.289, 0, 38.008),
new Vector3(-1.805, 0, 37.952)
],
"Rlj 60E1-1800_300-1_7.5 R": [
-1800,
-300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.423, 0, 38.998),
new Vector3(2.531, 0, 38.89)
],
"Rlj 60E1-1800_300-1_7.5 L": [
1800,
300,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.423, 0, 38.998),
new Vector3(-2.531, 0, 38.89)
],
"Rld 60E1-1800_600-1_14 R": [
1800,
-600,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.509, 0, 42.798),
new Vector3(1.526, 0, 42.767)
],
"Rld 60E1-1800_600-1_14 L": [
-1800,
600,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.509, 0, 42.798),
new Vector3(-1.526, 0, 42.767)
],
"Rlj 60E1-1800_450-1_9 R": [
-1800,
-450,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(0.69, 0, 49.84),
new Vector3(2.758, 0, 49.744)
],
"Rlj 60E1-1800_450-1_9 L": [
1800,
450,
[0, 0, 3, 4],
new Vector3(0, 0, 0),
new Vector3(0, 0, 0),
new Vector3(-0.69, 0, 49.84),
new Vector3(-2.758, 0, 49.745)
]
}
export default DefinedSwitches; export default DefinedSwitches;

View File

@ -0,0 +1,37 @@
export const SwitchTrackConnectionEnd = {
PREV: Symbol('SwitchTrackConnectionEnd.PREV'),
NEXT: Symbol('SwitchTrackConnectionEnd.NEXT'),
};
export const SwitchTrackConnectionType = {
INTERNAL: Symbol('SwitchTrackConnectionType.INTERNAL'),
EXTERNAL: Symbol('SwitchTrackConnectionType.EXTERNAL'),
};
export default class SwitchPrefabTrack {
startPos;
endPos;
radius;
dataIndex;
connections;
constructor(startPos, endPos, radius, dataIndex, connections = []) {
Object.assign(this, {
startPos,
endPos,
radius,
dataIndex,
connections,
});
}
static point(pos, dataIndex, connections = []) {
return new SwitchPrefabTrack(
pos,
pos,
0,
dataIndex,
connections,
);
}
}

View File

@ -0,0 +1,176 @@
import Vector3 from "../vector3";
import SwitchPrefabTrack, {SwitchTrackConnectionEnd, SwitchTrackConnectionType} from "./switch-prefab-track";
import SceneryParserLog from "../scenery-parser-log";
export default class SwitchPrefab {
tracks = {};
constructor(tracks) {
Object.assign(this, {
tracks,
});
this._verifyConnections();
}
_verifyConnections() {
// TODO: Should SceneryParserLog be used here?
Object.entries(this.tracks).forEach(([internalId, track]) => {
track.connections.forEach((connection) => {
if (connection.type === SwitchTrackConnectionType.INTERNAL) {
const otherTrack = this.tracks[connection.internalId];
if (!otherTrack) {
SceneryParserLog.warn(
'switchInvalidInternalConnection',
`In a switch prefab the referenced internal track ${connection.internalId} in a connection of track ${internalId} not found`,
);
return;
}
const reverseConnection = otherTrack.connections.find(
(otherConnection) => otherConnection.type === SwitchTrackConnectionType.INTERNAL && otherConnection.internalId === internalId,
);
if (!reverseConnection) {
SceneryParserLog.warn(
'switchInvalidInternalConnection',
`In a switch prefab the internal track ${internalId} is connected to ${connection.internalId} but there is not reverse connection`,
);
return;
}
if (reverseConnection.end !== connection.otherEnd) {
SceneryParserLog.warn(
'switchInvalidInternalConnection',
`In a switch prefab the connection between tracks internal tracks ${internalId} and ${connection.internalId} has mismatched ends`,
);
}
}
});
});
}
static fork(radiusA, radiusB, curveLength, addedLength) {
const tracks = {
start: new SwitchPrefabTrack(
Vector3.zero(),
Vector3.zero(),
radiusA,
0,
[
{
type: SwitchTrackConnectionType.EXTERNAL,
end: SwitchTrackConnectionEnd.PREV,
},
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.NEXT,
otherEnd: SwitchTrackConnectionEnd.PREV,
internalId: 'curve_a',
},
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.NEXT,
otherEnd: SwitchTrackConnectionEnd.PREV,
internalId: 'curve_b',
},
],
),
...SwitchPrefab._createSwitchTracks(
radiusA,
curveLength,
addedLength,
'a',
),
...SwitchPrefab._createSwitchTracks(
radiusB,
curveLength,
addedLength,
'b',
),
};
return new SwitchPrefab(tracks);
}
static _createSwitchTracks(radius, curveLength, addedLength, side) {
let curveEnd;
let endAngle;
if (radius === 0) {
curveEnd = new Vector3(0, 0, curveLength);
endAngle = 0;
} else {
const circleCenter = new Vector3(-radius, 0, 0);
endAngle = -curveLength / radius;
const centerToEnd = Vector3.fromAngleY(endAngle + Math.sign(radius) * Math.PI / 2, Math.abs(radius));
curveEnd = circleCenter.add(centerToEnd);
}
const tracks = {
[`curve_${side}`]: new SwitchPrefabTrack(
Vector3.zero(),
curveEnd,
radius,
side === 'a' ? 1 : 2,
[
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.PREV,
otherEnd: SwitchTrackConnectionEnd.NEXT,
internalId: 'start',
},
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.NEXT,
otherEnd: SwitchTrackConnectionEnd.PREV,
internalId: addedLength > 0 ? `added_${side}` : `end_${side}`,
},
],
),
};
let end = curveEnd;
if (addedLength > 0) {
end = end.add(Vector3.fromAngleY(endAngle, addedLength));
tracks[`added_${side}`] = new SwitchPrefabTrack(
curveEnd,
end,
0,
side === 'a' ? 3 : 4,
[
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.PREV,
otherEnd: SwitchTrackConnectionEnd.NEXT,
internalId: `curve_${side}`,
},
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.NEXT,
otherEnd: SwitchTrackConnectionEnd.PREV,
internalId: `end_${side}`,
},
],
);
}
tracks[`end_${side}`] = SwitchPrefabTrack.point(
end,
addedLength > 0 ?
(side === 'a' ? 5 : 6) :
(side === 'a' ? 3 : 4),
[
{
type: SwitchTrackConnectionType.INTERNAL,
end: SwitchTrackConnectionEnd.PREV,
otherEnd: SwitchTrackConnectionEnd.NEXT,
internalId: addedLength > 0 ? `added_${side}` : `curve_${side}`,
},
{
type: SwitchTrackConnectionType.EXTERNAL,
end: SwitchTrackConnectionEnd.NEXT,
},
]
);
return tracks;
}
}

View File

@ -3,7 +3,7 @@ import SceneryObject from "./scenery-object.js";
import SceneryParserLog from "./scenery-parser-log.js"; import SceneryParserLog from "./scenery-parser-log.js";
import Vector3 from "./vector3.js"; import Vector3 from "./vector3.js";
import DefinedSwitches from "./defs/defined-switches.js"; import DefinedSwitches from "./defs/defined-switches.js";
import Constants from "../helpers/constants.js"; import {SwitchTrackConnectionEnd, SwitchTrackConnectionType} from "./switch-descriptions/switch-prefab-track";
export default class Switch extends SceneryObject { export default class Switch extends SceneryObject {
model; model;
@ -17,8 +17,7 @@ export default class Switch extends SceneryObject {
type = "Switch"; type = "Switch";
applied = false; applied = false;
track_prefab_name; track_prefab_name;
trackA; tracks = [];
trackB;
def = null; def = null;
constructor(id, model, pos, rot, data, id_isolation, id_switch, maxspeed, derailspeed, track_prefab_name) { constructor(id, model, pos, rot, data, id_isolation, id_switch, maxspeed, derailspeed, track_prefab_name) {
@ -64,188 +63,105 @@ export default class Switch extends SceneryObject {
let def = DefinedSwitches[this.bare_model] || null; let def = DefinedSwitches[this.bare_model] || null;
if(!def && !Constants.parser.forceAutoSwitches) { if (!def) {
SceneryParserLog.warn('switchUndefinedModel', `Switch ${this.id} has an undefined model "${this.bare_model}", trying to generate auto model definition`); SceneryParserLog.warn('switchUndefinedModel', `Switch ${this.id} has an undefined model "${this.bare_model}"`);
return;
} }
if(!def || Constants.parser.forceAutoSwitches) { this._applySwitchFromDef(scenery, def);
def = this._tryGetAutoDef(scenery);
}
if(def) {
this._applySwitchFromDef(scenery, def);
} else {
SceneryParserLog.warn('switchAutoDefFailed', `Could not generate auto definition for switch ${this.id} with model "${this.bare_model}"`);
}
} }
_applySwitchFromDef(scenery, def) { _applySwitchFromDef(scenery, def) {
const ids = this._getTrackIds(def[2]); const trackIds = this._getTrackIds();
if(!ids) return; if (!trackIds) return;
const tracks = Object.entries(def.tracks).map(([key, track]) => {
return this._createSwitchTrackFromDef(scenery, def, track, trackIds)
});
if (tracks.some(track => !track)) return;
this.tracks = tracks;
this.def = def; this.def = def;
const trackAAliases = this._getTrackAliases(ids);
this.trackA = this._createSwitchTrackFromDef(scenery, this.id+"A", def[0], ids[0][1], ids[2][1], def[3], def[5], trackAAliases);
const trackBAliases = this._getTrackAliases(ids, 1, trackAAliases);
this.trackB = this._createSwitchTrackFromDef(scenery, this.id+"B", def[1], ids[1][1], ids[3][1], def[4], def[6], trackBAliases);
this.trackB.hide_isolation = true; // hide isolation for the second track
} }
_getTrackAliases(ids, startingId = 0, exclude = []) { _getTrackIds() {
const aliases = new Set(); const ids = this.data
for(let i = startingId; i < ids.length; i+=2) { .split(",")
aliases.add(ids[i][0]); .filter(part => part.trim() !== '')
.map(
(value) => value.split(":").map((part) => part.trim()),
);
if (ids.some((part) => part.length !== 3)) {
SceneryParserLog.warn('switchInvalidDataFormat', `Switch ${this.id} has invalid data: ${this.data}`);
} }
return ids;
exclude.forEach(alias => {
aliases.delete(alias);
});
return Array.from(aliases);
} }
_getTrackIds(outs) { _createSwitchTrackFromDef(scenery, switchDef, trackDef, ids) {
const dataValues = this.data.split(",");
const isCrossing = outs.length === 2;
if(isCrossing) outs = [outs[0], outs[1], outs[0], outs[1]];
return outs.map((out, index) => {
const parts = dataValues[out]?.split(":");
if(parts.length !== 3) {
SceneryParserLog.warn('switchInvalidDataFormat', `Switch ${this.id} has invalid data: ${this.data}`);
return null;
}
const trackId = parts[0].trim();
let connectedId = parts[1].trim() || parts[2].trim() || null;
if(isCrossing) connectedId = parts[~~(index / 2) + 1].trim();
return [trackId, connectedId];
});
}
_createSwitchTrackFromDef(scenery, id, r, previd, nextid, startPos, endPos, aliases = []) {
const rotRad = this.rot.multiply(Math.PI / 180); const rotRad = this.rot.multiply(Math.PI / 180);
if (trackDef.dataIndex >= ids.length) {
SceneryParserLog.warn(
'switchMissingTrackId',
`Switch ${this.id} with model ${this.bare_model} is missing an id for the track at index ${trackDef.dataIndex}`,
);
return null;
}
const [trackId, prevId, nextId] = ids[trackDef.dataIndex];
const endIds = {
[SwitchTrackConnectionEnd.PREV]: [],
[SwitchTrackConnectionEnd.NEXT]: [],
};
trackDef.connections.forEach((connection) => {
if (connection.type === SwitchTrackConnectionType.INTERNAL) {
const otherTrackDef = switchDef.tracks[connection.internalId];
if (!otherTrackDef) {
SceneryParserLog.warn(
'switchMissingTrackId',
`Switch prefab for model with model ${this.bare_model} of track ${this.id} does not have the internal track ${connection.internalId}`,
);
return;
}
if (otherTrackDef.dataIndex >= ids.length) {
SceneryParserLog.warn(
'switchMissingTrackId',
`Switch ${this.id} with model ${this.bare_model} is missing an id for the track at index ${otherTrackDef.dataIndex}`,
);
return;
}
const otherTrackId = ids[otherTrackDef.dataIndex][0];
if (otherTrackId) {
endIds[connection.end].push(otherTrackId);
}
} else if (connection.type === SwitchTrackConnectionType.EXTERNAL) {
const otherTrackId = connection.end === SwitchTrackConnectionEnd.PREV ? prevId : nextId;
if (otherTrackId) {
endIds[connection.end].push(otherTrackId);
}
}
});
const trackObj = new PointTrack( const trackObj = new PointTrack(
id, trackId,
this.pos.add(startPos.rotate(rotRad)), this.pos.add(trackDef.startPos.rotate(rotRad)),
this.pos.add(endPos.rotate(rotRad)), this.pos.add(trackDef.endPos.rotate(rotRad)),
r, trackDef.radius,
nextid, endIds[SwitchTrackConnectionEnd.PREV][0], // TODO: Pass the array
previd, endIds[SwitchTrackConnectionEnd.NEXT][0], // TODO: --||--
this.id_switch, this.id_switch,
0, // start_slope 0, // start_slope
0, // end_slope 0, // end_slope
this.id_isolation, this.id_isolation,
this.track_prefab_name, this.track_prefab_name,
this.maxspeed, this.maxspeed,
this.derailspeed this.derailspeed
); );
trackObj.switch = this; trackObj.switch = this;
scenery.addObject(trackObj); scenery.addObject(trackObj);
aliases.forEach(alias => { scenery.addTrackAlias(trackId, trackId);
scenery.addTrackAlias(id, alias);
});
return trackObj; return trackObj;
} }
_tryGetAutoDef(scenery) {
const outs = Switch.autoGetOutsFromData(this.data);
if(!outs) return null;
const radiuses = Switch.autoGetRadiusesFromModel(this.bare_model);
if(!radiuses) return null;
const [ra, rb] = radiuses;
const ids = this._getTrackIds(outs);
if(!ids) return null;
const trackPoints = ids.map(idsVal =>
this._autoFindClosestTrackEnd(scenery, idsVal[1])
);
if(trackPoints.length !== 4 || trackPoints.some(point => !point)) return null;
const rotRadNeg = this.rot.multiply(-Math.PI / 180);
const transformedPoints = trackPoints.map(point => point.sub(this.pos).rotate(rotRadNeg).toPrecision(3));
const newDef = [
ra,
rb,
outs,
...transformedPoints
];
if(!DefinedSwitches[this.bare_model]) DefinedSwitches[this.bare_model] = newDef;
if(Constants.parser.logNewAutoSwitches) console.log(this.bare_model, newDef);
return newDef;
}
static autoGetOutsFromData(data) {
const tracks = data.split(",");
if(tracks.length === 3) return [0, 1]; // Crossing
if(tracks.length < 4) {
SceneryParserLog.warn('switchInvalidDataFormat', `Switch data "${data}" is invalid, expected at least 4 tracks`);
return null;
}
const outs = [];
tracks.forEach((ct, i) => {
const ctv = ct.split(":");
outs.push(ctv[1] || ctv[2]);
});
return [
0,
outs[1] ? 1 : 0, // if no second track, use first track
outs[2] ? 2 : (outs[3] ? 3 : 5), // if no third track, use fourth or sixth track
outs[4] ? 4 : (outs[6] ? 6 : 3) // if no fourth track, use sixth or third track
];
}
static autoGetRadiusesFromModel(model) {
const bareModel = (model.split(',')[0] || model).trim();
if(/Rkp|Crossing/.test(bareModel)) return [0, 0];
const right = bareModel.at(-1) === "R";
const [prefix, rText, rldsR2Text] = bareModel.split("-");
const r = parseFloat(rText) || 0;
const [r1, r2] = rText.split('_').map(value => parseFloat(value) || 0);
switch(prefix) {
case 'Rz 60E1':
return [0, right ? -r : r];
case 'Rld 60E1':
return right ? [r1, -r2] : [-r1, r2];
case 'Rlds 60E1':
const rldsR2 = parseFloat(rldsR2Text) || 0;
return [-r1, rldsR2];
case 'Rlj 60E1':
return right ? [-r1, -r2] : [r1, r2];
default:
SceneryParserLog.warn('switchCannotResolveModel', `Switch model ${model} cannot be auto-resolved to radiuses`);
return null;
}
}
_autoFindClosestTrackEnd(scenery, trackId) {
if(!trackId) {
SceneryParserLog.warn('switchInvalidTrackConnection', `Switch ${this.id}, trackId of one of the required connections is empty`);
return null;
}
const track = scenery.getObject("tracks", trackId);
if(!track) {
SceneryParserLog.warn('switchInvalidTrackConnection', `Switch ${this.id}, track ${trackId} that the switch connects to not found`);
return null;
}
return track.getCloserEndPos(this.pos);
}
} }