scaff

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

README

Scaff

[!WARNING] Scaff is an experimental project not intended for production use cases.

Scaff (shortened from scaffold) is quite literally a scaffold for point-and-click games that don't require more than UI. We provide a minimal framework capable of everything you need for the kind of game that doesn't require a bloated game engine with collisions, 3D and more.

The vision is to make a really simple and efficient game engine that uses a giant tree of nodes to make development really fast and predictable. We've seen that trees work really well for UI (looking at stuff like React), so why not for everything in your 2D environment too?

Features

[!NOTE] We're still working on most of this, especially documentation and the canvas package. This is just what should be there in the future.

Scaff provides various features that make your life a lot easier:

  • Raw access at every point in case you need it (and with good documentation on how too, hopefully)
  • Signals for state tracking and only refreshing what's really needed
  • scaffui (Scaff User Interface) package for rich declarative UI based on state updates
  • scaffcv (Scaff Canvas) package for rich game environments reacting to state updates
  • Loggers, based on slog, that make logging a breeze and actually look really nice
  • A scene stack for easy scene management

This is just a really small overview. A lot of the functionality that makes Scaff special are the little packages and how they are made.

Credits

Name Description License Link Note
V Vector math and position utilities MIT https://github.com/setanarut/v Thanks for helping out with vector math!
Kamera Camera movement and math CC0 https://github.com/setanarut/kamera Thanks for making this amazing package, making it myself would've been really difficult.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func TrackValue

func TrackValue[T any](tracker *Tracker, signal *Signal[T]) T

TrackValue ensures tracker is subscribed to signal and returns the current value; closed or nil inputs return zero value.

Types

type AcceptChild

type AcceptChild = AcceptChildTemplate[NodeBuilder]

A struct that can be embedded as a pointer to implement a Child(builder NodeBuilder) function on props for a node with a single child.

This is recommended for use with a single child node as it saves a lot of code and implements all of the things required for children properly according to best practices.

func EmptyChild

func EmptyChild() *AcceptChild

func WithChild

func WithChild(builder NodeBuilder) *AcceptChild

type AcceptChildTemplate

type AcceptChildTemplate[B any] struct {
	// contains filtered or unexported fields
}

Template struct for type aliases that can be embedded as a pointer to implement a Child(builder NodeBuilder) function on props for a node with a single child.

func EmptyChildTemplate

func EmptyChildTemplate[B any]() *AcceptChildTemplate[B]

Helper function for quickly creating empty single child template.

func WithChildTemplate

func WithChildTemplate[B any](builder B) *AcceptChildTemplate[B]

Helper function for quickly creating new single child props.

func (*AcceptChildTemplate[B]) Child

func (ac *AcceptChildTemplate[B]) Child(builder B)

Child adds a child to the node. There can only be one child.

There are internal reasons for this to be a method. Trackers just need to work with this properly.

func (*AcceptChildTemplate[B]) ClearChanged

func (ac *AcceptChildTemplate[B]) ClearChanged()

func (AcceptChildTemplate[B]) GetBuilders

func (ac AcceptChildTemplate[B]) GetBuilders() []B

func (AcceptChildTemplate[B]) GetChanged

func (ac AcceptChildTemplate[B]) GetChanged() []uint

type AcceptChildren

type AcceptChildren = AcceptChildrenTemplate[NodeBuilder]

A struct that can be embedded as a pointer to implement a Child(idex int, builder NodeBuilder) function on props for a node with a multiple children.

This is recommended for use with a multi child node as it saves a lot of code and implements all of the things required for children properly according to best practices.

func EmptyChildren

func EmptyChildren() *AcceptChildren

func WithChildren

func WithChildren(builders []NodeBuilder) *AcceptChildren

type AcceptChildrenTemplate

type AcceptChildrenTemplate[B any] struct {
	// contains filtered or unexported fields
}

