Courage.Layout#
require("Courage.Layout") loads a vanilla J2D .blo screen, optionally plays linked animations, and rasterizes the result into the CReact asset registry. Panels can show the result with an image primitive.
Use this when you want to use the original game menus in a mod overlay.
Loading the module#
Active mod context#
Layout.capture and Layout.update require an active mod folder (same rule as Courage.Assets). Call them from init() or other load-time setup, not from deferred callbacks after init finishes.
API#
| Function | Returns | Description |
|---|---|---|
Layout.load(opts) | boolean | Load a BLO screen. See load options. Unloads any previous layout. |
Layout.unload() | (none) | Tear down the loaded screen, animations, and captured asset. |
Layout.getSize() | width, height | Layout size in pixels, or nil, nil when nothing is loaded. |
Layout.capture(rel?, opts?) | assetKey, w, h | Rasterize the current frame and register RGBA pixels. Default rel is "cache/layout.png". Returns nil, err on failure. See capture options. |
Layout.update(rel?) | boolean | Re-rasterize at the current animation frame and refresh the asset registered by capture. |
Layout.setFrame(frame) | (none) | Jump to an animation frame (applied on the next capture/update). |
Layout.advance(delta, loop?) | number | Advance by delta seconds. loop defaults to true. Returns the new frame. |
Layout.getFrameMax() | number | Max frame across loaded BCK/BPK/BTK clips, or 0 when none are set. |
Layout.paneBounds(pane, relativeTo?) | x, y, w, h | Returns coordinates and dimensions of a pane. Returns nil if not found. |
Layout.listPanes() | string[] | Returns a list of all pane names in the layout. |
Capture options#
Layout.capture takes an optional opts table to crop or pad the captured area:
| Field | Type | Default | Description |
|---|---|---|---|
pane | string | nil | Pane name to restrict the capture to. Only the area occupied by this pane is captured. |
pad | number | 0 | Extra padding pixels to add around the captured area. |
padTop | number | -1 | Top padding (overrides pad). |
padRight | number | -1 | Right padding (overrides pad). |
padBottom | number | -1 | Bottom padding (overrides pad). |
padLeft | number | -1 | Left padding (overrides pad). |
Load options#
Layout.load takes one table:
| Field | Type | Default | Description |
|---|---|---|---|
blo | string | (required) | BLO resource name inside the archive (for example "zelda_2d_item_select.blo"). |
priority | number | 0x20000 | J2D draw priority passed to setPriority. |
archive | string | nil | Path to a mod archive when the BLO is not in the main 2D archive. |
msgArchive | number | 0 | Message archive index (for example 1 = msgres01) when loading from extracted msg data. |
useMain2D | boolean | false | Use dComIfGp_getMain2DArchive() instead of archive / msgArchive. |
bck | string | nil | Skeletal animation resource name. |
bpk | string | nil | Color pattern animation resource name. |
btk | string | nil | Texture SRT animation resource name. |
animPane | string | nil | Pane tag to attach BCK/BPK (for example "moya00"). |
animArchive | string | nil | Archive path for animation files when they are not in the BLO archive. |
animMsgArchive | number | -1 | Msg archive index for animation files. |
animUseMain2D | boolean | same as useMain2D | Load animation clips from the main 2D archive. |
Example#
local Layout = require("Courage.Layout")
local UI = require("Courage.UI")
local MOD_ID = "item-picker"
function ItemPicker:init()
if not Layout.load({
blo = "zelda_2d_item_select.blo",
useMain2D = true,
}) then
return
end
local key, w, h = Layout.capture("ui/item_select.png")
if not key then return end
UI.setState(MOD_ID, { bg = key, w = w, h = h })
UI.showPopup(MOD_ID)
end
function ItemPicker:shutdown()
Layout.unload()
UI.hidePopup()
end
return ItemPicker
import * as Layout from "Courage.Layout"
import * as UI from "Courage.UI"
const MOD_ID = "item-picker"
ItemPicker.init = function () {
if (!Layout.load({
blo: "zelda_2d_item_select.blo",
useMain2D: true,
})) {
return
}
const [key, w, h] = Layout.capture("ui/item_select.png")
if (!key) return
UI.setState(MOD_ID, { bg: key, w, h })
UI.showPopup(MOD_ID)
}
ItemPicker.shutdown = function () {
Layout.unload()
UI.hidePopup()
}
See also#
- Courage.Assets, logical asset keys and CReact texture resolution
- Courage.UI,
showPopupfor in-world overlays - User Interfaces with CReact, panel and popup bundles
- Asset modding guide,
.bloformat overview