Show only the game view in fullscreen, in the editor and the link (#267)
A game is easier to judge and to play without the editor around it. The Game tab and the game link now both have a button that puts the game view itself into fullscreen, not just the browser window. - The Game tab header has a fullscreen button on the right. It hides toolbar, panels, tab headers and console and keeps the zoom from the picker. A running game keeps running. - A corner button at the top right, or Esc, leaves fullscreen and puts the view back into the tab where it was. - The game link shows the same corner button. Over a running game it hides after 2 s without mouse movement and returns on the next move. - A click on the corner button never reaches the game. - Stop ends fullscreen. Stop switches back to the Scene tab, and any switch away from the Game tab ends fullscreen, so no empty screen is left behind. - src/viewport/fullscreen.ts wraps the Fullscreen API and holds the rule for when the button shows. FullscreenCorner.ts is the button used by both pages. Two SVG icons are new. - Editor.showGameFullscreen moves the GameViewport into the root while fullscreen is on. Tests: - ./check.sh: 195 files, 2815 tests, exit 0 (3 new unit tests). - e2e 60: 2 new checks for the corner button on the game link. - e2e 61 (new): 4 checks for fullscreen in the editor. - Full e2e run (local): ALL PASSED, 1580 checks. - Counter-checks fail as expected: rule without "no game running", no stopPropagation (60h), no end on tab switch (61c), no reparenting of the view (61a). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
24d360aeec
commit
cab1c0177f
17 files changed
+356
-8
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import type { Application } from 'pixi.js';
|
||||
import type { Application, Container } from 'pixi.js';
|
||||
import { ui } from '../../ui';
|
||||
import type { Editor } from '../Editor';
|
||||
import type { SnapToggle } from '../graph/SnapToggle';
|
||||
import type { EditorState } from '../state';
|
||||
@@ -18,6 +19,16 @@ export function centreOf(widget: { getGlobalPosition(): { x: number; y: number }
|
||||
return { x: p.x + widget.w / 2, y: p.y + widget.h / 2 };
|
||||
}
|
||||
|
||||
/** Whether `node` and everything it hangs from are visible, up to a stage. */
|
||||
export function shownOnStage(node: Container): boolean {
|
||||
let current = node;
|
||||
while (current.visible) {
|
||||
if (!current.parent) return current === ui().app.stage;
|
||||
current = current.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** A tab's magnet (#194): where to click it, how big it is drawn, and whether it is on. */
|
||||
export function snapButton(snap: SnapToggle): {
|
||||
x: number;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { currentVisibilityPopup } from '../panels/SceneVisibilityPopup';
|
||||
import { currentTilemapWidgets, paintedLayerId, paintedTilemap } from '../panels/TilemapPanel';
|
||||
import type { TilemapTool } from '../state';
|
||||
import { rectOf } from '../textProbe';
|
||||
import { centreOf, type HookContext } from './hookHelpers';
|
||||
import { centreOf, type HookContext, shownOnStage } from './hookHelpers';
|
||||
|
||||
/** The Scene and Game tabs, the tilemap painted in the scene view, and the Container tab. */
|
||||
export function sceneHooks({ state, editor }: HookContext) {
|
||||
@@ -96,6 +96,16 @@ export function sceneHooks({ state, editor }: HookContext) {
|
||||
picker: centreOf(gamePane.scalePicker),
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Fullscreen of the game view (#267): whether the view is moved to the root, whether the browser
|
||||
* is in fullscreen, the header button, and the corner button while it shows.
|
||||
*/
|
||||
gameFullscreen: () => ({
|
||||
on: gameView.isFullscreen,
|
||||
document: document.fullscreenElement !== null,
|
||||
headerButton: shownOnStage(gamePane.fullscreenButton) ? centreOf(gamePane.fullscreenButton) : null,
|
||||
corner: shownOnStage(gameView.fullscreenButton) ? centreOf(gameView.fullscreenButton) : null,
|
||||
}),
|
||||
/** Which typeface a text ended up drawn in, and how wide it made it. */
|
||||
textInfo: (id: string) => viewport.textInfo(id),
|
||||
gameTextInfo: (id: string) => gameView.textInfo(id),
|
||||
|
||||
Reference in new issue
Block a user