Template struct for type aliases that can be embedded as a pointer to implement a Child(i uint, builder NodeBuilder) function on props for a node with a multiple children.

There are internal reasons for this to be a method. Trackers just need to work with this properly.

func EmptyChildrenTemplate

func EmptyChildrenTemplate[B any]() *AcceptChildrenTemplate[B]

Helper function for quickly creating empty multi child template.

func WithChildrenTemplate

func WithChildrenTemplate[B any](builders []B) *AcceptChildrenTemplate[B]

Helper function for quickly creating new single child props.

func (*AcceptChildrenTemplate[B]) Child

func (ac *AcceptChildrenTemplate[B]) Child(i uint, builder B)

Child adds a new child to the node. i is the index of the child. Make sure it is actually valid and stuff.

There are internal reasons for this to be a method. Trackers just need to work with this properly.

func (*AcceptChildrenTemplate[B]) ClearChanged

func (ac *AcceptChildrenTemplate[B]) ClearChanged()

func (AcceptChildrenTemplate[B]) GetBuilders

func (ac AcceptChildrenTemplate[B]) GetBuilders() []B

func (AcceptChildrenTemplate[B]) GetChanged

func (ac AcceptChildrenTemplate[B]) GetChanged() []uint

type AcceptNoChild

type AcceptNoChild = AcceptNoChildTemplate[NodeBuilder]

A struct that can be embedded as a pointer to implement a Child(builder NodeBuilder) function on props for a node with no children.

This is recommended for use with a single child node as it saves a lot of code and implements all of the things required for children properly according to best practices.

func EmptyNoChild

func EmptyNoChild() AcceptNoChild

type AcceptNoChildTemplate

type AcceptNoChildTemplate[B any] struct{}

Template struct for type aliases that can be embedded as a pointer to implement a Child(builder NodeBuilder) function on props for a node that should have no child.

func EmptyNoChildTemplate

func EmptyNoChildTemplate[B any]() AcceptNoChildTemplate[B]

Helper function for quickly creating no child template

func (AcceptNoChildTemplate[B]) ClearChanged

func (anc AcceptNoChildTemplate[B]) ClearChanged()

func (AcceptNoChildTemplate[B]) GetBuilders

func (anc AcceptNoChildTemplate[B]) GetBuilders() []B

func (AcceptNoChildTemplate[B]) GetChanged

func (anc AcceptNoChildTemplate[B]) GetChanged() []uint

type BuildContext

type BuildContext struct {
	// contains filtered or unexported fields
}

All the context for nodes being created within ScaffUI

func (BuildContext) AssetManager

func (bc BuildContext) AssetManager() *paint.AssetManager

func (BuildContext) CopyWithNewUpdateQueue

func (bc BuildContext) CopyWithNewUpdateQueue() *BuildContext

func (BuildContext) UpdateQueue

func (bc BuildContext) UpdateQueue() *UpdateQueue

type ChildProps

type ChildProps[B any] interface {
	// GetBuilders gets all the builders for the children of this node
	GetBuilders() []B

	// GetChanged gets all the changed indices since the last time ClearChanged was called.
	GetChanged() []uint

	// ClearChanged clears all the changed indices
	ClearChanged()
}

An interface for props of a node that has children. This helps nodes like single child not rebuild as often.

type Context

type Context struct {
	// contains filtered or unexported fields
}

func (Context) Focused

func (c Context) Focused() bool

If a scene is in the front of the scene stack, it is focused

func (Context) Handled

func (c Context) Handled(event EventId)

Mark a type of event as handled.

func (Context) Height

func (c Context) Height() float64

Height of the game

func (Context) IsHandled

func (c Context) IsHandled(event EventId) bool

Check if any kind of event has already been handled.

func (Context) Now

func (c Context) Now() time.Time

The current time (use for all things to make testing easier)

func (Context) TransitionFrame

func (c Context) TransitionFrame() scath.Timeframe

The timeframe for the transition

