widget manager refact
This commit is contained in:
@@ -49,7 +49,7 @@ All game code lives in one flat package, `inc`. There are no subdirectories: a
|
|||||||
file's name carries the structure, in the form `[category].[name].go`.
|
file's name carries the structure, in the form `[category].[name].go`.
|
||||||
|
|
||||||
- The category is always **singular**: `item`, `scene`, `background`,
|
- The category is always **singular**: `item`, `scene`, `background`,
|
||||||
`character`, `dialog`, `script`, `world`, `ui`, `theme`, `names`.
|
`character`, `dialog`, `script`, `world`, `widget`, `ui`, `theme`, `names`.
|
||||||
- `[category].manager.go` is the file that ties a category together — its
|
- `[category].manager.go` is the file that ties a category together — its
|
||||||
entity type and whatever else the category shares.
|
entity type and whatever else the category shares.
|
||||||
- Every other file in a category holds exactly one entity: one scene, one
|
- Every other file in a category holds exactly one entity: one scene, one
|
||||||
@@ -65,9 +65,10 @@ inc/theme.manager.go the Theme alias and the colour helpers
|
|||||||
inc/theme.realworld.go realworld-93
|
inc/theme.realworld.go realworld-93
|
||||||
inc/theme.nokia_punk.go nokia-punk
|
inc/theme.nokia_punk.go nokia-punk
|
||||||
inc/world.manager.go unsaved runtime state
|
inc/world.manager.go unsaved runtime state
|
||||||
inc/world.action.go custom actions and the action pump
|
inc/world.action.go custom actions
|
||||||
inc/ui.manager.go HUD layout and widget registration
|
inc/widget.manager.go the Widget alias, HUD layout, the visibility gate
|
||||||
inc/ui.*.go custom widgets, coloured text
|
inc/widget.*.go one widget per file, registering itself
|
||||||
|
inc/ui.text.go coloured text on a scratch image
|
||||||
inc/background.*.go one image asset per scene
|
inc/background.*.go one image asset per scene
|
||||||
inc/character.*.go the cast, tapes included
|
inc/character.*.go the cast, tapes included
|
||||||
inc/item.*.go inventory
|
inc/item.*.go inventory
|
||||||
@@ -84,7 +85,7 @@ Every category that owns a collection of entities has a manager, and they are
|
|||||||
all the engine's own `inkwell.Manager[T]` — the same registry type the `*Game`
|
all the engine's own `inkwell.Manager[T]` — the same registry type the `*Game`
|
||||||
hangs its content off. The game defines no registry of its own.
|
hangs its content off. The game defines no registry of its own.
|
||||||
|
|
||||||
All seven are declared together, in `boot.go`, so the list of what the game
|
All eight are declared together, in `boot.go`, so the list of what the game
|
||||||
holds is one block rather than a line hidden in each category file:
|
holds is one block rather than a line hidden in each category file:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -96,6 +97,7 @@ var (
|
|||||||
SceneManager = inkwell.NewManager[Scene]()
|
SceneManager = inkwell.NewManager[Scene]()
|
||||||
ScriptManager = inkwell.NewManager[Script]()
|
ScriptManager = inkwell.NewManager[Script]()
|
||||||
ThemeManager = inkwell.NewManager[Theme]()
|
ThemeManager = inkwell.NewManager[Theme]()
|
||||||
|
WidgetManager = inkwell.NewManager[Widget]()
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -146,6 +148,43 @@ into one.
|
|||||||
Nothing may depend on it — including the order the arrow keys walk the scenes,
|
Nothing may depend on it — including the order the arrow keys walk the scenes,
|
||||||
which is simply the order the files sit in.
|
which is simply the order the files sit in.
|
||||||
|
|
||||||
|
### Widgets name their layer instead of their order
|
||||||
|
|
||||||
|
A widget is a file like any other entity — `widget.<name>.go`, one widget,
|
||||||
|
registering itself in an `init()` — and that includes the engine's own widgets,
|
||||||
|
which the game registers as literals the same way it registers a background:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.Cursor{
|
||||||
|
Name: "cursor",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
What a widget cannot take from alphabetical registration is its place in the
|
||||||
|
stack: the frame has to be drawn under the slots that sit on it, the cursor over
|
||||||
|
everything, and the use-with guard has to see a click after the HUD has had it.
|
||||||
|
So a widget declares a layer rather than inheriting one from the order it was
|
||||||
|
registered in — `inkwell.LayerScene`, `LayerPanel`, `LayerHUD`, `LayerSpeech`,
|
||||||
|
`LayerDialog`, `LayerMenu`, `LayerCurtain`, `LayerCursor`. The engine draws from
|
||||||
|
the bottom layer up and ticks from the top layer down, and registration order
|
||||||
|
only decides ties inside one layer:
|
||||||
|
|
||||||
|
```go
|
||||||
|
func (h *hudFrame) Layer() inkwell.Layer { return inkwell.LayerPanel }
|
||||||
|
```
|
||||||
|
|
||||||
|
A widget that says nothing sits on `LayerHUD`; ours all say it, because the
|
||||||
|
layer is the one thing about a widget the file cannot show. `gate`, the wrapper
|
||||||
|
that hides a widget outside `ModePlay`, returns `inkwell.LayerOf` of the widget
|
||||||
|
it wraps, so wrapping never moves anything.
|
||||||
|
|
||||||
|
Two widgets are worth knowing about because they are not decoration: `pump`
|
||||||
|
drives `World.PumpTick`, which is what runs every queued action, and
|
||||||
|
`usewith_guard` sits on `LayerScene` so that it ticks last and can answer a
|
||||||
|
use-with pair nobody authored.
|
||||||
|
|
||||||
### Handing a category to the engine
|
### Handing a category to the engine
|
||||||
|
|
||||||
Nothing is copied. `inkwell.NewGame` builds its own empty managers, and `New`
|
Nothing is copied. `inkwell.NewGame` builds its own empty managers, and `New`
|
||||||
@@ -159,6 +198,7 @@ g.DialogueManager = DialogManager
|
|||||||
g.ItemManager = ItemManager
|
g.ItemManager = ItemManager
|
||||||
g.SceneManager = SceneManager
|
g.SceneManager = SceneManager
|
||||||
g.ScriptManager = ScriptManager
|
g.ScriptManager = ScriptManager
|
||||||
|
g.WidgetManager = WidgetManager
|
||||||
ThemeManager.Each(g.ThemeManager.Register)
|
ThemeManager.Each(g.ThemeManager.Register)
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -221,7 +261,7 @@ constants in `names.manager.go`, the colour tokens, and the action constructors
|
|||||||
(`TapeSay`, `Paused`, `SetMode`, `EnterScene`, `Back`, `Fn`).
|
(`TapeSay`, `Paused`, `SetMode`, `EnterScene`, `Back`, `Fn`).
|
||||||
|
|
||||||
Everything else is machinery and stays unexported: the HUD widgets
|
Everything else is machinery and stays unexported: the HUD widgets
|
||||||
(`tapeSlots`, `letterbox`, `hudFrame`, …), `registerUI`, the runners,
|
(`tapeSlots`, `letterbox`, `hudFrame`, …), `gated`, the runners,
|
||||||
`prepareScene`, `sceneDefaults`, `fillSelectorPins`.
|
`prepareScene`, `sceneDefaults`, `fillSelectorPins`.
|
||||||
|
|
||||||
The word is **scene**, the engine's own. The wiki and the concept-art deck count
|
The word is **scene**, the engine's own. The wiki and the concept-art deck count
|
||||||
|
|||||||
@@ -109,9 +109,9 @@ Every pixel it gives back is a pixel of art.
|
|||||||
InventoryBar TapeSlots TapeChannel
|
InventoryBar TapeSlots TapeChannel
|
||||||
```
|
```
|
||||||
|
|
||||||
Every vertical measurement derives from `ui.LineH` (glyph cell + leading) and
|
Every vertical measurement derives from `LineH` (glyph cell + leading) and from
|
||||||
from `ui.ScreenH`, not from the wireframe deck's ratios, so the layout cannot
|
`ScreenH`, both in `widget.manager.go`, not from the wireframe deck's ratios, so
|
||||||
drift out of step with the font — or with the art — again;
|
the layout cannot drift out of step with the font — or with the art — again;
|
||||||
`TestLayoutFitsTheFont` guards it. The tape channel comes out at 4 rows of 38
|
`TestLayoutFitsTheFont` guards it. The tape channel comes out at 4 rows of 38
|
||||||
columns, which is about one and a half of Dex's remarks on screen at once.
|
columns, which is about one and a half of Dex's remarks on screen at once.
|
||||||
|
|
||||||
@@ -161,8 +161,10 @@ main.go flags + inkwell.Run
|
|||||||
inc/boot.go the managers, and New(Opts)
|
inc/boot.go the managers, and New(Opts)
|
||||||
inc/names.manager.go entity names and world-state keys
|
inc/names.manager.go entity names and world-state keys
|
||||||
inc/theme.*.go realworld-93 + nokia-punk
|
inc/theme.*.go realworld-93 + nokia-punk
|
||||||
inc/world.*.go unsaved runtime state, custom actions, action pump
|
inc/world.*.go unsaved runtime state and custom actions
|
||||||
inc/ui.*.go HUD: layout, custom widgets, coloured text
|
inc/widget.manager.go HUD layout and the widget registration list
|
||||||
|
inc/widget.*.go one widget per file
|
||||||
|
inc/ui.text.go coloured text
|
||||||
inc/<kind>.<name>.go one file per registered entity, by kind
|
inc/<kind>.<name>.go one file per registered entity, by kind
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -195,7 +197,7 @@ Every category owns a manager, and they are all the engine's own
|
|||||||
`inkwell.Manager[T]` — the same registry the `*Game` hangs its content off, kept
|
`inkwell.Manager[T]` — the same registry the `*Game` hangs its content off, kept
|
||||||
in registration order and addressed by name. There is no second registry type
|
in registration order and addressed by name. There is no second registry type
|
||||||
here: the entity types are aliases of engine structs, so they already satisfy
|
here: the entity types are aliases of engine structs, so they already satisfy
|
||||||
`inkwell.Named` and need no help reading their own name. The seven of them are
|
`inkwell.Named` and need no help reading their own name. The eight of them are
|
||||||
declared as one block in `boot.go`, and a category's manager file is left
|
declared as one block in `boot.go`, and a category's manager file is left
|
||||||
holding the alias:
|
holding the alias:
|
||||||
|
|
||||||
@@ -215,6 +217,17 @@ func init() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Widgets go the same way, the engine's own included: `widget.cursor.go` registers
|
||||||
|
an `inkwell.Cursor` exactly as `background.street.go` registers an image. What
|
||||||
|
they cannot take from alphabetical order is their place in the stack, so each
|
||||||
|
widget names a **layer** — `LayerScene`, `LayerPanel`, `LayerHUD`, `LayerSpeech`,
|
||||||
|
`LayerDialog`, `LayerMenu`, `LayerCurtain`, `LayerCursor` — and inkwell draws
|
||||||
|
from the bottom layer up, ticks from the top layer down, and lets registration
|
||||||
|
order decide only ties inside one layer. That is why the HUD frame comes out
|
||||||
|
under the tape slots and the cursor over everything, whatever the file names
|
||||||
|
happen to be. The layer was added to inkwell for this; the alternative was a
|
||||||
|
registration list, which is the thing this package spent its life deleting.
|
||||||
|
|
||||||
So adding an entity is adding a file, and there is no second list to keep in
|
So adding an entity is adding a file, and there is no second list to keep in
|
||||||
step. The price is that registration order is file-name order: the arrow keys
|
step. The price is that registration order is file-name order: the arrow keys
|
||||||
walk the scenes alphabetically rather than in the concept-art deck's order.
|
walk the scenes alphabetically rather than in the concept-art deck's order.
|
||||||
@@ -307,8 +320,8 @@ has to shadow where the player is.
|
|||||||
*Fix:* move `drawText` to `text/v2` — no call site would change.
|
*Fix:* move `drawText` to `text/v2` — no call site would change.
|
||||||
|
|
||||||
2. **`queueAction` is unexported**, so a domain widget cannot start an action.
|
2. **`queueAction` is unexported**, so a domain widget cannot start an action.
|
||||||
*Workaround:* the pump in `world.action.go` drives its own `Runner` through
|
*Workaround:* the pump — `widget.action_pump.go` calling `World.PumpTick` —
|
||||||
the exported `inkwell.Ctx`. *Caveat:* it runs alongside the engine's script
|
drives its own `Runner` through the exported `inkwell.Ctx`. *Caveat:* it runs alongside the engine's script
|
||||||
runner, not instead of it.
|
runner, not instead of it.
|
||||||
|
|
||||||
3. **The `"Nem ehhez."` flash is hardcoded** in `core.engine.go` for an
|
3. **The `"Nem ehhez."` flash is hardcoded** in `core.engine.go` for an
|
||||||
@@ -319,7 +332,7 @@ has to shadow where the player is.
|
|||||||
|
|
||||||
4. **Widgets have no `Visible` field and the `Manager` cannot unregister**, so
|
4. **Widgets have no `Visible` field and the `Manager` cannot unregister**, so
|
||||||
the built-in HUD cannot be hidden during a cutscene. *Workaround:* the
|
the built-in HUD cannot be hidden during a cutscene. *Workaround:* the
|
||||||
`gate` wrapper in `ui/ui.go` forwards `Tick`/`Draw`/`BlocksClickAt` only
|
`gate` wrapper in `widget.manager.go` forwards `Tick`/`Draw`/`BlocksClickAt` only
|
||||||
while the HUD is visible.
|
while the HUD is visible.
|
||||||
|
|
||||||
5. **`Run` hardcodes a 4× window** (`core.dsl.go`), which at 640×400 would be
|
5. **`Run` hardcodes a 4× window** (`core.dsl.go`), which at 640×400 would be
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module git.teletypegames.org/games/realworld
|
|||||||
go 1.26.3
|
go 1.26.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830092549-e26f7345c14d
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830201917-2429ada0900f
|
||||||
github.com/hajimehoshi/ebiten/v2 v2.9.9
|
github.com/hajimehoshi/ebiten/v2 v2.9.9
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830092549-e26f7345c14d h1:4AGtmrWwfnHkJvZ90on1+9bUmZOGSrcIG4KaJFiy+xo=
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830092549-e26f7345c14d h1:4AGtmrWwfnHkJvZ90on1+9bUmZOGSrcIG4KaJFiy+xo=
|
||||||
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830092549-e26f7345c14d/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830092549-e26f7345c14d/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
||||||
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830200555-53f4df04669c h1:GOKa6IbkfJXjB5LREr3eUw6YeeOeDICryfa0eKERWo0=
|
||||||
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830200555-53f4df04669c/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
||||||
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830201917-2429ada0900f h1:WBIh7svmA2R7tbi1Xrafn5//yl8vnK2qbpBXDbbz6Aw=
|
||||||
|
git.teletypegames.org/engines/inkwell v0.1.1-0.20260830201917-2429ada0900f/go.mod h1:/v6QtismTE8+e7kobbVR5B/CpTSrd4j2DYwJ8DvINhs=
|
||||||
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 h1:+kz5iTT3L7uU+VhlMfTb8hHcxLO3TlaELlX8wa4XjA0=
|
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 h1:+kz5iTT3L7uU+VhlMfTb8hHcxLO3TlaELlX8wa4XjA0=
|
||||||
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1/go.mod h1:lKJoeixeJwnFmYsBny4vvCJGVFc3aYDalhuDsfZzWHI=
|
github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1/go.mod h1:lKJoeixeJwnFmYsBny4vvCJGVFc3aYDalhuDsfZzWHI=
|
||||||
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
|
github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE=
|
||||||
|
|||||||
+2
-1
@@ -12,6 +12,7 @@ var (
|
|||||||
SceneManager = inkwell.NewManager[Scene]()
|
SceneManager = inkwell.NewManager[Scene]()
|
||||||
ScriptManager = inkwell.NewManager[Script]()
|
ScriptManager = inkwell.NewManager[Script]()
|
||||||
ThemeManager = inkwell.NewManager[Theme]()
|
ThemeManager = inkwell.NewManager[Theme]()
|
||||||
|
WidgetManager = inkwell.NewManager[Widget]()
|
||||||
)
|
)
|
||||||
|
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
@@ -43,11 +44,11 @@ func New(o Opts) *inkwell.Game {
|
|||||||
g.ItemManager = ItemManager
|
g.ItemManager = ItemManager
|
||||||
g.SceneManager = SceneManager
|
g.SceneManager = SceneManager
|
||||||
g.ScriptManager = ScriptManager
|
g.ScriptManager = ScriptManager
|
||||||
|
g.WidgetManager = WidgetManager
|
||||||
ThemeManager.Each(g.ThemeManager.Register)
|
ThemeManager.Each(g.ThemeManager.Register)
|
||||||
|
|
||||||
World.attach(g)
|
World.attach(g)
|
||||||
g.UseTheme(RealWorld)
|
g.UseTheme(RealWorld)
|
||||||
registerUI()
|
|
||||||
|
|
||||||
g.StartAt(start)
|
g.StartAt(start)
|
||||||
g.OnStart(ScriptOpening)
|
g.OnStart(ScriptOpening)
|
||||||
|
|||||||
@@ -1,199 +0,0 @@
|
|||||||
package inc
|
|
||||||
|
|
||||||
import (
|
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ScreenW = 640
|
|
||||||
ScreenH = 380
|
|
||||||
|
|
||||||
LineH = glyphH + 2
|
|
||||||
Pad = 6
|
|
||||||
|
|
||||||
TopBarH = LineH + 2
|
|
||||||
DividerX = 394
|
|
||||||
|
|
||||||
HUDH = Pad + LineH + 4 + invSlot*2 + invGap + Pad
|
|
||||||
HUDTop = ScreenH - HUDH
|
|
||||||
|
|
||||||
statusY = HUDTop + Pad
|
|
||||||
slotsY = HUDTop + Pad + LineH
|
|
||||||
slotsH = LineH*2 + Pad*2
|
|
||||||
invY = slotsY + 4
|
|
||||||
invSlot = 40
|
|
||||||
invGap = 4
|
|
||||||
)
|
|
||||||
|
|
||||||
func registerUI() {
|
|
||||||
g := World.G
|
|
||||||
|
|
||||||
g.UIManager.Register(&useWithGuard{
|
|
||||||
Name: "usewith_guard",
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&actionPump{
|
|
||||||
Name: "pump",
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&sceneNav{
|
|
||||||
Name: "scene_nav",
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&windowSizer{
|
|
||||||
Name: "window",
|
|
||||||
Scale: 2,
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&inkwell.HotspotDebug{
|
|
||||||
Name: "hotspot_debug",
|
|
||||||
})
|
|
||||||
|
|
||||||
top := &inkwell.TopBar{
|
|
||||||
Name: "topbar",
|
|
||||||
Height: TopBarH,
|
|
||||||
TimeVar: VarArmillaStrip,
|
|
||||||
}
|
|
||||||
World.SetTopBar(top)
|
|
||||||
g.UIManager.Register(gated("topbar_gate", top))
|
|
||||||
|
|
||||||
g.UIManager.Register(&letterbox{
|
|
||||||
Name: "letterbox",
|
|
||||||
Bar: 36,
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&hudFrame{
|
|
||||||
Name: "hudframe",
|
|
||||||
})
|
|
||||||
|
|
||||||
g.UIManager.Register(gated("status_gate", &inkwell.StatusLine{
|
|
||||||
Name: "status",
|
|
||||||
Y: statusY,
|
|
||||||
Align: inkwell.AlignLeft,
|
|
||||||
ScreenWidth: DividerX,
|
|
||||||
}))
|
|
||||||
g.UIManager.Register(gated("inventory_gate", &inkwell.InventoryBar{
|
|
||||||
Name: "inventory",
|
|
||||||
Origin: inkwell.Point{
|
|
||||||
X: Pad + 2,
|
|
||||||
Y: invY,
|
|
||||||
},
|
|
||||||
Slots: 8,
|
|
||||||
Cols: 4,
|
|
||||||
SlotSize: invSlot,
|
|
||||||
Gap: invGap,
|
|
||||||
}))
|
|
||||||
g.UIManager.Register(&tapeSlots{
|
|
||||||
Name: "tapes",
|
|
||||||
Bounds: inkwell.Rect(192, slotsY, 194, slotsH),
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&tapeChannel{
|
|
||||||
Name: "channel",
|
|
||||||
Bounds: inkwell.Rect(DividerX+2, HUDTop+2, ScreenW-DividerX-4, ScreenH-HUDTop-4),
|
|
||||||
})
|
|
||||||
|
|
||||||
g.UIManager.Register(&inkwell.SpeechBubble{
|
|
||||||
Name: "speech",
|
|
||||||
MaxWidth: 360,
|
|
||||||
Padding: Pad,
|
|
||||||
OffsetY: 8,
|
|
||||||
FallbackY: TopBarH + Pad,
|
|
||||||
})
|
|
||||||
|
|
||||||
g.UIManager.Register(&inkwell.DialogBox{
|
|
||||||
Name: "dialog",
|
|
||||||
Bounds: inkwell.Rect(0, ScreenH-LineH*9, DividerX, LineH*9),
|
|
||||||
LineHeight: LineH,
|
|
||||||
Padding: Pad,
|
|
||||||
})
|
|
||||||
|
|
||||||
g.UIManager.Register(&inkwell.RadialVerbs{
|
|
||||||
Name: "verbs",
|
|
||||||
Trigger: inkwell.MouseButtonRight,
|
|
||||||
Radius: 58,
|
|
||||||
Labels: map[string]string{
|
|
||||||
"look": "Look", "use": "Use", "talk": "Talk", "take": "Take",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&inkwell.EndCard{
|
|
||||||
Name: "endcard",
|
|
||||||
})
|
|
||||||
g.UIManager.Register(&inkwell.Cursor{
|
|
||||||
Name: "cursor",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type windowSizer struct {
|
|
||||||
Name string
|
|
||||||
Scale int
|
|
||||||
done bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *windowSizer) GetName() string { return s.Name }
|
|
||||||
func (s *windowSizer) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
|
||||||
|
|
||||||
func (s *windowSizer) Tick(ctx *inkwell.UICtx) {
|
|
||||||
if s.done {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.done = true
|
|
||||||
scale := s.Scale
|
|
||||||
if scale <= 0 {
|
|
||||||
scale = 2
|
|
||||||
}
|
|
||||||
ebiten.SetWindowSize(ctx.Game.Width*scale, ctx.Game.Height*scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
type gate struct {
|
|
||||||
Name string
|
|
||||||
Inner inkwell.Widget
|
|
||||||
}
|
|
||||||
|
|
||||||
func gated(name string, inner inkwell.Widget) inkwell.Widget {
|
|
||||||
return &gate{
|
|
||||||
Name: name,
|
|
||||||
Inner: inner,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *gate) GetName() string { return n.Name }
|
|
||||||
|
|
||||||
func (n *gate) Tick(ctx *inkwell.UICtx) {
|
|
||||||
if World.HUDVisible() {
|
|
||||||
n.Inner.Tick(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *gate) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
|
||||||
if World.HUDVisible() {
|
|
||||||
n.Inner.Draw(dst, ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *gate) BlocksClickAt(p inkwell.Point) bool {
|
|
||||||
if !World.HUDVisible() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
b, ok := n.Inner.(interface{ BlocksClickAt(inkwell.Point) bool })
|
|
||||||
return ok && b.BlocksClickAt(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
type hudFrame struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hudFrame) GetName() string { return h.Name }
|
|
||||||
func (h *hudFrame) Tick(ctx *inkwell.UICtx) {}
|
|
||||||
|
|
||||||
func (h *hudFrame) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
|
||||||
if !World.HUDVisible() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
th := ctx.Game.Theme()
|
|
||||||
vector.DrawFilledRect(dst, 0, HUDTop+1, ScreenW, ScreenH-HUDTop-1, th.PanelBG, false)
|
|
||||||
|
|
||||||
vector.StrokeLine(dst, 0, HUDTop, ScreenW, HUDTop, 1, th.CharacterPanelBorder, false)
|
|
||||||
|
|
||||||
vector.StrokeLine(dst, DividerX, HUDTop+1, DividerX, ScreenH, 1, th.CharacterPanelBorder, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *hudFrame) BlocksClickAt(p inkwell.Point) bool {
|
|
||||||
return World.HUDVisible() && p.Y >= HUDTop
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&actionPump{
|
||||||
|
Name: "pump",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type actionPump struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *actionPump) GetName() string { return p.Name }
|
||||||
|
func (p *actionPump) Layer() inkwell.Layer { return inkwell.LayerScene }
|
||||||
|
func (p *actionPump) Tick(ctx *inkwell.UICtx) { World.PumpTick(ctx.DT) }
|
||||||
|
func (p *actionPump) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.Cursor{
|
||||||
|
Name: "cursor",
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.DialogBox{
|
||||||
|
Name: "dialog",
|
||||||
|
Bounds: inkwell.Rect(0, ScreenH-LineH*9, DividerX, LineH*9),
|
||||||
|
LineHeight: LineH,
|
||||||
|
Padding: Pad,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.EndCard{
|
||||||
|
Name: "endcard",
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.HotspotDebug{
|
||||||
|
Name: "hotspot_debug",
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&hudFrame{
|
||||||
|
Name: "hudframe",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type hudFrame struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hudFrame) GetName() string { return h.Name }
|
||||||
|
func (h *hudFrame) Layer() inkwell.Layer { return inkwell.LayerPanel }
|
||||||
|
func (h *hudFrame) Tick(ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
|
func (h *hudFrame) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
|
if !World.HUDVisible() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
th := ctx.Game.Theme()
|
||||||
|
vector.DrawFilledRect(dst, 0, HUDTop+1, ScreenW, ScreenH-HUDTop-1, th.PanelBG, false)
|
||||||
|
|
||||||
|
vector.StrokeLine(dst, 0, HUDTop, ScreenW, HUDTop, 1, th.CharacterPanelBorder, false)
|
||||||
|
|
||||||
|
vector.StrokeLine(dst, DividerX, HUDTop+1, DividerX, ScreenH, 1, th.CharacterPanelBorder, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *hudFrame) BlocksClickAt(p inkwell.Point) bool {
|
||||||
|
return World.HUDVisible() && p.Y >= HUDTop
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(gated("inventory", &inkwell.InventoryBar{
|
||||||
|
Name: "inventory",
|
||||||
|
Origin: inkwell.Point{
|
||||||
|
X: Pad + 2,
|
||||||
|
Y: invY,
|
||||||
|
},
|
||||||
|
Slots: 8,
|
||||||
|
Cols: 4,
|
||||||
|
SlotSize: invSlot,
|
||||||
|
Gap: invGap,
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -7,12 +7,20 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&letterbox{
|
||||||
|
Name: "letterbox",
|
||||||
|
Bar: 36,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type letterbox struct {
|
type letterbox struct {
|
||||||
Name string
|
Name string
|
||||||
Bar float64
|
Bar float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *letterbox) GetName() string { return l.Name }
|
func (l *letterbox) GetName() string { return l.Name }
|
||||||
|
func (l *letterbox) Layer() inkwell.Layer { return inkwell.LayerScene }
|
||||||
|
|
||||||
func (l *letterbox) Tick(ctx *inkwell.UICtx) {
|
func (l *letterbox) Tick(ctx *inkwell.UICtx) {
|
||||||
if World.Mode() != ModeCutscene || !World.TapeWaiting() {
|
if World.Mode() != ModeCutscene || !World.TapeWaiting() {
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Widget = inkwell.Widget
|
||||||
|
|
||||||
|
const (
|
||||||
|
ScreenW = 640
|
||||||
|
ScreenH = 380
|
||||||
|
|
||||||
|
LineH = glyphH + 2
|
||||||
|
Pad = 6
|
||||||
|
|
||||||
|
TopBarH = LineH + 2
|
||||||
|
DividerX = 394
|
||||||
|
|
||||||
|
HUDH = Pad + LineH + 4 + invSlot*2 + invGap + Pad
|
||||||
|
HUDTop = ScreenH - HUDH
|
||||||
|
|
||||||
|
statusY = HUDTop + Pad
|
||||||
|
slotsY = HUDTop + Pad + LineH
|
||||||
|
slotsH = LineH*2 + Pad*2
|
||||||
|
invY = slotsY + 4
|
||||||
|
invSlot = 40
|
||||||
|
invGap = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
type gate struct {
|
||||||
|
Name string
|
||||||
|
Inner Widget
|
||||||
|
}
|
||||||
|
|
||||||
|
func gated(name string, inner Widget) Widget {
|
||||||
|
return &gate{
|
||||||
|
Name: name,
|
||||||
|
Inner: inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *gate) GetName() string { return n.Name }
|
||||||
|
|
||||||
|
func (n *gate) Layer() inkwell.Layer { return inkwell.LayerOf(n.Inner) }
|
||||||
|
|
||||||
|
func (n *gate) Tick(ctx *inkwell.UICtx) {
|
||||||
|
if World.HUDVisible() {
|
||||||
|
n.Inner.Tick(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *gate) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {
|
||||||
|
if World.HUDVisible() {
|
||||||
|
n.Inner.Draw(dst, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *gate) BlocksClickAt(p inkwell.Point) bool {
|
||||||
|
if !World.HUDVisible() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
b, ok := n.Inner.(interface{ BlocksClickAt(inkwell.Point) bool })
|
||||||
|
return ok && b.BlocksClickAt(p)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.RadialVerbs{
|
||||||
|
Name: "verbs",
|
||||||
|
Trigger: inkwell.MouseButtonRight,
|
||||||
|
Radius: 58,
|
||||||
|
Labels: map[string]string{
|
||||||
|
"look": "Look", "use": "Use", "talk": "Talk", "take": "Take",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -6,11 +6,18 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&sceneNav{
|
||||||
|
Name: "scene_nav",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type sceneNav struct {
|
type sceneNav struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *sceneNav) GetName() string { return n.Name }
|
func (n *sceneNav) GetName() string { return n.Name }
|
||||||
|
func (n *sceneNav) Layer() inkwell.Layer { return inkwell.LayerScene }
|
||||||
func (n *sceneNav) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
func (n *sceneNav) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (n *sceneNav) Tick(ctx *inkwell.UICtx) {
|
func (n *sceneNav) Tick(ctx *inkwell.UICtx) {
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&inkwell.SpeechBubble{
|
||||||
|
Name: "speech",
|
||||||
|
MaxWidth: 360,
|
||||||
|
Padding: Pad,
|
||||||
|
OffsetY: 8,
|
||||||
|
FallbackY: TopBarH + Pad,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(gated("status", &inkwell.StatusLine{
|
||||||
|
Name: "status",
|
||||||
|
Y: statusY,
|
||||||
|
Align: inkwell.AlignLeft,
|
||||||
|
ScreenWidth: DividerX,
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -8,12 +8,20 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&tapeChannel{
|
||||||
|
Name: "channel",
|
||||||
|
Bounds: inkwell.Rect(DividerX+2, HUDTop+2, ScreenW-DividerX-4, ScreenH-HUDTop-4),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type tapeChannel struct {
|
type tapeChannel struct {
|
||||||
Name string
|
Name string
|
||||||
Bounds inkwell.Rectangle
|
Bounds inkwell.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tapeChannel) GetName() string { return t.Name }
|
func (t *tapeChannel) GetName() string { return t.Name }
|
||||||
|
func (t *tapeChannel) Layer() inkwell.Layer { return inkwell.LayerHUD }
|
||||||
|
|
||||||
func (t *tapeChannel) Tick(ctx *inkwell.UICtx) {}
|
func (t *tapeChannel) Tick(ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
@@ -6,12 +6,20 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/vector"
|
"github.com/hajimehoshi/ebiten/v2/vector"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&tapeSlots{
|
||||||
|
Name: "tapes",
|
||||||
|
Bounds: inkwell.Rect(192, slotsY, 194, slotsH),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type tapeSlots struct {
|
type tapeSlots struct {
|
||||||
Name string
|
Name string
|
||||||
Bounds inkwell.Rectangle
|
Bounds inkwell.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tapeSlots) GetName() string { return t.Name }
|
func (t *tapeSlots) GetName() string { return t.Name }
|
||||||
|
func (t *tapeSlots) Layer() inkwell.Layer { return inkwell.LayerHUD }
|
||||||
|
|
||||||
func (t *tapeSlots) BlocksClickAt(p inkwell.Point) bool {
|
func (t *tapeSlots) BlocksClickAt(p inkwell.Point) bool {
|
||||||
return World.HUDVisible() && t.Bounds.Contains(p)
|
return World.HUDVisible() && t.Bounds.Contains(p)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(gated("topbar", &titleBar{
|
||||||
|
TopBar: &inkwell.TopBar{
|
||||||
|
Name: "topbar",
|
||||||
|
Height: TopBarH,
|
||||||
|
TimeVar: VarArmillaStrip,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type titleBar struct {
|
||||||
|
*inkwell.TopBar
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *titleBar) Tick(ctx *inkwell.UICtx) {
|
||||||
|
t.LeftText = World.SceneTitle()
|
||||||
|
if World.Paused() {
|
||||||
|
t.LeftText += " — paused"
|
||||||
|
}
|
||||||
|
t.TopBar.Tick(ctx)
|
||||||
|
}
|
||||||
@@ -7,11 +7,18 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&useWithGuard{
|
||||||
|
Name: "usewith_guard",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
type useWithGuard struct {
|
type useWithGuard struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *useWithGuard) GetName() string { return u.Name }
|
func (u *useWithGuard) GetName() string { return u.Name }
|
||||||
|
func (u *useWithGuard) Layer() inkwell.Layer { return inkwell.LayerScene }
|
||||||
func (u *useWithGuard) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
func (u *useWithGuard) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
func (u *useWithGuard) Tick(ctx *inkwell.UICtx) {
|
func (u *useWithGuard) Tick(ctx *inkwell.UICtx) {
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package inc
|
||||||
|
|
||||||
|
import (
|
||||||
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
WidgetManager.Register(&windowSizer{
|
||||||
|
Name: "window",
|
||||||
|
Scale: 2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type windowSizer struct {
|
||||||
|
Name string
|
||||||
|
Scale int
|
||||||
|
done bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *windowSizer) GetName() string { return s.Name }
|
||||||
|
func (s *windowSizer) Layer() inkwell.Layer { return inkwell.LayerScene }
|
||||||
|
func (s *windowSizer) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
||||||
|
|
||||||
|
func (s *windowSizer) Tick(ctx *inkwell.UICtx) {
|
||||||
|
if s.done {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.done = true
|
||||||
|
scale := s.Scale
|
||||||
|
if scale <= 0 {
|
||||||
|
scale = 2
|
||||||
|
}
|
||||||
|
ebiten.SetWindowSize(ctx.Game.Width*scale, ctx.Game.Height*scale)
|
||||||
|
}
|
||||||
+1
-19
@@ -2,7 +2,6 @@ package inc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
inkwell "git.teletypegames.org/engines/inkwell"
|
inkwell "git.teletypegames.org/engines/inkwell"
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (w *world) Do(a inkwell.Action) {
|
func (w *world) Do(a inkwell.Action) {
|
||||||
@@ -12,15 +11,6 @@ func (w *world) Do(a inkwell.Action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *world) PumpTick(dt float64) {
|
func (w *world) PumpTick(dt float64) {
|
||||||
|
|
||||||
if w.top != nil {
|
|
||||||
title := w.sceneTitle()
|
|
||||||
if w.paused {
|
|
||||||
title += " — paused"
|
|
||||||
}
|
|
||||||
w.top.LeftText = title
|
|
||||||
}
|
|
||||||
|
|
||||||
if w.running == nil {
|
if w.running == nil {
|
||||||
if len(w.queue) == 0 {
|
if len(w.queue) == 0 {
|
||||||
return
|
return
|
||||||
@@ -40,7 +30,7 @@ func (w *world) PumpTick(dt float64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *world) sceneTitle() string {
|
func (w *world) SceneTitle() string {
|
||||||
s, ok := w.G.SceneManager.Get(w.G.CurrentScene())
|
s, ok := w.G.SceneManager.Get(w.G.CurrentScene())
|
||||||
if !ok {
|
if !ok {
|
||||||
return ""
|
return ""
|
||||||
@@ -51,14 +41,6 @@ func (w *world) sceneTitle() string {
|
|||||||
return s.Name
|
return s.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
type actionPump struct {
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *actionPump) GetName() string { return p.Name }
|
|
||||||
func (p *actionPump) Tick(ctx *inkwell.UICtx) { World.PumpTick(ctx.DT) }
|
|
||||||
func (p *actionPump) Draw(dst *ebiten.Image, ctx *inkwell.UICtx) {}
|
|
||||||
|
|
||||||
type fnAction struct{ fn func(*inkwell.Ctx) }
|
type fnAction struct{ fn func(*inkwell.Ctx) }
|
||||||
|
|
||||||
func (a *fnAction) Start() inkwell.Runner {
|
func (a *fnAction) Start() inkwell.Runner {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ type world struct {
|
|||||||
pending string
|
pending string
|
||||||
queue []inkwell.Action
|
queue []inkwell.Action
|
||||||
running inkwell.Runner
|
running inkwell.Runner
|
||||||
top *inkwell.TopBar
|
|
||||||
|
|
||||||
tapeWaiting bool
|
tapeWaiting bool
|
||||||
tapeLine inkwell.Action
|
tapeLine inkwell.Action
|
||||||
@@ -36,7 +35,6 @@ func (w *world) attach(g *inkwell.Game) {
|
|||||||
w.pending = ""
|
w.pending = ""
|
||||||
w.queue = nil
|
w.queue = nil
|
||||||
w.running = nil
|
w.running = nil
|
||||||
w.top = nil
|
|
||||||
w.tapeWaiting = false
|
w.tapeWaiting = false
|
||||||
w.tapeLine = nil
|
w.tapeLine = nil
|
||||||
}
|
}
|
||||||
@@ -49,8 +47,6 @@ func (w *world) HUDVisible() bool { return w.mode == ModePlay }
|
|||||||
|
|
||||||
func (w *world) Paused() bool { return w.paused }
|
func (w *world) Paused() bool { return w.paused }
|
||||||
|
|
||||||
func (w *world) SetTopBar(t *inkwell.TopBar) { w.top = t }
|
|
||||||
|
|
||||||
func (w *world) Slot2() string {
|
func (w *world) Slot2() string {
|
||||||
if v, ok := w.G.State.Var(VarSlot2).(string); ok {
|
if v, ok := w.G.State.Var(VarSlot2).(string); ok {
|
||||||
return v
|
return v
|
||||||
|
|||||||
Reference in New Issue
Block a user