Compare commits

2 Commits

Author SHA1 Message Date
10f6d92b7f removes bundle from output 2025-02-15 06:42:13 -07:00
968867c5d9 Fixed ghost track rotation on rear ends
Recalculation on track edit end
Changes rendering of ties to be evenly spaced
Fixes ghost and held track rendering
2025-02-15 06:40:39 -07:00
6 changed files with 41 additions and 2862 deletions

2841
bundle.js

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
type ContextStore = Record<string, any>; type ContextStore = Record<string, any>;
const contextStack: ContextStore[] = [];
const defaultContext: ContextStore = {}; const defaultContext: ContextStore = {};
const contextStack: ContextStore[] = [defaultContext];
const debug = JSON.parse(localStorage.getItem("debug") || "false"); const debug = JSON.parse(localStorage.getItem("debug") || "false");

View File

@@ -74,10 +74,10 @@ setInterval(() => {
fpsEl.id = "fps"; fpsEl.id = "fps";
document.body.appendChild(fpsEl); document.body.appendChild(fpsEl);
} }
const fPerc = frameRate / 60; // const fPerc = frameRate / 60;
if (fPerc < 0.6) { // if (fPerc < 0.6) {
state.optimizePerformance(fPerc); // state.optimizePerformance(fPerc);
} // }
fpsEl.textContent = frameRate.toFixed(1) + " fps"; fpsEl.textContent = frameRate.toFixed(1) + " fps";
}, 1000); }, 1000);

View File

@@ -237,10 +237,10 @@ export class PathSegment {
resolution = 1, resolution = 1,
targetLength?: number, targetLength?: number,
) { ) {
const points: Vector[] = []; const points: [Vector, number][] = [];
points.push(this.points[0]); points.push([this.points[0], this.tangent(0).heading()]);
let prev = points[0]; let [prev] = points[0];
let distSinceLastEvenPoint = 0; let distSinceLastEvenPoint = 0;
let t = 0; let t = 0;
@@ -258,7 +258,7 @@ export class PathSegment {
Vector.sub(point, prev).normalize().mult(overshoot), Vector.sub(point, prev).normalize().mult(overshoot),
); );
distSinceLastEvenPoint = overshoot; distSinceLastEvenPoint = overshoot;
points.push(evenPoint); points.push([evenPoint, this.tangent(t).heading()]);
prev = evenPoint; prev = evenPoint;
} }
@@ -278,7 +278,7 @@ export class PathSegment {
Vector.sub(point, prev).normalize().mult(overshoot), Vector.sub(point, prev).normalize().mult(overshoot),
); );
distSinceLastEvenPoint = overshoot; distSinceLastEvenPoint = overshoot;
points.push(evenPoint); points.push([evenPoint, this.tangent(t).heading()]);
prev = evenPoint; prev = evenPoint;
} }
@@ -304,7 +304,7 @@ export class PathSegment {
const curveLength = this.startingLength; const curveLength = this.startingLength;
const points = this.calculateEvenlySpacedPoints(1, 1, curveLength + 1); const points = this.calculateEvenlySpacedPoints(1, 1, curveLength + 1);
if (points.length >= curveLength) { if (points.length >= curveLength) {
this.points[3].set(points[curveLength]); this.points[3].set(points[curveLength][0]);
} }
} }

View File