func (Context) Width

func (c Context) Width() float64

Width of the game

type Event

type Event interface {
	EventID() EventId
}

type EventId

type EventId string
const (
	EventIdMove       EventId = "scaff::move"
	EventIdScroll     EventId = "scaff::scroll"
	EventIdSizeChange EventId = "scaff::size-change"
)

All types of events in Scaff

func EventIdKeyPress

func EventIdKeyPress(key ebiten.Key) EventId

This event id has the key in it to make sure it can be handled separately from other events.

func EventIdKeyRelease

func EventIdKeyRelease(key ebiten.Key) EventId

This event id has the key in it to make sure it can be handled separately from other events.

func EventIdPress

func EventIdPress(button ebiten.MouseButton) EventId

This event id has the button in it to make sure it can be marked as handled separately from events for other buttons

func EventIdRelease

func EventIdRelease(button ebiten.MouseButton) EventId

This event id has the button in it to make sure it can be marked as handled separately from events for other buttons

type Game

type Game struct {
	// contains filtered or unexported fields
}

func NewGame

func NewGame() *Game

NewGame returns a new Game instance with default values

func (*Game) Draw

func (g *Game) Draw(screen *ebiten.Image)

Draw handles drawing of the game by drawing the bottom scene first and then going up from there.

func (*Game) EmitEvent

func (g *Game) EmitEvent(contexts []*Context, event Event)

EmitEvent sends an event to all scenes in the scene list in proper order (top -> bottom)

func (*Game) EmitEventNoContext

func (g *Game) EmitEventNoContext(event Event)

EmitEventNoContext sends an event to all scenes in the scene list in proper order (top -> bottom), but it also builds a context for the scenes at the same time. Scenes that are not fully transitioned will not receive events.

func (*Game) GetSceneList

func (g *Game) GetSceneList() []Scene

Get the scene list, this may not be the last updated one, but the one that will be set next time Update is called.

func (*Game) Goto

func (g *Game) Goto(scene Scene)

Goto completely removes all scenes from the scene stack and makes this scene the new one and only scene.

func (*Game) Height

func (g *Game) Height() float64

func (*Game) Layout

func (g *Game) Layout(width, height int) (int, int)

This is not needed as we have LayoutF below, we want to make sure the scale factor is taken into account properly.

func (*Game) LayoutF

func (g *Game) LayoutF(logicWinWidth, logicWinHeight float64) (float64, float64)

This makes sure the monitor's resolution is actually properly respected (Source: https://github.com/tinne26/kage-desk/blob/main/docs/tutorials/ebitengine_game.md#layout)

func (*Game) Pop

func (g *Game) Pop()

Pop removes the top scene from the scene stack.

func (*Game) PopUntil

func (g *Game) PopUntil(id string)

PopUntil "pops" (removes from the top) all scenes in the scene stack until a scene with a certain id is found (but that one is not removed).

func (*Game) Push

func (g *Game) Push(scene Scene)

Push adds a scene to the top of the scene stack.

func (*Game) Update

func (g *Game) Update() error

Update forwards Ebiten's Update to all scenes and emits input events from top -> bottom.

func (*Game) Width

func (g *Game) Width() float64

type Identifiable

type Identifiable interface {
	ID() string
}

An interface that attaches a simple string identifer to

type KeyPressEvent

type KeyPressEvent struct {
	Key ebiten.Key
}

Emitted when a user presses a key.

func (KeyPressEvent) EventID

func (kp KeyPressEvent) EventID() EventId

type KeyReleaseEvent

type KeyReleaseEvent struct {
	Key ebiten.Key
}

Emitted when a user releases a key.

func (KeyReleaseEvent) EventID

func (kr KeyReleaseEvent) EventID() EventId

type Loadable

type Loadable[T any] interface {

	// Called when the Node is initialized in the tree
	Load(parent T)

	// Called when the Node is removed from the tree
	Unload()
}

