Start work on menu interactivity.
With this commit, we get a ui.Interface and ui.Widget type. The interface monitors hover and mouse click state and tells the widgets about them; the widgets execute code specified by the application when events occur. Next step: have wh40k load the main menu and play sound, etc.
This commit is contained in:
84
internal/ui/widget.go
Normal file
84
internal/ui/widget.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"image"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
|
||||
"code.ur.gs/lupine/ordoor/internal/assetstore"
|
||||
"code.ur.gs/lupine/ordoor/internal/menus"
|
||||
)
|
||||
|
||||
// Widget represents an interactive area of the screen. Backgrounds and other
|
||||
// non-interactive areas are not widgets.
|
||||
type Widget struct {
|
||||
// Position on the screen in original (i.e., unscaled) coordinates
|
||||
Bounds image.Rectangle
|
||||
// Tooltip string // TODO: show the tooltip when hovering?
|
||||
|
||||
OnHoverEnter func()
|
||||
OnHoverLeave func()
|
||||
|
||||
// Mouse up can happen without a click taking place if, for instance, the
|
||||
// mouse cursor leaves the bounds while still pressed.
|
||||
OnMouseDown func()
|
||||
OnMouseClick func()
|
||||
OnMouseUp func()
|
||||
|
||||
// These are expected to have the same dimensions as the Bounds
|
||||
hoverAnimation []*ebiten.Image
|
||||
hoverState bool
|
||||
|
||||
// FIXME: We assume right mouse button isn't needed here
|
||||
// TODO: down, up, and click hooks.
|
||||
mouseButtonDownImage *ebiten.Image
|
||||
mouseButtonState bool
|
||||
|
||||
path []int
|
||||
record *menus.Record
|
||||
sprite *assetstore.Sprite
|
||||
}
|
||||
|
||||
func (w *Widget) hovering(value bool) {
|
||||
if w.OnHoverEnter != nil && !w.hoverState && value {
|
||||
w.OnHoverEnter()
|
||||
}
|
||||
|
||||
if w.OnHoverLeave != nil && w.hoverState && !value {
|
||||
w.OnHoverLeave()
|
||||
}
|
||||
|
||||
w.hoverState = value
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Widget) mouseButton(value bool) {
|
||||
if w.OnMouseDown != nil && !w.mouseButtonState && value {
|
||||
w.OnMouseDown()
|
||||
}
|
||||
|
||||
if w.mouseButtonState && !value {
|
||||
if w.OnMouseClick != nil && w.hoverState {
|
||||
w.OnMouseClick()
|
||||
}
|
||||
|
||||
if w.OnMouseUp != nil {
|
||||
w.OnMouseUp()
|
||||
}
|
||||
}
|
||||
|
||||
w.mouseButtonState = value
|
||||
}
|
||||
|
||||
func (w *Widget) Image(aniStep int) (*ebiten.Image, error) {
|
||||
if w.hoverState && w.mouseButtonState {
|
||||
return w.mouseButtonDownImage, nil
|
||||
}
|
||||
|
||||
if w.hoverState && len(w.hoverAnimation) > 0 {
|
||||
return w.hoverAnimation[(aniStep)%len(w.hoverAnimation)], nil
|
||||
}
|
||||
|
||||
return w.sprite.Image, nil
|
||||
}
|
Reference in New Issue
Block a user