166 lines
3.5 KiB
Go
166 lines
3.5 KiB
Go
package ui
|
|
|
|
import (
|
|
"image"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/assetstore"
|
|
"code.ur.gs/lupine/ordoor/internal/menus"
|
|
)
|
|
|
|
// A button without hover animation
|
|
// FIXME: Keyboard.mnu has TypeSimpleButton instances that seem to include a
|
|
// hover in the SpriteId field
|
|
type button struct {
|
|
locator string
|
|
|
|
rect image.Rectangle
|
|
|
|
baseSpr *assetstore.Sprite
|
|
clickSpr *assetstore.Sprite
|
|
frozenSpr *assetstore.Sprite
|
|
|
|
clickImpl
|
|
freezeImpl
|
|
hoverImpl
|
|
}
|
|
|
|
// A button with hover animation
|
|
type mainButton struct {
|
|
hoverAnim animation
|
|
|
|
button
|
|
}
|
|
|
|
func (d *Driver) buildButton(p *menus.Properties) (*button, *Widget, error) {
|
|
sprites, err := d.menu.Sprites(p.ObjectIdx, p.BaseSpriteID(), 3) // base, pressed, disabled
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
btn := &button{
|
|
locator: p.Locator,
|
|
rect: sprites[0].Rect.Add(p.Point()),
|
|
baseSpr: sprites[0],
|
|
clickSpr: sprites[1],
|
|
frozenSpr: sprites[2],
|
|
hoverImpl: hoverImpl{text: p.Text},
|
|
}
|
|
|
|
widget := &Widget{
|
|
Locator: p.Locator,
|
|
Active: p.Active,
|
|
ownClickables: []clickable{btn},
|
|
ownFreezables: []freezable{btn},
|
|
ownHoverables: []hoverable{btn},
|
|
ownPaintables: []paintable{btn},
|
|
}
|
|
|
|
return btn, widget, nil
|
|
}
|
|
|
|
func (d *Driver) buildMainButton(p *menus.Properties) (*mainButton, *Widget, error) {
|
|
sprites, err := d.menu.Sprites(p.ObjectIdx, p.Share, 3) // base, pressed, disabled
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
hovers, err := d.menu.Images(p.ObjectIdx, p.SpriteId[0], p.DrawType)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
btn := &mainButton{
|
|
hoverAnim: animation(hovers),
|
|
button: button{
|
|
locator: p.Locator,
|
|
rect: sprites[0].Rect.Add(p.Point()),
|
|
baseSpr: sprites[0],
|
|
clickSpr: sprites[1],
|
|
frozenSpr: sprites[2],
|
|
hoverImpl: hoverImpl{text: p.Text},
|
|
},
|
|
}
|
|
|
|
widget := &Widget{
|
|
Locator: p.Locator,
|
|
Active: p.Active,
|
|
ownClickables: []clickable{btn},
|
|
ownFreezables: []freezable{btn},
|
|
ownHoverables: []hoverable{btn},
|
|
ownPaintables: []paintable{btn},
|
|
}
|
|
|
|
return btn, widget, nil
|
|
}
|
|
|
|
func (d *Driver) buildDoorHotspot(p *menus.Properties) (*button, *Widget, error) {
|
|
sprites, err := d.menu.Sprites(p.ObjectIdx, p.Share, 2) // base, pressed
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
btn := &button{
|
|
locator: p.Locator,
|
|
rect: sprites[0].Rect.Add(p.Point()),
|
|
baseSpr: sprites[0],
|
|
clickSpr: sprites[1],
|
|
frozenSpr: sprites[0], // No disabled sprite
|
|
hoverImpl: hoverImpl{text: p.Text},
|
|
}
|
|
|
|
widget := &Widget{
|
|
Locator: p.Locator,
|
|
Active: p.Active,
|
|
ownClickables: []clickable{btn},
|
|
ownFreezables: []freezable{btn},
|
|
ownHoverables: []hoverable{btn},
|
|
ownPaintables: []paintable{btn},
|
|
}
|
|
|
|
return btn, widget, nil
|
|
|
|
}
|
|
|
|
func (b *button) id() string {
|
|
return b.locator
|
|
}
|
|
|
|
func (b *button) bounds() image.Rectangle {
|
|
return b.rect
|
|
}
|
|
|
|
func (b *button) mouseDownState() bool {
|
|
if b.isFrozen() {
|
|
return false
|
|
}
|
|
|
|
return b.clickImpl.mouseDownState()
|
|
}
|
|
|
|
func (b *button) registerMouseClick() {
|
|
if !b.isFrozen() {
|
|
b.clickImpl.registerMouseClick()
|
|
}
|
|
}
|
|
|
|
func (b *button) regions(tick int) []region {
|
|
if b.isFrozen() {
|
|
return oneRegion(b.bounds().Min, b.frozenSpr.Image)
|
|
}
|
|
|
|
if b.mouseDownState() {
|
|
return oneRegion(b.bounds().Min, b.clickSpr.Image)
|
|
}
|
|
|
|
return oneRegion(b.bounds().Min, b.baseSpr.Image)
|
|
}
|
|
|
|
func (m *mainButton) regions(tick int) []region {
|
|
// FIXME: main button should complete its animation when we mouse away
|
|
if !m.isFrozen() && !m.mouseDownState() && m.hoverState() {
|
|
return oneRegion(m.bounds().Min, m.hoverAnim.image(tick))
|
|
}
|
|
|
|
return m.button.regions(tick)
|
|
}
|