type MoveEvent

type MoveEvent struct {
	X      int
	Y      int
	DeltaX int
	DeltaY int
}

func (MoveEvent) EventID

func (me MoveEvent) EventID() EventId

func (MoveEvent) Position

func (me MoveEvent) Position() scath.Vec

type Node

type Node interface {
	Tracking
	Identifiable
	Loadable[Node]

	// Should return your own parent
	Parent() Node

	// Should return your own children
	Children() []Node

	// Called on every physics tick (like 60 times a second, depending on what ebitens tick rate is)
	Update(c *Context) TracedError

	// Handle events from the system (you do not have to handle any, but should always push them along to children at least)
	HandleEvent(c *Context, event Event) TracedError

	// Draw the thing onto the screen
	Draw(c *Context, image *ebiten.Image)
}

type NodeBuilder

type NodeBuilder func(*BuildContext) Node

func Standard

func Standard[P ChildProps[NodeBuilder]](create StandardCreate[P]) NodeBuilder

Standard lets you create a node with multiple children. Simply implement the ChildProps interface on the props you want to have for your node.

type PositionalEvent

type PositionalEvent interface {
	Event
	Position() scath.Vec
}

type PressEvent

type PressEvent struct {
	X      int
	Y      int
	Button ebiten.MouseButton
}

Emitted when the user presses a mouse button down.

func (PressEvent) EventID

func (de PressEvent) EventID() EventId

func (PressEvent) Position

func (de PressEvent) Position() scath.Vec

type ReleaseEvent

type ReleaseEvent struct {
	X      int
	Y      int
	Button ebiten.MouseButton
}

Emitted when a user releases a mouse button.

func (ReleaseEvent) EventID

func (re ReleaseEvent) EventID() EventId

func (ReleaseEvent) Position

func (re ReleaseEvent) Position() scath.Vec

type RootProps

type RootProps struct {
	*AcceptChildren
}

type Scene

type Scene interface {
	// GetId returns the unique identifier of the scene.
	GetId() string

	// Update updates the scene with the given context.
	Update(c *Context) error

	// Draw draws the scene onto the screen.
	Draw(c *Context, screen *ebiten.Image)

	// HandleEvent should handle an event (like input events + resizing, etc.)
	HandleEvent(c *Context, e Event) error

	TransitionCapable
}

type SceneTree

type SceneTree struct {
	// contains filtered or unexported fields
}

func NewSceneTree

func NewSceneTree(id string, assetManager *paint.AssetManager) *SceneTree

NewSceneTree makes a new scene tree based on an identifier. This tree supports a builder pattern, just use .Mount(<node>) to mount a node into it or add a transition with SetTransitionProps.

func (*SceneTree) Draw

func (st *SceneTree) Draw(c *Context, screen *ebiten.Image)

Pass Draw to the layers in the correct order

func (*SceneTree) GetId

func (st *SceneTree) GetId() string

Pass the ID to the GetID function for the Scene interface

func (*SceneTree) HandleEvent

func (st *SceneTree) HandleEvent(c *Context, e Event) error

Pass events to the root node

func (*SceneTree) Load

func (st *SceneTree) Load()

Transfers Load from the Scene interface to the scene root.

func (*SceneTree) Mount

func (st *SceneTree) Mount(create func(t *Tracker, props *RootProps)) *SceneTree

Mount a node as the root of the scene tree.

func (*SceneTree) SetTransitionProps

func (st *SceneTree) SetTransitionProps(handler func(bool) TransitionProperties) *SceneTree

Set what kind of transition properties the scene should use (the parameter in the function is if the transition is reverse or not)

func (*SceneTree) Transition

func (st *SceneTree) Transition(in bool) TransitionProperties

Forward transition properties from the embedded function

func (*SceneTree) Unload

func (st *SceneTree) Unload()

Transfers Unload from the Scene interface to the scene root.

