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 }