@@ -121,18 +121,20 @@ export class EditTrackState extends State<States> {
); );
this.ghostRotated = true; this.ghostRotated = true;
break; break;
case "back": case "back": {
this.ghostSegment.setPositionByPoint( this.ghostSegment.setPositionByPoint(
this.closestEnd.pos, this.closestEnd.pos,
this.ghostSegment.points[3], this.ghostSegment.points[3],
); );
const ghostEndTangent = this.ghostSegment.tangent(1);
// this.ghostSegment.points[3] = this.closestEnd.pos; // this.ghostSegment.points[3] = this.closestEnd.pos;
!this.ghostRotated && this.ghostSegment.rotateAboutPoint( !this.ghostRotated && this.ghostSegment.rotateAboutPoint(
this.closestEnd.tangent.heading(), this.closestEnd.tangent.heading() - ghostEndTangent.heading(),
this.ghostSegment.points[3], this.ghostSegment.points[3],
); );
this.ghostRotated = true; this.ghostRotated = true;
break; break;
}
} }
// } else if (closestEnd) { // } else if (closestEnd) {
// this.closestEnd = closestEnd; // this.closestEnd = closestEnd;
@@ -258,11 +260,11 @@ export class EditTrackState extends State<States> {
const doodler = getContextItem<Doodler>("doodler"); const doodler = getContextItem<Doodler>("doodler");
this.layers.push( this.layers.push(
doodler.createLayer(() => { doodler.createLayer(() => {
this.selectedSegment?.draw(); this.selectedSegment?.draw(false, true);
if (this.ghostSegment) { if (this.ghostSegment) {
doodler.drawWithAlpha(0.5, () => { doodler.drawWithAlpha(0.5, () => {
if (!this.ghostSegment) return; if (!this.ghostSegment) return;
this.ghostSegment.draw(); this.ghostSegment.draw(false, true);
if (getContextItemOrDefault("debug", false)) { if (getContextItemOrDefault("debug", false)) {
const colors = getContextItem<string[]>("colors"); const colors = getContextItem<string[]>("colors");
for ( for (
@@ -396,6 +398,9 @@ export class EditTrackState extends State<States> {
getContextItem<Doodler>("doodler").deleteLayer(layer); getContextItem<Doodler>("doodler").deleteLayer(layer);
} }
const track = getContextItem<TrackSystem>("track");
track.recalculateAll();
const inputManager = getContextItem<InputManager>("inputManager"); const inputManager = getContextItem<InputManager>("inputManager");
inputManager.offKey("e"); inputManager.offKey("e");
inputManager.offKey("w"); inputManager.offKey("w");

View File

@@ -29,6 +29,13 @@ export class TrackSystem {
} }
} }
recalculateAll() {
for (const segment of this.segments.values()) {
segment.recalculateRailPoints();
segment.length = segment.calculateApproxLength();
}
}
registerSegment(segment: TrackSegment) { registerSegment(segment: TrackSegment) {
segment.setTrack(this); segment.setTrack(this);
this.segments.set(segment.id, segment); this.segments.set(segment.id, segment);
@@ -39,6 +46,9 @@ export class TrackSystem {
s.backNeighbours = s.backNeighbours.filter((n) => n !== segment); s.backNeighbours = s.backNeighbours.filter((n) => n !== segment);
s.frontNeighbours = s.frontNeighbours.filter((n) => n !== segment); s.frontNeighbours = s.frontNeighbours.filter((n) => n !== segment);
} }
const ends = this.ends.get(segment);
this.ends.delete(segment);
this.endArray = this.endArray.filter((e) => !ends?.includes(e));
} }
draw(showControls = false) { draw(showControls = false) {
@@ -291,7 +301,7 @@ export class TrackSegment extends PathSegment {
this.track = t; this.track = t;
} }
override draw(showControls = false) { override draw(showControls = false, recalculateRailPoints = false) {
// if (showControls) { // if (showControls) {
// this.doodler.drawBezier( // this.doodler.drawBezier(
// this.points[0], // this.points[0],
@@ -320,15 +330,17 @@ export class TrackSegment extends PathSegment {
}); });
} }
const ties = Math.ceil(this.length / 10); const spacing = Math.ceil(this.length / 10);
for (let i = 0; i < ties; i++) { const points = this.calculateEvenlySpacedPoints(this.length / spacing);
const t = i / ties; for (let i = 0; i < points.length - 1; i++) {
const p = this.getPointAtT(t); // const t = i / ties;
// const p = this.getPointAtT(t);
const [p, t] = points[i];
// this.doodler.drawCircle(p, 2, { // this.doodler.drawCircle(p, 2, {
// color: "red", // color: "red",
// weight: 3, // weight: 3,
// }); // });
this.doodler.drawRotated(p, this.tangent(t).heading(), () => { this.doodler.drawRotated(p, t, () => {
this.doodler.line(p, p.copy().add(0, 10), { this.doodler.line(p, p.copy().add(0, 10), {
color: "#291b17", color: "#291b17",
weight: 4, weight: 4,
@@ -348,6 +360,9 @@ export class TrackSegment extends PathSegment {
}); });
} }
if (recalculateRailPoints) {
this.recalculateRailPoints();
}
this.doodler.deferDrawing( this.doodler.deferDrawing(
() => { () => {
this.doodler.drawLine(this.normalPoints, { this.doodler.drawLine(this.normalPoints, {