func (*SceneTree) Update

func (st *SceneTree) Update(c *Context) error

Forward update + handle some events that are only available in update

type ScrollEvent

type ScrollEvent struct {
	X       int
	Y       int
	ScrollX float64
	ScrollY float64
}

Emitted when there is a new scroll delta. This can be either the mouse, a touchpad or potentially also swiping around on mobile.

func (ScrollEvent) EventID

func (se ScrollEvent) EventID() EventId

func (ScrollEvent) Position

func (se ScrollEvent) Position() scath.Vec

type Signal

type Signal[T any] struct {
	// contains filtered or unexported fields
}

func NewSignal

func NewSignal[T any](def T) *Signal[T]

Create a new signal

func (*Signal[T]) AddListener

func (s *Signal[T]) AddListener(listener func(T)) func()

AddListener registers a listener and immediately pushes the current value; it returns an unsubscribe function.

func (*Signal[T]) Refresh

func (s *Signal[T]) Refresh()

Refresh re-emits the current value to all listeners without changing it; listeners run synchronously.

func (*Signal[T]) Set

func (s *Signal[T]) Set(value T)

Set updates the value and notifies all current listeners; listeners run synchronously and can block callers.

func (*Signal[T]) Track

func (s *Signal[T]) Track(tracking Tracking) T

Convenience wrapper over cgui.TrackValue (tracking is implemented by every Node object by default, you can just pass it in)

func (*Signal[T]) Value

func (s *Signal[T]) Value() T

Get the value of the signal (IF YOU WANT THE UI TO UPDATE USE TRACK WITH THE CORRECT TRACKER)

type SizeChangeEvent

type SizeChangeEvent struct{}

Emitted when the size of the application changes.

This does not contain the new size as the context already does anyway.

func (SizeChangeEvent) EventID

func (sce SizeChangeEvent) EventID() EventId

type StandardCreate

type StandardCreate[P ChildProps[NodeBuilder]] struct {
	ID           string
	DefaultProps P
	PropsCreator func(t *Tracker, props *P)
	Create       func(methods *StandardMethods[P])
}

Struct for defining a new standard node.

ID should be a unique id for the node, but also probably be readable as it shows up in error messages.

DefaultProps are the props as they are by default. Make sure to also specify any embedded struct pointers.

PropsCreator should be the function passed in by users of your node (as in it should probably be an argument of the function creating your node).

Create is the function actually specifying your node. You can overwrite all of the functions of the node interface there, with some exceptions that we implement for you.

type StandardMethods

type StandardMethods[P ChildProps[NodeBuilder]] struct {
	OnLoad         func(node *StandardNode[P], parent Node)
	OnUnload       func(node *StandardNode[P])
	OnPropsChanged func(node *StandardNode[P])
	OnUpdate       func(node *StandardNode[P], c *Context) error
	OnHandleEvent  func(node *StandardNode[P], c *Context, event Event) error
	OnDraw         func(node *StandardNode[P], c *Context, image *ebiten.Image)
}

type StandardNode

type StandardNode[P ChildProps[NodeBuilder]] struct {
	// contains filtered or unexported fields
}

func (*StandardNode[P]) Children

func (s *StandardNode[P]) Children() []Node

func (*StandardNode[P]) Context

func (s *StandardNode[P]) Context() *BuildContext

func (*StandardNode[P]) Draw

func (s *StandardNode[P]) Draw(c *Context, image *ebiten.Image)

func (*StandardNode[P]) DrawChild

func (s *StandardNode[P]) DrawChild(c *Context, image *ebiten.Image)

Draw the children of the node

func (*StandardNode[P]) HandleEvent

func (s *StandardNode[P]) HandleEvent(c *Context, event Event) TracedError

func (*StandardNode[P]) HandleEventChild

func (s *StandardNode[P]) HandleEventChild(c *Context, event Event) TracedError

func (*StandardNode[P]) ID

