Camera view frame, viewport clipping, overlay layer for editor symbols
- Camera assets get width/height properties; play mode renders only the camera frame (letterboxed, masked, culled) and nothing without a camera - Remove demo arrow-key/camera-follow systems from play mode - Clip world and gizmos to the viewport (selection frame no longer leaks over the left panel) - Blur focused widget on pointerdown outside it so inspector edits commit before selection changes - Separate objects/overlay layers so camera symbols always render on top - Add tools/seed-demo.mjs for reproducible E2E runs Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5a46124454
commit
aaa8154adf
11 files changed
+307
-142
No files matched your search
@@ -29,6 +29,20 @@ export class FocusManager {
|
||||
this.focus(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A pointer went down on `target`. If that is outside the focused widget, the widget
|
||||
* loses focus *before* the press is handled, so a text field commits its edit before
|
||||
* whatever the click triggers (selection change, inspector rebuild, …) can destroy it.
|
||||
*/
|
||||
blurIfOutside(target: Container | null): void {
|
||||
const w = this.focusedWidget;
|
||||
if (!w) return;
|
||||
for (let node = target; node; node = node.parent) {
|
||||
if (node === w) return;
|
||||
}
|
||||
this.focus(null);
|
||||
}
|
||||
|
||||
/** Drop focus if the focused widget was removed from the tree or hidden. */
|
||||
validate(): void {
|
||||
const w = this.focusedWidget;
|
||||
|
||||
+4
-1
@@ -1,4 +1,4 @@
|
||||
import type { Application, Container } from 'pixi.js';
|
||||
import type { Application, Container, FederatedPointerEvent } from 'pixi.js';
|
||||
import { FocusManager } from './FocusManager';
|
||||
import { KeyboardBridge } from './KeyboardBridge';
|
||||
|
||||
@@ -18,6 +18,9 @@ let context: UIContext | null = null;
|
||||
|
||||
export function initUI(app: Application, root: Container, overlay: Container): UIContext {
|
||||
context = { app, focus: new FocusManager(root), keyboard: new KeyboardBridge(), overlay };
|
||||
// Capture phase on the stage runs before any widget handler: a press outside the focused
|
||||
// widget blurs it (committing text edits) before the press can change selection.
|
||||
app.stage.addEventListener('pointerdown', (e) => context?.focus.blurIfOutside((e as FederatedPointerEvent).target as Container), { capture: true });
|
||||
// Clicking the canvas must not steal DOM focus from the keyboard bridge input.
|
||||
app.canvas.addEventListener('mousedown', (e) => e.preventDefault());
|
||||
app.canvas.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||
|
||||
Reference in new issue
Block a user