The scene view and the animation preview share one camera, the three form dialogs one base, and keys are found through one set of helpers (#85)
game-maker / gate (push) Successful in 1m36s
game-maker / suite (push) Successful in 5m41s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5 committed 2026-09-17 14:19:53 +02:00
1 parent bf02c9e8b3
commit 2a390e52ff
22 files changed
+418 -452

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
import { Button, type ButtonOptions, HStack, Label, Popup, Spacer, Theme, type Widget } from '../ui';
/** Matches the inspector's label column. */
const LABEL_WIDTH = 76;
/**
* A small modal form – the texture's Slice dialog, the timeline's row and frames dialogs: a bold
* title, rows led by a label in the inspector's label column, Cancel and a confirming button last.
*/
export abstract class FormDialog extends Popup {
protected constructor(minWidth: number, title: string) {
super({ modal: true, padding: Theme.padding * 2, gap: Theme.gap });
this.minWidth = minWidth;
this.content.add(new Label(title, { style: 'bodyBold' }));
}
protected fieldLabel(text: string): Label {
const label = new Label(text, { style: 'muted' });
label.minWidth = LABEL_WIDTH;
return label;
}
/** A row of `widgets`, left-aligned at the height of an inspector row. */
protected formRow(...widgets: Widget[]): HStack {
const row = new HStack({ gap: Theme.gap, align: 'center' });
row.minHeight = Theme.rowHeight;
for (const widget of widgets) row.add(widget);
row.add(new Spacer(), 1);
return row;
}
/** Cancel and the confirming button, right-aligned; the dialog closes before `onConfirm` runs. */
protected addButtons(text: string, variant: ButtonOptions['variant'], onConfirm: () => void): Button {
const buttons = new HStack({ gap: Theme.gap, align: 'center' });
buttons.add(new Spacer(), 1);
const cancel = new Button('Cancel');
cancel.onClick = this.closeThen();
buttons.add(cancel);
const confirm = new Button(text, { variant });
confirm.onClick = this.closeThen(onConfirm);
buttons.add(confirm);
this.content.add(buttons);
return confirm;
}
}
/** One open dialog of a kind at a time: opening the next closes the last. `current` is for the check scripts. */
export function dialogSlot<T extends Popup>(): { current(): T | null; open(dialog: T): T } {
let current: T | null = null;
return {
current: () => current,
open(dialog) {
current?.close();
current = dialog;
dialog.onClose = () => {
if (current === dialog) current = null;
};
dialog.openCentered();
return dialog;
},
};
}