func (s *StandardNode[P]) ID() string

func (*StandardNode[P]) Load

func (s *StandardNode[P]) Load(parent Node)

func (*StandardNode[P]) Parent

func (s *StandardNode[P]) Parent() Node

func (*StandardNode[P]) Props

func (s *StandardNode[P]) Props() P

func (*StandardNode[P]) PropsChanged

func (s *StandardNode[P]) PropsChanged(new P)

func (*StandardNode[P]) Tracker

func (s *StandardNode[P]) Tracker() *Tracker

func (*StandardNode[P]) Unload

func (s *StandardNode[P]) Unload()

func (*StandardNode[P]) Update

func (s *StandardNode[P]) Update(c *Context) TracedError

type State

type State[O any, S any] struct {
	// contains filtered or unexported fields
}

func DefaultState

func DefaultState[O any, S any](state S) *State[O, S]

ONLY USE THIS FOR THE DEFAULT STATE. Sort of like the else branch of an if statement, this state is active if no other state's checker returns true.

func NewState

func NewState[O any, S any](state S, checker func(O) bool) *State[O, S]

Create a new state. Will be activated if checker returned true and no state upper in the ladder has been activated.

func (*State[O, S]) Load

func (s *State[O, S]) Load()

These functions are just required to implement the interface, they don't really matter

func (*State[O, S]) Transition

func (s *State[O, S]) Transition(in bool) TransitionProperties

func (*State[O, S]) Unload

func (s *State[O, S]) Unload()

type StateMachine

type StateMachine[O any, S comparable] struct {
	// contains filtered or unexported fields
}

func NewStateMachine

func NewStateMachine[O any, S comparable](create StateMachineCreate[O, S]) *StateMachine[O, S]

Create a new StateMachine.

Some things to keep in mind: - The first states are the highest priority (just like in a if statement). - def is the default state meaning when no other state works for the conditions, it will be used.

func (*StateMachine[O, S]) Draw

func (sm *StateMachine[O, S]) Draw(now time.Time, drawFunc func(state S, frame scath.Timeframe))

Use this to draw the actual object that is supposed to be drawn from the state in the StateMachine.

func (*StateMachine[O, S]) Update

func (sm *StateMachine[O, S]) Update(now time.Time, obj O)

Call to update the state in the StateMachine.

type StateMachineCreate

type StateMachineCreate[O any, S comparable] struct {
	// What transition to use between states. If not set, no transition will be used.
	Transition optional.O[TransitionProperties]

	// All the states in StateMachine
	States []*State[O, S]

	// The default state (at the start, should not be in States)
	Default *State[O, S]
}

A struct to create a new StateMachine.

type TracedError

type TracedError interface {
	error
	// contains filtered or unexported methods
}

func NewTracedError

func NewTracedError(identifiable Identifiable, err error) TracedError

Create a new error that actually traces the path of different identifiable objects. This makes it visible where an error happened for more easy debugging.

To use this, just wrap all of the times you return an error with this function.

type Tracker

type Tracker struct {
	// contains filtered or unexported fields
}

TODO: We need a method for actually, after the props are created, running all the effects cause otherwise those parts of the props won't be set, an ideal thing to do additionally would be to when the effects are ran, track which signals were added in each effect and then create a mapping between signal -> effect index, that way we could only re-run the effects that matter, for others we just re-run all effects obv.

func NewTracker

func NewTracker(context *BuildContext, onChange func()) *Tracker

func (*Tracker) Clear

func (t *Tracker) Clear()

Clear removes all tracked signals and is safe to call multiple times.

func (*Tracker) Effect

func (t *Tracker) Effect(handler func())

Effect adds a new handler being called when the thing changes, use this to actually react to changes of signals (runs first immediately after being called).

RECURSIVE EFFECTS ARE NOT ALLOWED.

func (*Tracker) OnChange

func (t *Tracker) OnChange(t2 *Tracker, handler func())

