Added defined switches, fixed bugs
+Added pre-defined switches so they dont have to be generated. Unrecognised switches models are still automatically resolved and their new definitions are saved for later use +Added .multiply, .toPrecission and .rotate functions in the Vector3 class *Improved switches to normal tracks connections *Improved switches-related error handling
This commit is contained in:
parent
6d4aef606a
commit
9b49f4dc73
@ -3,6 +3,9 @@ const Constants = {
|
||||
zoomSensitivity: 0.002,
|
||||
trackSlopeScale: 10,
|
||||
},
|
||||
parser: {
|
||||
forceAutoSwitches: false
|
||||
},
|
||||
warnings: {
|
||||
all: false, // enable all warnings
|
||||
trackObjectCannotBeApplied: false,
|
||||
@ -10,6 +13,11 @@ const Constants = {
|
||||
unknownObjectType: true,
|
||||
unknownTrackType: true,
|
||||
signalWithoutSpawnInfo: true,
|
||||
trackAliasAlreadyExists: true,
|
||||
switchUndefinedModel: true,
|
||||
switchAutoDefFailed: true,
|
||||
switchInvalidDataFormat: true,
|
||||
switchNoModel: true,
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
|
||||
348
src/model/defined-switches.js
Normal file
348
src/model/defined-switches.js
Normal file
@ -0,0 +1,348 @@
|
||||
import Vector3 from "./vector3";
|
||||
|
||||
const DefinedSwitches = {
|
||||
"Crossing4.444": [
|
||||
0,
|
||||
0,
|
||||
[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)
|
||||
],
|
||||
"Rz 60E1-300-1_9 R": [
|
||||
0,
|
||||
-300,
|
||||
[0, 0, 3, 4],
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 33.231),
|
||||
new Vector3(1.835, 0, 33.129)
|
||||
],
|
||||
"Rz 60E1-300-1_9 L": [
|
||||
0,
|
||||
300,
|
||||
[0, 0, 3, 4],
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 33.231),
|
||||
new Vector3(-1.835, 0, 33.129)
|
||||
],
|
||||
"Rz 60E1-190-1_9 R": [
|
||||
0,
|
||||
-190,
|
||||
[0, 0, 5, 6],
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 27.139),
|
||||
new Vector3(1.835, 0, 27.037)
|
||||
],
|
||||
"Rz 60E1-190-1_9 L": [
|
||||
0,
|
||||
190,
|
||||
[0, 0, 5, 6],
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 27.139),
|
||||
new Vector3(-1.835, 0, 27.037)
|
||||
],
|
||||
"Rz 60E1-500-1_12 R": [
|
||||
0,
|
||||
500,
|
||||
[0, 0, 3, 4],
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 41.595),
|
||||
new Vector3(1.727, 0, 41.523)
|
||||
],
|
||||
"Rz 60E1-500-1_12 L": [
|
||||
0,
|
||||
500,
|
||||
[0, 0, 3, 4],
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 0),
|
||||
new Vector3(0, 0, 41.595),
|
||||
new Vector3(-1.727, 0, 41.523)
|
||||
],
|
||||
"Rkpd 60E1-190-1_9": [
|
||||
0,
|
||||
0,
|
||||
[0, 1, 2, 3],
|
||||
new Vector3(-0.918, 0, -16.557),
|
||||
new Vector3(0.917, 0, -16.557),
|
||||
new Vector3(0.917, 0, 16.557),
|
||||
new Vector3(-0.917, 0, 16.557)
|
||||
],
|
||||
"Rkp 60E1-190-1_9 ab": [
|
||||
0,
|
||||
0,
|
||||
[0, 1, 2, 3],
|
||||
new Vector3(-0.918, 0, -16.557),
|
||||
new Vector3(0.917, 0, -16.556),
|
||||
new Vector3(0.917, 0, 16.558),
|
||||
new Vector3(-0.921, 0, 16.558)
|
||||
],
|
||||
"Rz 60E1-265-1_10 R": [
|
||||
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-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-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-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)
|
||||
],
|
||||
"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)
|
||||
],
|
||||
"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-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_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;
|
||||
@ -13,6 +13,7 @@ export default class Scenery
|
||||
signalBoxes = [];
|
||||
spawnSignals = [];
|
||||
bounds = { minX: Infinity, minZ: Infinity, maxX: -Infinity, maxZ: -Infinity };
|
||||
trackAliases = {};
|
||||
static nextMiscId = 1;
|
||||
|
||||
getBounds () {
|
||||
@ -72,6 +73,19 @@ export default class Scenery
|
||||
return this.objects[category][id] ?? null;
|
||||
}
|
||||
|
||||
addTrackAlias(id, alias) {
|
||||
if(this.trackAliases[alias]) {
|
||||
SceneryParserLog.warn('trackAliasAlreadyExists', `Track alias "${alias}" already exists for track "${this.trackAliases[alias]}". Cannot add alias for "${id}".`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.trackAliases[alias] = id;
|
||||
}
|
||||
|
||||
getTrackIdByAlias(idOrAlias) {
|
||||
return this.trackAliases[idOrAlias] || idOrAlias;
|
||||
}
|
||||
|
||||
static _parseObject(text) {
|
||||
const type = text.split(";", 2)[0];
|
||||
switch(type) {
|
||||
|
||||
@ -2,6 +2,8 @@ import PointTrack from "./point-track.js";
|
||||
import SceneryObject from "./scenery-object.js";
|
||||
import SceneryParserLog from "./scenery-parser-log.js";
|
||||
import Vector3 from "./vector3.js";
|
||||
import DefinedSwitches from "./defined-switches.js";
|
||||
import Constants from "../helpers/constants.js";
|
||||
|
||||
export default class Switch extends SceneryObject {
|
||||
model;
|
||||
@ -12,7 +14,6 @@ export default class Switch extends SceneryObject {
|
||||
derailspeed;
|
||||
category = "switches";
|
||||
type = "Switch";
|
||||
outs = [];
|
||||
applied = false;
|
||||
trackA;
|
||||
trackB;
|
||||
@ -25,6 +26,8 @@ export default class Switch extends SceneryObject {
|
||||
id_switch, id_isolation,
|
||||
maxspeed, derailspeed
|
||||
});
|
||||
|
||||
this.bare_model = model.split(',')[0]?.trim() || model.trim();
|
||||
}
|
||||
|
||||
static fromText(text) {
|
||||
@ -49,80 +52,71 @@ export default class Switch extends SceneryObject {
|
||||
if(this.applied) return; // already applied
|
||||
this.applied = true;
|
||||
|
||||
this.outs = Switch.getOutsFromData(this.data);
|
||||
const r = Switch.getRadiusFromModel(this.model);
|
||||
|
||||
this.trackA = this._createGetSwitchTrack(scenery, this.id+"A", this.outs[0], this.outs[2], 0);
|
||||
if(this.trackA) {
|
||||
scenery.addObject(this.trackA);
|
||||
if(!this.bare_model) {
|
||||
SceneryParserLog.warn('switchNoModel', `Switch ${this.id} has no model defined, apply`);
|
||||
return null;
|
||||
}
|
||||
|
||||
this.trackB = this._createGetSwitchTrack(scenery, this.id+"B", this.outs[1], this.outs[3], r);
|
||||
if(this.trackB) {
|
||||
this.trackB.hide_isolation = true; // hide isolation for the second track
|
||||
scenery.addObject(this.trackB);
|
||||
let def = DefinedSwitches[this.bare_model] || null;
|
||||
|
||||
if(!def && !Constants.parser.forceAutoSwitches) {
|
||||
SceneryParserLog.warn('switchUndefinedModel', `Switch ${this.id} has undefined model "${this.bare_model}", trying to generate auto model definition`);
|
||||
}
|
||||
|
||||
if(!def || Constants.parser.forceAutoSwitches) {
|
||||
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}"`);
|
||||
}
|
||||
}
|
||||
|
||||
static getOutsFromData(data) {
|
||||
const cts = data.split(",");
|
||||
_applySwitchFromDef(scenery, def) {
|
||||
const ids = this._getTrackIds(def[2]);
|
||||
if(!ids) return;
|
||||
|
||||
const tou = [];
|
||||
cts.forEach((ct, i) => {
|
||||
cts[i] = ct.split(":");
|
||||
if(cts[i][1] === "") cts[i][1] = cts[i][2];
|
||||
tou.push(cts[i][1]);
|
||||
const trackAAliases = [ids[0][0], ids[2][0]];
|
||||
this.trackA = this._createSwitchTrackFromDef(scenery, this.id+"A", def[0], ids[0][1], ids[2][1], def[3], def[5], trackAAliases);
|
||||
scenery.addObject(this.trackA);
|
||||
|
||||
const trackBAliases = [ids[0][0], ids[2][0]].filter(alias => trackAAliases.includes(alias) === false);
|
||||
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
|
||||
scenery.addObject(this.trackB);
|
||||
}
|
||||
|
||||
_getTrackIds(outs) {
|
||||
const dataValues = this.data.split(",");
|
||||
const isCrossing = outs.length === 2;
|
||||
if(isCrossing) outs = [outs[0], outs[0], outs[1], 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];
|
||||
});
|
||||
|
||||
return [
|
||||
tou[0],
|
||||
tou[1] || tou[0],
|
||||
tou[2] || tou[3] || tou[5],
|
||||
tou[4] || tou[6] || tou[3]
|
||||
];
|
||||
}
|
||||
|
||||
static getRadiusFromModel(model) {
|
||||
if(/Rkpd|Crossing/.test(model)) return 0;
|
||||
_createSwitchTrackFromDef(scenery, id, r, previd, nextid, startPos, endPos, aliases = []) {
|
||||
const rotRad = this.rot.multiply(Math.PI / 180);
|
||||
|
||||
const radiusText = model.replace(/(Rz 60E1-)|-1_.*/g, "");
|
||||
const radius = parseInt(radiusText) || 0;
|
||||
const side = model.split(",")[0];
|
||||
const isRight = side[side.length-1] === "R";
|
||||
|
||||
return isRight ? -radius : radius;
|
||||
}
|
||||
|
||||
_createGetSwitchTrack(scenery, name, from, to, r) {
|
||||
if(!from) {
|
||||
SceneryParserLog.warn('switchInvalidTrackConnection', `Switch track ${name} has no 'from' track set`);
|
||||
return null;
|
||||
} else if(!to) {
|
||||
SceneryParserLog.warn('switchInvalidTrackConnection', `Switch track ${name} has no 'to' track set`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const startTrack = scenery.getObject("tracks", from);
|
||||
const endTrack = scenery.getObject("tracks", to);
|
||||
|
||||
if(!startTrack) {
|
||||
SceneryParserLog.warn('switchInvalidTrackConnection', `Switch track ${name}, 'from' track ${from} not found`);
|
||||
return null;
|
||||
} else if(!endTrack) {
|
||||
SceneryParserLog.warn('switchInvalidTrackConnection', `Switch track ${name}, 'to' track ${to} not found`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const startTrackEnd = startTrack.getCloserEndPos(this.pos);
|
||||
const endTrackEnd = endTrack.getCloserEndPos(this.pos);
|
||||
|
||||
let trackObj = new PointTrack(
|
||||
name,
|
||||
startTrackEnd,
|
||||
endTrackEnd,
|
||||
const trackObj = new PointTrack(
|
||||
id,
|
||||
this.pos.add(startPos.rotate(rotRad)),
|
||||
this.pos.add(endPos.rotate(rotRad)),
|
||||
r,
|
||||
from,
|
||||
to,
|
||||
previd,
|
||||
nextid,
|
||||
this.id_switch,
|
||||
0, // start_slope
|
||||
0, // end_slope
|
||||
@ -131,6 +125,105 @@ export default class Switch extends SceneryObject {
|
||||
this.derailspeed
|
||||
);
|
||||
|
||||
aliases.forEach(alias => {
|
||||
scenery.addTrackAlias(id, alias);
|
||||
});
|
||||
|
||||
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;
|
||||
// console.log(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] = 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':
|
||||
return [-r1, r2];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,47 @@ export default class Vector3 {
|
||||
);
|
||||
}
|
||||
|
||||
rotate(rot) {
|
||||
const [ax, ay, az] = rot.toArray();
|
||||
|
||||
const cosX = Math.cos(ax);
|
||||
const sinX = Math.sin(ax);
|
||||
const cosY = Math.cos(ay);
|
||||
const sinY = Math.sin(ay);
|
||||
const cosZ = Math.cos(az);
|
||||
const sinZ = Math.sin(az);
|
||||
|
||||
// Rotate around Y
|
||||
let x = this.x * cosY + this.z * sinY;
|
||||
let z = -this.x * sinY + this.z * cosY;
|
||||
|
||||
// Rotate around X
|
||||
let y = this.y * cosX - z * sinX;
|
||||
z = this.y * sinX + z * cosX;
|
||||
|
||||
// Rotate around Z
|
||||
x = x * cosZ - y * sinZ;
|
||||
y = x * sinZ + y * cosZ;
|
||||
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
toPrecision(precision = 3) {
|
||||
return new Vector3(
|
||||
parseFloat(this.x.toFixed(precision)),
|
||||
parseFloat(this.y.toFixed(precision)),
|
||||
parseFloat(this.z.toFixed(precision))
|
||||
);
|
||||
}
|
||||
|
||||
multiply(scalar) {
|
||||
return new Vector3(
|
||||
this.x * scalar,
|
||||
this.y * scalar,
|
||||
this.z * scalar
|
||||
);
|
||||
}
|
||||
|
||||
lerp(other, t) {
|
||||
return new Vector3(
|
||||
this.x + (other.x - this.x) * t,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user