Windows with willowui
SceneWindowLayer (the ui family) connects a SceneStack to willowui windows. Each scene gets its own WindowManager, so its windows hide when another scene covers it and go away when it exits. A separate set of screen windows stays above every scene.
The layer only watches the stack. It never pushes, pops or creates scenes, and it leaves dragging, z-order, modal overlays and widget focus to willowui.
Your project lists willowui too
gamekit brings willowui for its own use. As soon as your own code imports from willowui, list it in your packages as well, pointing at the same folder gamekit uses (two different sources for one package name is an error):
json5
{
entry: "ui.tks",
systems: ["willow", "bitmap"],
packages: {
gamekit: "../gamekit-tks",
willowui: "../willowui-tks",
},
window: { title: "Windows", width: 640, height: 480 },
}Scene windows and screen windows
ts
import { Label } from "willowui/src/core/label";
import { Window, WindowManager } from "willowui/src/widgets/containers/window";
import { AppScene, SceneStack } from "gamekit";
import { SceneWindowLayer } from "gamekit/src/ui";
const scenes: SceneStack = new SceneStack();
const layers: SceneWindowLayer = new SceneWindowLayer(scenes, (): WindowManager => new WindowManager());
async function main(): Promise<void> {
const play: AppScene = new AppScene("play");
await scenes.start(play);
// A scene window belongs to one scene: it hides when another scene covers it.
const inventory: Window = new Window("inventory", "Inventory", "default", 18.0);
inventory.setSize(240.0, 160.0);
inventory.body.addChild(new Label("hint", "Hidden while paused.", "default", 14.0));
engine.root2d.add(inventory.node);
layers.openSceneWindow(play, inventory);
// A screen window stays above every scene, across push, pop and replace.
const chat: Window = new Window("chat", "Chat", "default", 18.0);
chat.setSize(240.0, 120.0);
engine.root2d.add(chat.node);
layers.openScreenWindow(chat);
await scenes.push(new AppScene("pause")); // the inventory hides, chat stays
}
await main();| Call | What it does |
|---|---|
new SceneWindowLayer(scenes, createManager?, keyboardHandler?, widgetFocus?) | Watches a stack. createManager returns a fresh willowui WindowManager for each scene. |
openSceneWindow(scene, window) | Adds a window to that scene's manager. Covering the scene suspends the manager; uncovering resumes it; exiting the scene removes the window. |
openScreenWindow(window) | Adds a window to screenWindows, which stays across push, pop and replace. |
closeWindow(window) | Removes a window from its manager without disposing it. You created it, so you dispose it. |
sceneWindows(scene) | That scene's manager. |
dispose() | Ends the layer with the same ownership rule. |
Focus
One group has focus at a time. The layer checks, in order:
- A visible modal among the screen windows.
- A modal on the ready top scene.
- The floating window clicked last.
- The top scene itself.
Opening a modal focuses it. clickWindow(window) focuses a floating window; clickScene() blurs every window manager and gives focus back to the scene, so the scene's own arrow-key handling works again.
Keyboard input goes to the optional keyboardHandler(window, input) while a window has focus. Otherwise dispatchKeyboard(input) offers it to the top scene's handleInput. Pass a willowui FocusManager as widgetFocus and the focused window is handed to it, so tabbing between widgets stays inside willowui.
The window-layers example walks through all of this in a window.
Reference: SceneWindowLayer, FocusGroupResolver.