On change will be called when anything subscribed to the tracker changes, unlike effect, it does not track dependencies, this should be used for components that share a tracker across multiple nodes.

Also runs the handler once after being added.

func (*Tracker) Tracker

func (t *Tracker) Tracker() *Tracker

Implement Tracking interface

type Tracking

type Tracking interface {
	// Should return the tracker for the current Node
	Tracker() *Tracker
}

type TransitionCapable

type TransitionCapable interface {
	// Transition is called when the state is transitioned in or out to configure the transition properly.
	Transition(in bool) TransitionProperties

	// Load is called when the state is loaded.
	Load()

	// Unload is called when the state is unloaded.
	Unload()
}

type TransitionProperties

type TransitionProperties struct {
	// If the transition is isolated, the next / previous state will be transitioned in / out after.
	//
	// If the duration is not the same, the transition currently coming in always wins since it is drawn on top and the other state will just be dropped.
	//
	// Isolation will always be prioritied over non-isolation.
	Isolated bool

	// How long the transition should take. 0 = instant
	Duration time.Duration
}

func NoTransition

func NoTransition() TransitionProperties

func (TransitionProperties) ToTimeframe

func (tp TransitionProperties) ToTimeframe(now time.Time, outTransition optional.O[TransitionProperties]) scath.Timeframe

ToTimeframe converts the transition properties to a scath.Timeframe.

type TransitioningState

type TransitioningState[T TransitionCapable] struct {
	// contains filtered or unexported fields
}

TransitioningState is a struct storing one object that can transition.

NOT GOROUTINE SAFE

func NewTransitioningState

func NewTransitioningState[T TransitionCapable](now time.Time, state T) *TransitioningState[T]

NewTransitioningState creates a new TransitioningState with the given state.

The in transition will be initialized to start immediately.

func (*TransitioningState[T]) GetCurrent

func (ts *TransitioningState[T]) GetCurrent() optional.O[T]

GetCurrent returns the current state, immediately returns new state, even when the transition is not over.

func (*TransitioningState[T]) Set

func (ts *TransitioningState[T]) Set(now time.Time, state optional.O[T])

Set the state in the TransitioningState. You can also use nil to transition the thing out.

This will not handle setting the same thing twice, please deal with that at a higher level since comparisons in here are expensive.

func (*TransitioningState[T]) SetEmpty

func (ts *TransitioningState[T]) SetEmpty(now time.Time)

func (*TransitioningState[T]) Update

func (ts *TransitioningState[T]) Update(now time.Time, update func(T, scath.Timeframe) error) error

Update should be called to both render and update the state of the transitions.

type UpdateQueue

type UpdateQueue struct {
	// contains filtered or unexported fields
}

func NewUpdateQueue

func NewUpdateQueue() *UpdateQueue

func (*UpdateQueue) Clear

func (u *UpdateQueue) Clear()

Clear removes all callbacks from the queue without executing them

func (*UpdateQueue) Push

func (u *UpdateQueue) Push(tracker *Tracker, effect int, callback func())

Push adds a callback to the queue, it's indexed by the tracker pointer and effect ID to avoid duplicates

func (*UpdateQueue) Update

func (u *UpdateQueue) Update()

Update runs all the callbacks in the queue and then clears it

Directories

Path Synopsis
The paint package provides utilities for painting all kinds of things using Ebiten.
The paint package provides utilities for painting all kinds of things using Ebiten.
This package provides support for creating world layers using declarative state.
This package provides support for creating world layers using declarative state.
This package provides support for rich UI layers with input handling, rendering, layouting and declarative UI.
This package provides support for rich UI layers with input handling, rendering, layouting and declarative UI.
uinode
This package provides very basic nodes that work with scaffui.
This package provides very basic nodes that work with scaffui.
Scaff + math = scath.
Scaff + math = scath.
Scaff's utility package.
Scaff's utility package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL