Improved Misc objects parsing
+Added AngleHelper.normalizeDegVector +Added support for MiscGroups +Added an option to skip base Misc objects parsing *Moved nextMiscId from Scenery to SceneryParser *Cleane up SceneryParser code
This commit is contained in:
parent
15c7d8ba9e
commit
c6b6fef724
@ -1,3 +1,5 @@
|
||||
import Vector3 from "../model/vector3";
|
||||
|
||||
function degToRad(angle) {
|
||||
return angle * (Math.PI / 180);
|
||||
}
|
||||
@ -16,10 +18,19 @@ function normalizeDegAngle(angle) {
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeDegVector(vector) {
|
||||
return new Vector3(
|
||||
normalizeDegAngle(vector.x),
|
||||
normalizeDegAngle(vector.y),
|
||||
normalizeDegAngle(vector.z)
|
||||
)
|
||||
}
|
||||
|
||||
const AngleHelper = {
|
||||
degToRad,
|
||||
radToDeg,
|
||||
normalizeDegAngle,
|
||||
normalizeDegVector
|
||||
}
|
||||
|
||||
export default AngleHelper;
|
||||
@ -20,6 +20,7 @@ const Constants = {
|
||||
attachSignsMaxDistanceX: 0.2,
|
||||
attachSignsGridSize: 10,
|
||||
logAttachedSigns: false,
|
||||
skipBaseMisc: true
|
||||
},
|
||||
warnings: {
|
||||
all: false, // enable all warnings
|
||||
@ -37,9 +38,9 @@ const Constants = {
|
||||
invalidSceneryInfoVersion: true,
|
||||
signUndefinedPrefabName: true,
|
||||
tracksConnectionTest: true,
|
||||
tracksConnectionTestSwitchRelated: true,
|
||||
electrificationNevpNotApplied: false,
|
||||
electrificationConflict: false,
|
||||
tracksConnectionTestSwitchRelated: true,
|
||||
electrificationResolverError: true,
|
||||
electrificationResolverWarnings: true,
|
||||
signalElemsUnknownPrefab: true,
|
||||
@ -50,6 +51,7 @@ const Constants = {
|
||||
connectTracksFailed: true,
|
||||
routeInvalidSegment: true,
|
||||
derailerUnknownDirection: true,
|
||||
endMiscGroupWithoutStart: true,
|
||||
},
|
||||
errors: {
|
||||
invalidSceneryInfo: true
|
||||
|
||||
21
src/model/misc-group.js
Normal file
21
src/model/misc-group.js
Normal file
@ -0,0 +1,21 @@
|
||||
import Vector3 from "./vector3";
|
||||
|
||||
export default class MiscGroup {
|
||||
pos;
|
||||
rot;
|
||||
|
||||
constructor(pos, rot) {
|
||||
this.pos = pos;
|
||||
this.rot = rot;
|
||||
}
|
||||
|
||||
static fromText(text) {
|
||||
const values = text.split(";");
|
||||
const object = new MiscGroup(
|
||||
Vector3.fromValuesArray(values, 3), // pos
|
||||
Vector3.fromValuesArray(values, 6), // rot
|
||||
);
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
import AngleHelper from "../../helpers/angleHelper";
|
||||
import SceneryObject from "../scenery-object";
|
||||
import Vector3 from "../vector3";
|
||||
|
||||
@ -6,7 +7,6 @@ export default class Misc extends SceneryObject {
|
||||
name;
|
||||
category = "misc";
|
||||
type = "Misc";
|
||||
applied = false;
|
||||
|
||||
constructor(id, misc_id, prefab_name, pos, rot, name) {
|
||||
super(id, pos, rot);
|
||||
@ -17,17 +17,37 @@ export default class Misc extends SceneryObject {
|
||||
});
|
||||
}
|
||||
|
||||
static fromText(id, text) {
|
||||
static fromText(id, text, miscGroups = []) {
|
||||
const values = text.split(";");
|
||||
|
||||
const object = new Misc(
|
||||
id, // id
|
||||
values[1], // misc_id
|
||||
values[2], // prefab_name
|
||||
Vector3.fromValuesArray(values, 3), // pos
|
||||
Vector3.fromValuesArray(values, 6), // rot
|
||||
...Misc.applyGroupTransforms(
|
||||
Vector3.fromValuesArray(values, 3), // pos
|
||||
Vector3.fromValuesArray(values, 6), // rot
|
||||
miscGroups
|
||||
),
|
||||
values[9] // name
|
||||
);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static applyGroupTransforms(pos, rot, miscGroups) {
|
||||
if(!miscGroups) return [ pos, rot ];
|
||||
|
||||
for (const group of miscGroups) {
|
||||
const rotRad = AngleHelper.degToRad(group.rot.y);
|
||||
const rotRadY = new Vector3(0, rotRad, 0);
|
||||
pos = pos.rotate(rotRadY).add(group.pos);
|
||||
rot = rot.add(group.rot);
|
||||
// TODO: Replace this with some fancy quaternion math maybe
|
||||
}
|
||||
|
||||
rot = AngleHelper.normalizeDegVector(rot);
|
||||
|
||||
return [ pos, rot ];
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,14 +25,21 @@ export default class SignalBox extends Misc {
|
||||
scenery.addSignalBox(this);
|
||||
}
|
||||
|
||||
static fromText(id, text) {
|
||||
static isSignalBox(prefabName) {
|
||||
return prefabName.startsWith('SignalBox');
|
||||
}
|
||||
|
||||
static fromText(id, text, miscGroups = []) {
|
||||
const values = text.split(";");
|
||||
const object = new SignalBox(
|
||||
id, // id
|
||||
values[1], // misc_id
|
||||
values[2], // prefab_name
|
||||
Vector3.fromValuesArray(values, 3), // pos
|
||||
Vector3.fromValuesArray(values, 6), // rot
|
||||
...Misc.applyGroupTransforms(
|
||||
Vector3.fromValuesArray(values, 3), // pos
|
||||
Vector3.fromValuesArray(values, 6), // rot
|
||||
miscGroups
|
||||
),
|
||||
values[9] // name
|
||||
);
|
||||
|
||||
|
||||
@ -19,17 +19,18 @@ 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
|
||||
*/
|
||||
import MiscGroup from './misc-group';
|
||||
|
||||
export default class SceneryParser {
|
||||
static nextMiscId = 1;
|
||||
|
||||
static fromText(scText) {
|
||||
SceneryParser.nextMiscId = 1;
|
||||
const lines = scText.split("\n").map(line => line.trim());
|
||||
const scenery = new Scenery();
|
||||
|
||||
let currentRoute = null;
|
||||
const currentMiscGroups = [];
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
if(index === 0) {
|
||||
@ -37,22 +38,30 @@ export default class SceneryParser {
|
||||
if(sceneryInfo) scenery.addObject(sceneryInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!line?.length) return;
|
||||
|
||||
if (currentRoute !== null) {
|
||||
const foundRouteEnd = SceneryParser._parseRouteLine(line, currentRoute);
|
||||
if (foundRouteEnd) {
|
||||
const isRouteEnd = SceneryParser._parseRouteLine(line, currentRoute);
|
||||
|
||||
if (isRouteEnd) {
|
||||
scenery.addObject(currentRoute);
|
||||
currentRoute = null;
|
||||
}
|
||||
} else {
|
||||
const object = SceneryParser._parseObject(line);
|
||||
if(!object) return; // skip null objects
|
||||
if (object.type === 'Route') {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const object = SceneryParser._parseObject(line, currentMiscGroups);
|
||||
if(!object) return; // skip null objects
|
||||
|
||||
switch(object.type) {
|
||||
case 'Route':
|
||||
currentRoute = object;
|
||||
} else {
|
||||
return; // do not add Route object yet
|
||||
default:
|
||||
scenery.addObject(object);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -80,7 +89,7 @@ export default class SceneryParser {
|
||||
return SceneryInfo.fromText(text);
|
||||
}
|
||||
|
||||
static _parseObject(text) {
|
||||
static _parseObject(text, currentMiscGroups) {
|
||||
const type = text.split(";", 2)[0];
|
||||
|
||||
if (type === 'EndRoute' || type.indexOf("Forest") !== -1 || type.indexOf("Empty") !== -1) {
|
||||
@ -98,13 +107,22 @@ export default class SceneryParser {
|
||||
case 'Route':
|
||||
return Route.fromText(text);
|
||||
case 'Misc':
|
||||
return SceneryParser._parseMisc(text);
|
||||
return SceneryParser._parseMisc(text, currentMiscGroups);
|
||||
case 'CameraHome':
|
||||
return CameraHome.fromText(text);
|
||||
case 'MainCamera':
|
||||
return MainCamera.fromText(text);
|
||||
case 'MiscGroup':
|
||||
const group = MiscGroup.fromText(text);
|
||||
currentMiscGroups.unshift(group);
|
||||
|
||||
return null;
|
||||
case 'EndMiscGroup':
|
||||
if(!currentMiscGroups.shift()) {
|
||||
SceneryParserLog.warn('endMiscGroupWithoutStart', 'Unexpected EndMiscGroup found without a preceding MiscGroup');
|
||||
}
|
||||
|
||||
return null;
|
||||
case 'Wires':
|
||||
case 'Fence':
|
||||
case 'TerrainPoint':
|
||||
@ -152,13 +170,16 @@ export default class SceneryParser {
|
||||
}
|
||||
}
|
||||
|
||||
static _parseMisc(text) {
|
||||
static _parseMisc(text, miscGroups) {
|
||||
const prefabName = text.split(';', 4)[2];
|
||||
const id = SceneryParser.nextMiscId++;
|
||||
|
||||
if(prefabName.startsWith("SignalBox")) {
|
||||
return SignalBox.fromText(Scenery.nextMiscId++, text);
|
||||
if(SignalBox.isSignalBox(prefabName)) {
|
||||
return SignalBox.fromText(id, text, miscGroups);
|
||||
} else if(Constants.parser.skipBaseMisc) {
|
||||
return null;
|
||||
} else {
|
||||
return Misc.fromText(Scenery.nextMiscId++, text);
|
||||
return Misc.fromText(id, text, miscGroups);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,6 @@ export default class Scenery
|
||||
spawnPoints = [];
|
||||
bounds = { minX: Infinity, minZ: Infinity, maxX: -Infinity, maxZ: -Infinity };
|
||||
electrificationResolved = ElectrificationResolutionStatus.NOT_RESOLVED;
|
||||
static nextMiscId = 1;
|
||||
|
||||
getBounds () {
|
||||
return { ...this.bounds };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user