Added SpawnPoints
+Added SpawnPoint object parser, layer and icon *Renamed Scenery.addSpawnSignal to .addSpawnPoint *Renamed Scenery.spawnSignals to .spawnPoints *Minor name changes
This commit is contained in:
parent
197cb2dcde
commit
38ecdbc2e3
8
public/assets/spawn.svg
Normal file
8
public/assets/spawn.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="100mm" height="100mm" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m33.8 15.3c-5.9209 0-10.8 4.8791-10.8 10.8v37.8c0 5.9209 4.8791 10.8 10.8 10.8h32.4c5.9209 0 10.8-4.8791 10.8-10.8v-37.8c0-5.9209-4.8791-10.8-10.8-10.8z" class="background" />
|
||||
<path d="m32 12c-6.5788 0-12 5.4215-12 12v42c0 5.3408 3.5732 9.9187 8.4377 11.453l-2.2732 6.567a3 3 0 0 0 1.8552 3.8163 3 3 0 0 0 3.8163-1.8557l2.7616-7.9804h30.805l2.7631 7.9804a3 3 0 0 0 3.8163 1.8557 3 3 0 0 0 1.8536-3.8163l-2.2732-6.567c4.8645-1.5338 8.4372-6.1117 8.4372-11.453v-42c0-6.5788-5.421-12-12-12h-36zm0 8h36c2.2852 0 4.0003 1.7151 4.0003 4.0003v42c0 2.2852-1.7151 3.9998-4.0003 3.9998h-36c-2.2852 0-4.0003-1.7146-4.0003-3.9998v-42c0-2.2852 1.7151-4.0003 4.0003-4.0003z" stop-color="#000000" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="m40 54a4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4z" stroke-linecap="round" stroke-linejoin="round" stroke-width="8"/>
|
||||
<path d="m68 54a4 4 0 0 1-4 4 4 4 0 0 1-4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4z" stroke-linecap="round" stroke-linejoin="round" stroke-width="8"/>
|
||||
<path d="m34 24h32.38c1.108 0 2 0.892 2 2v12.801c0 1.108-0.892 2-2 2h-32.38c-1.108 0-2-0.892-2-2v-12.801c0-1.108 0.892-2 2-2z" stroke-linecap="round" stroke-linejoin="round" stroke-width="8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -17,16 +17,17 @@ export default function LocList(props) {
|
||||
});
|
||||
}, [scenery?.signalBoxes]);
|
||||
|
||||
const spawnSignals = useMemo(() => {
|
||||
if (!scenery?.spawnSignals) return null;
|
||||
return scenery.spawnSignals.map(signal => {
|
||||
const pos = signal.pos.toSVGCoords();
|
||||
const name = signal.spawn_info.name || signal.getPrintableSignalName();
|
||||
const spawnPoints = useMemo(() => {
|
||||
if (!scenery?.spawnPoints) return null;
|
||||
return scenery.spawnPoints.map(trackObject => {
|
||||
const pos = trackObject.pos.toSVGCoords();
|
||||
const isSignal = trackObject.type === 'Signal';
|
||||
const name = trackObject.spawn_info.name || (isSignal ? trackObject.getPrintableSignalName() : trackObject.getPrintableSpawnPointName());
|
||||
return (
|
||||
<ClickableLocation name={name} pos={pos} key={signal.id} />
|
||||
<ClickableLocation name={name} pos={pos} key={trackObject.id} />
|
||||
)
|
||||
});
|
||||
}, [scenery?.spawnSignals]);
|
||||
}, [scenery?.spawnPoints]);
|
||||
|
||||
return (
|
||||
<div className="loclist">
|
||||
@ -34,7 +35,7 @@ export default function LocList(props) {
|
||||
{ signalBoxes }
|
||||
</div>
|
||||
<div className="loclist-section">
|
||||
{ spawnSignals }
|
||||
{ spawnPoints }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -82,3 +82,11 @@
|
||||
.map svg g.derailer path {
|
||||
fill: #eee;
|
||||
}
|
||||
|
||||
.map svg g.spawn-point path {
|
||||
fill: #eee;
|
||||
}
|
||||
|
||||
.map svg g.spawn-point path.background {
|
||||
fill: #111;
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import SignRenderer from './object-renderers/SignRenderer';
|
||||
import NEVPRenderer from './object-renderers/NEVPRenderer';
|
||||
import DerailerRenderer from './object-renderers/DerailerRenderer';
|
||||
import ElectrificationStatusPopup from './additional-layer-components/ElectrificationStatusPopup';
|
||||
import SpawnPointRenderer from './object-renderers/SpawnPointRenderer';
|
||||
|
||||
const ObjectRendererQueue = [
|
||||
{
|
||||
@ -61,6 +62,13 @@ const ObjectRendererQueue = [
|
||||
'renderer': SignalRenderer,
|
||||
'cond': (layers) => layers['signals']
|
||||
},
|
||||
{
|
||||
'name': 'spawn-points',
|
||||
'category': 'track-objects',
|
||||
'type': 'SpawnPoint',
|
||||
'renderer': SpawnPointRenderer,
|
||||
'cond': (layers) => layers['spawn-points'],
|
||||
},
|
||||
{
|
||||
'name': 'signalboxes',
|
||||
'category': 'misc',
|
||||
|
||||
33
src/components/map/object-renderers/SpawnPointRenderer.js
Normal file
33
src/components/map/object-renderers/SpawnPointRenderer.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { ReactSVG } from 'react-svg'
|
||||
import AngleHelper from '../../../helpers/angleHelper';
|
||||
|
||||
export default function SpawnPointRenderer(props) {
|
||||
const { object } = props;
|
||||
const [x, y] = object.pos.toSVGCoords();
|
||||
|
||||
const rot = AngleHelper.normalizeDegAngle(object.rot.y);
|
||||
const upsideDown = rot >= 180;
|
||||
const upsideDownRot = upsideDown ? 90 : -90;
|
||||
const anchor = upsideDown ? "start" : "end";
|
||||
|
||||
return (
|
||||
<g className="spawn-point" transform={`translate(${x}, ${y}) rotate(${object.rot.y})`}>
|
||||
<g className="signal-icon" transform={`rotate(180) translate(-2.835, -2.835)`}>
|
||||
<ReactSVG
|
||||
src={`${process.env.PUBLIC_URL}/assets/spawn.svg`}
|
||||
wrapper='svg'
|
||||
|
||||
beforeInjection={(svg) => {
|
||||
svg.setAttribute('width', '1.5mm');
|
||||
svg.setAttribute('height', '1.5mm');
|
||||
}}
|
||||
/>
|
||||
</g>
|
||||
<g transform={`translate(0, 3) rotate(${upsideDownRot})`}>
|
||||
<text x="0" y="0" textAnchor={anchor} dominantBaseline="middle">
|
||||
{object.getPrintableSpawnPointName()}
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
);
|
||||
}
|
||||
@ -21,7 +21,7 @@ const Constants = {
|
||||
switchInvalidTrackConnection: true,
|
||||
unknownObjectType: true,
|
||||
unknownTrackType: true,
|
||||
signalWithoutSpawnInfo: true,
|
||||
spawnWithoutSpawnInfo: true,
|
||||
trackAliasAlreadyExists: true,
|
||||
trackAliasNoTrack: true,
|
||||
switchUndefinedModel: true,
|
||||
@ -50,7 +50,7 @@ const Constants = {
|
||||
{
|
||||
id: 'switches-names',
|
||||
name: 'Switches names',
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
id: 'isolations-ids',
|
||||
@ -67,6 +67,11 @@ const Constants = {
|
||||
name: 'Signals',
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
id: 'spawn-points',
|
||||
name: 'SpawnPoints',
|
||||
default: true,
|
||||
},
|
||||
{
|
||||
id: 'derailers',
|
||||
name: 'Derailers',
|
||||
|
||||
@ -17,6 +17,7 @@ import MainCamera from './main-camera';
|
||||
import ElectrificationResolver from './electrification-resolver';
|
||||
import NEVP from './nevp';
|
||||
import Derailer from './derailer';
|
||||
import SpawnPoint from './spawn-point';
|
||||
|
||||
/*
|
||||
TODO: add support for WorldRotation and WorldTranslation
|
||||
@ -129,6 +130,8 @@ export default class SceneryParser {
|
||||
return Derailer.fromText(text);
|
||||
} else if(NEVP.isNEVP(text)) {
|
||||
return NEVP.fromText(text);
|
||||
} else if(SpawnPoint.isSpawnPoint(text)) {
|
||||
return SpawnPoint.fromText(text);
|
||||
} else {
|
||||
return TrackObject.fromText(text);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ export default class Scenery
|
||||
{
|
||||
objects = {};
|
||||
signalBoxes = [];
|
||||
spawnSignals = [];
|
||||
spawnPoints = [];
|
||||
bounds = { minX: Infinity, minZ: Infinity, maxX: -Infinity, maxZ: -Infinity };
|
||||
trackAliases = {};
|
||||
electrificationResolved = ElectrificationResolutionStatus.NOT_RESOLVED;
|
||||
@ -19,8 +19,8 @@ export default class Scenery
|
||||
this.signalBoxes.push(signalBox);
|
||||
}
|
||||
|
||||
addSpawnSignal(signal) {
|
||||
this.spawnSignals.push(signal);
|
||||
addSpawnPoint(trackObject) {
|
||||
this.spawnPoints.push(trackObject);
|
||||
}
|
||||
|
||||
addObject(object) {
|
||||
|
||||
@ -20,7 +20,7 @@ export default class Signal extends TrackObject {
|
||||
});
|
||||
|
||||
if (this.is_spawn && !this.spawn_info) {
|
||||
SceneryParserLog.warn('signalWithoutSpawnInfo', `Signal ${this.id} is marked as spawn but has no spawn info`);
|
||||
SceneryParserLog.warn('spawnWithoutSpawnInfo', `Signal ${this.id} is marked as spawn but has no spawn info`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ export default class Signal extends TrackObject {
|
||||
this.applied = true;
|
||||
|
||||
if (this.is_spawn) {
|
||||
scenery.addSpawnSignal(this);
|
||||
scenery.addSpawnPoint(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
72
src/model/spawn-point.js
Normal file
72
src/model/spawn-point.js
Normal file
@ -0,0 +1,72 @@
|
||||
import SceneryParserLog from "./scenery-parser-log";
|
||||
import SpawnInfo from "./spawn-info";
|
||||
import TrackObject from "./track-object";
|
||||
import Vector3 from "./vector3";
|
||||
|
||||
export default class SpawnPoint extends TrackObject {
|
||||
is_spawn;
|
||||
spawn_info;
|
||||
spawn_point_name;
|
||||
type = "SpawnPoint";
|
||||
applied = false;
|
||||
|
||||
constructor(id, prefab_name, pos, rot, track_id, name, is_spawn, spawn_info, signal_name) {
|
||||
super(id, prefab_name, pos, rot, track_id, name);
|
||||
|
||||
Object.assign(this, {
|
||||
is_spawn,
|
||||
spawn_info,
|
||||
signal_name
|
||||
});
|
||||
|
||||
if (this.is_spawn && !this.spawn_info) {
|
||||
SceneryParserLog.warn('spawnWithoutSpawnInfo', `SpawnPoint ${this.id} is marked as spawn but has no spawn info`);
|
||||
}
|
||||
}
|
||||
|
||||
getPrintableSpawnPointName() {
|
||||
return this.spawn_point_name?.trim() || this.name?.trim() || "Spawn Point";
|
||||
}
|
||||
|
||||
/*
|
||||
Check if a TrackObject text is a SpawnPoint.
|
||||
@param {string} text - The text representation of the TrackObject.
|
||||
@returns {boolean} - Returns true if the text represents a SpawnPoint, false otherwise.
|
||||
@static
|
||||
@memberof Signal
|
||||
*/
|
||||
static isSpawnPoint(text) {
|
||||
const values = text.split(";");
|
||||
if(values.length < 29) return false;
|
||||
|
||||
const prefabName = values[2];
|
||||
return prefabName === "Spawn Point";
|
||||
}
|
||||
|
||||
static fromText(text) {
|
||||
const values = text.split(";");
|
||||
const signal = new SpawnPoint(
|
||||
values[1], // id
|
||||
values[2], // prefab_name
|
||||
Vector3.fromValuesArray(values, 3), // pos
|
||||
Vector3.fromValuesArray(values, 6), // rot
|
||||
values[9], // track_id
|
||||
values[11], // name,
|
||||
values[12] === "Spawn Signal", // is_spawn
|
||||
SpawnInfo.fromText(values[15]), // spawn_info
|
||||
values[29]
|
||||
);
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
applyObject(scenery) {
|
||||
if(this.applied) return; // already applied
|
||||
this.applied = true;
|
||||
|
||||
if (this.is_spawn) {
|
||||
scenery.addSpawnPoint(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user