RouteRenderer, code tweaks
+Added Route class +Added RouteRenderer *Parts of the map rendered by different renderers are now separated into <g> groups *Fixed signals not being parsed correctly
This commit is contained in:
parent
06dd81eec6
commit
b7f9d80045
7
public/assets/route.svg
Normal file
7
public/assets/route.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="160mm" height="100mm" version="1.1" viewBox="0 0 160 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g>
|
||||||
|
<path d="m120 80s-28.351-30-112-30c83.62 0 112-30 112-30z"/>
|
||||||
|
<rect x="119" y="35" width="33" height="30"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 274 B |
@ -15,7 +15,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.map svg text.switch-name {
|
.map svg text.switch-name {
|
||||||
fill: #eee;
|
|
||||||
fill: #bbf;
|
fill: #bbf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,4 +37,13 @@
|
|||||||
|
|
||||||
.map svg g.signal g {
|
.map svg g.signal g {
|
||||||
stroke: #eee;
|
stroke: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map svg g.route g {
|
||||||
|
fill: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map svg g.route text {
|
||||||
|
fill: #eee;
|
||||||
|
font-size: 72mm;
|
||||||
}
|
}
|
||||||
@ -3,6 +3,7 @@ import SwitchNameRenderer from './object-renderers/SwitchNameRenderer';
|
|||||||
import IsolationIdRenderer from './object-renderers/IsolationIdRenderer';
|
import IsolationIdRenderer from './object-renderers/IsolationIdRenderer';
|
||||||
import TrackObjectRenderer from './object-renderers/TrackObjectRenderer';
|
import TrackObjectRenderer from './object-renderers/TrackObjectRenderer';
|
||||||
import SignalRenderer from './object-renderers/SignalRenderer';
|
import SignalRenderer from './object-renderers/SignalRenderer';
|
||||||
|
import RouteRenderer from './object-renderers/RouteRenderer';
|
||||||
|
|
||||||
const ObjectRendererQueue = [
|
const ObjectRendererQueue = [
|
||||||
{
|
{
|
||||||
@ -36,6 +37,12 @@ const ObjectRendererQueue = [
|
|||||||
'type': 'Signal',
|
'type': 'Signal',
|
||||||
'renderer': SignalRenderer,
|
'renderer': SignalRenderer,
|
||||||
'cond': (settings) => settings.layers['signals']
|
'cond': (settings) => settings.layers['signals']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'routes',
|
||||||
|
'category': 'routes',
|
||||||
|
'renderer': RouteRenderer,
|
||||||
|
'cond': (settings) => settings.layers['routes']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -18,12 +18,16 @@ export default function SceneryRoot(props) {
|
|||||||
const objects = scenery.objects[category] ?? null;
|
const objects = scenery.objects[category] ?? null;
|
||||||
if(!objects) return [null];
|
if(!objects) return [null];
|
||||||
|
|
||||||
return Object.values(objects).map((object) => {
|
return (
|
||||||
if((type !== undefined && type !== object.type) || (types !== undefined && !types.includes(object.type))) return null;
|
<g className={`scenery-layer-${name}`} key={name}>
|
||||||
|
{Object.values(objects).map((object) => {
|
||||||
|
if((type !== undefined && type !== object.type) || (types !== undefined && !types.includes(object.type))) return null;
|
||||||
|
|
||||||
return <RendererComponent key={`${name}-${object.id}`} object={object} />;
|
return <RendererComponent key={`${name}-${object.id}`} object={object} />;
|
||||||
});
|
})}
|
||||||
}).flat();
|
</g>
|
||||||
|
);
|
||||||
|
});
|
||||||
}, [scenery, settings]);
|
}, [scenery, settings]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
44
src/components/map/object-renderers/RouteRenderer.js
Normal file
44
src/components/map/object-renderers/RouteRenderer.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
import { ReactSVG } from "react-svg";
|
||||||
|
|
||||||
|
export default function RouteRenderer(props) {
|
||||||
|
const { object } = props;
|
||||||
|
|
||||||
|
const x = object.x;
|
||||||
|
const z = -object.z;
|
||||||
|
|
||||||
|
const upsideDown = useMemo(() => {
|
||||||
|
let rot = object.rot;
|
||||||
|
if (rot < 0) {
|
||||||
|
rot += 360 * Math.ceil(Math.abs(rot) / 360);
|
||||||
|
} else if (rot >= 360) {
|
||||||
|
rot -= 360 * Math.floor(rot / 360);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rot > 180;
|
||||||
|
}, [object.rot]);
|
||||||
|
|
||||||
|
const upsideDownRot = upsideDown ? 90 : -90;
|
||||||
|
const offY = object.track_count === 2 ? -22 : 20;
|
||||||
|
const anchor = upsideDown ? "start" : "end";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<g className="route" transform={`translate(${x}, ${z}) rotate(${object.rot})`}>
|
||||||
|
<g transform={`rotate(90) translate(-80, -40)`}>
|
||||||
|
<ReactSVG
|
||||||
|
src="/assets/route.svg"
|
||||||
|
wrapper='svg'
|
||||||
|
beforeInjection={(svg) => {
|
||||||
|
svg.setAttribute('width', '20mm');
|
||||||
|
svg.setAttribute('height', '20mm');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g transform={`translate(${object.track_offset}, 0) rotate(${upsideDownRot})`}>
|
||||||
|
<text x='0' y={offY} textAnchor={anchor} dominantBaseline="bottom">
|
||||||
|
{object.route_name}
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -28,6 +28,11 @@ const Constants = {
|
|||||||
id: 'signals',
|
id: 'signals',
|
||||||
name: 'Signals',
|
name: 'Signals',
|
||||||
default: true,
|
default: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'routes',
|
||||||
|
name: 'Routes',
|
||||||
|
default: true,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
43
src/model/route.js
Normal file
43
src/model/route.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import SceneryObject from "./scenery-object";
|
||||||
|
|
||||||
|
export default class Route extends SceneryObject {
|
||||||
|
track_count;
|
||||||
|
route_name;
|
||||||
|
electrified;
|
||||||
|
track_offset;
|
||||||
|
category = "routes";
|
||||||
|
type = "Route";
|
||||||
|
|
||||||
|
constructor(prefab_name, x, y, z, rot, track_count, route_name, track_offset, electrified) {
|
||||||
|
super(route_name, x, y, z);
|
||||||
|
|
||||||
|
Object.assign(this, {
|
||||||
|
prefab_name,
|
||||||
|
rot,
|
||||||
|
track_count,
|
||||||
|
route_name,
|
||||||
|
track_offset,
|
||||||
|
electrified,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Route;;ConnectionForest;14418.61;-6.663832;8637.426;0;33.34996;0;2;Ol;2;;True
|
||||||
|
|
||||||
|
static fromText(text) {
|
||||||
|
const values = text.split(";");
|
||||||
|
const route = new Route(
|
||||||
|
values[2], // prefab_name
|
||||||
|
parseFloat(values[3]), // x
|
||||||
|
parseFloat(values[4]), // y
|
||||||
|
parseFloat(values[5]), // z
|
||||||
|
parseFloat(values[7]), // rot
|
||||||
|
parseInt(values[9]), // track_count
|
||||||
|
values[10], // route_name
|
||||||
|
parseFloat(values[11]), // track_offset
|
||||||
|
values[13] === "True" || values[12] === "1" // electrified
|
||||||
|
);
|
||||||
|
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ import StandardTrack from './standard-track';
|
|||||||
import BezierTrack from './bezier-track';
|
import BezierTrack from './bezier-track';
|
||||||
import TrackObject from './track-object';
|
import TrackObject from './track-object';
|
||||||
import Signal from './signal';
|
import Signal from './signal';
|
||||||
|
import Route from './route';
|
||||||
|
|
||||||
export default class Scenery
|
export default class Scenery
|
||||||
{
|
{
|
||||||
@ -67,6 +68,11 @@ export default class Scenery
|
|||||||
return Switch.fromText(text);
|
return Switch.fromText(text);
|
||||||
case 'TrackObject':
|
case 'TrackObject':
|
||||||
return Scenery._parseTrackObject(text);
|
return Scenery._parseTrackObject(text);
|
||||||
|
case 'Route':
|
||||||
|
return Route.fromText(text);
|
||||||
|
case 'Empty':
|
||||||
|
case 'EndRoute':
|
||||||
|
return null;
|
||||||
default:
|
default:
|
||||||
console.warn(`Unknown object type: ${type}`);
|
console.warn(`Unknown object type: ${type}`);
|
||||||
return null;
|
return null;
|
||||||
@ -91,10 +97,6 @@ export default class Scenery
|
|||||||
}
|
}
|
||||||
|
|
||||||
static _parseTrackObject(text) {
|
static _parseTrackObject(text) {
|
||||||
const prefabName = text.split(";", 4)[2];
|
|
||||||
switch(prefabName) {
|
|
||||||
default:
|
|
||||||
return TrackObject.fromText(text);
|
|
||||||
if(Signal.isSignal(text)) {
|
if(Signal.isSignal(text)) {
|
||||||
return Signal.fromText(text);
|
return Signal.fromText(text);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user