Canvas-only 2D game editor/runtime built on PixiJS v8 + Vite + TypeScript. - core: asset model (Scene/Camera/Sprite), scene objects with sparse overrides, property schema + resolve, command stack (undo/redo), serialization and project store interface (16 unit tests) - ui: custom in-canvas widget toolkit (panels, fields, color picker, list/scroll, popup) with a hidden <input> keyboard bridge - editor: asset/hierarchy panels, schema-driven inspector, toolbar - viewport: box rendering, camera frame, selection gizmo, drag/zoom/pan - runtime: world/entity instantiation for play mode, input, camera follow - api: PHP JSON project store with revision counter (409 on conflict) - tools: CDP-based e2e smoke test Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
29 lines
816 B
TypeScript
29 lines
816 B
TypeScript
import type { Project } from '../model/Project';
|
||
import type { Command } from './Command';
|
||
|
||
export class RenameProjectCommand implements Command {
|
||
readonly label = 'Rename project';
|
||
private previous = '';
|
||
|
||
constructor(private readonly name: string) {}
|
||
|
||
execute(project: Project): void {
|
||
this.previous = project.name;
|
||
project.name = this.name;
|
||
}
|
||
|
||
undo(project: Project): void {
|
||
project.name = this.previous;
|
||
}
|
||
}
|
||
|
||
/** "Sprite", "Sprite 2", "Sprite 3" … – the first name not yet used by an asset. */
|
||
export function nextAssetName(project: Project, base: string): string {
|
||
const taken = new Set(project.assets.map((a) => a.name));
|
||
if (!taken.has(base)) return base;
|
||
for (let i = 2; ; i++) {
|
||
const candidate = `${base} ${i}`;
|
||
if (!taken.has(candidate)) return candidate;
|
||
}
|
||
}
|