Files
OpenFrontIO/src/client/graphics/layers/ReplayPanel.ts
T
evanpelle bac29448c2 rename Layer → Controller; drop canvas2D-era interface hooks
The Layer interface dates to the canvas2D era when each entry drew to
the shared 2D context via renderLayer(ctx). With canvas2D gone, nothing
draws there and the renderLayer hook is dead. Rename the interface
("main-thread analog of the worker's Execution") and trim it:

  interface Controller {
    init?: () => void;
    tick?: () => void;
    getTickIntervalMs?: () => number;
  }

renderLayer / shouldTransform / redraw are gone.

Sweep across 28 files: from "./Layer" → "./Controller", implements
Layer → implements Controller, Layer[] / Map<Layer,…> →
Controller[] / Map<Controller,…>. Delete the no-op renderLayer +
shouldTransform method bodies that every layer had inherited.

GameRenderer drops the RedrawGraphicsEvent listener + redraw() fanout
(nothing implements redraw anymore) and the now-unused eventBus
constructor field.

One real case: AttackingTroopsOverlay.renderLayer wasn't a no-op — it
updates DOM label transforms each frame so labels track the WebGL
camera during pan/zoom. Rename to private updateLabelDOM() and start
a self-driven RAF in init() so the per-frame updates keep running.

Class names ending in "Layer" (UILayer, StructureIconsLayer, NameLayer,
etc.) intentionally left as-is — those are separate identifiers and
the class-rename / file-move is a follow-up.

407 tests pass.
2026-05-16 22:35:14 -07:00

108 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { EventBus } from "../../../core/EventBus";
import { GameView } from "../../../core/game/GameView";
import { ReplaySpeedChangeEvent } from "../../InputHandler";
import {
defaultReplaySpeedMultiplier,
ReplaySpeedMultiplier,
} from "../../utilities/ReplaySpeedMultiplier";
import { translateText } from "../../Utils";
import { Controller } from "./Controller";
export class ShowReplayPanelEvent {
constructor(
public visible: boolean = true,
public isSingleplayer: boolean = false,
) {}
}
@customElement("replay-panel")
export class ReplayPanel extends LitElement implements Controller {
public game: GameView | undefined;
public eventBus: EventBus | undefined;
@property({ type: Boolean })
visible: boolean = false;
@state()
private _replaySpeedMultiplier: number = defaultReplaySpeedMultiplier;
@property({ type: Boolean })
isSingleplayer = false;
createRenderRoot() {
return this; // Enable Tailwind CSS
}
init() {
if (this.eventBus) {
this.eventBus.on(ShowReplayPanelEvent, (event: ShowReplayPanelEvent) => {
this.visible = event.visible;
this.isSingleplayer = event.isSingleplayer;
});
this.eventBus.on(
ReplaySpeedChangeEvent,
(event: ReplaySpeedChangeEvent) => {
this._replaySpeedMultiplier = event.replaySpeedMultiplier;
this.requestUpdate();
},
);
}
}
getTickIntervalMs() {
return 1000;
}
tick() {
if (!this.visible) return;
this.requestUpdate();
}
onReplaySpeedChange(value: ReplaySpeedMultiplier) {
this._replaySpeedMultiplier = value;
this.eventBus?.emit(new ReplaySpeedChangeEvent(value));
}
render() {
if (!this.visible) return html``;
return html`
<div
class="p-2 bg-gray-800/92 backdrop-blur-sm shadow-xs min-[1200px]:rounded-lg rounded-l-lg"
@contextmenu=${(e: Event) => e.preventDefault()}
>
<label class="block mb-2 text-white" translate="no">
${this.game?.config()?.isReplay()
? translateText("replay_panel.replay_speed")
: translateText("replay_panel.game_speed")}
</label>
<div class="grid grid-cols-4 gap-2">
${this.renderSpeedButton(ReplaySpeedMultiplier.slow, "×0.5")}
${this.renderSpeedButton(ReplaySpeedMultiplier.normal, "×1")}
${this.renderSpeedButton(ReplaySpeedMultiplier.fast, "×2")}
${this.renderSpeedButton(
ReplaySpeedMultiplier.fastest,
translateText("replay_panel.fastest_game_speed"),
)}
</div>
</div>
`;
}
private renderSpeedButton(value: ReplaySpeedMultiplier, label: string) {
const backgroundColor =
this._replaySpeedMultiplier === value ? "bg-malibu-blue" : "";
return html`
<button
class="py-0.5 px-1 text-sm text-white rounded-sm border transition border-gray-500 ${backgroundColor} hover:border-gray-200"
@click=${() => this.onReplaySpeedChange(value)}
>
${label}
</button>
`;
}
}