Implement hypertext (badly)
This commit is contained in:
@@ -23,7 +23,7 @@ import (
|
|||||||
type Interface struct {
|
type Interface struct {
|
||||||
Name string
|
Name string
|
||||||
menu *assetstore.Menu
|
menu *assetstore.Menu
|
||||||
static []*assetstore.Sprite // Static elements in the interface
|
static []*staticElement
|
||||||
ticks int
|
ticks int
|
||||||
widgets []*Widget
|
widgets []*Widget
|
||||||
}
|
}
|
||||||
@@ -75,15 +75,24 @@ func (i *Interface) Update(screenX, screenY int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Interface) Draw(screen *ebiten.Image) error {
|
func (i *Interface) Draw(screen *ebiten.Image) error {
|
||||||
|
var tooltip string // Draw this last, so it's on top of everything
|
||||||
|
|
||||||
|
mousePt := i.getMousePos(screen.Size())
|
||||||
geo := i.scale(screen.Size())
|
geo := i.scale(screen.Size())
|
||||||
do := &ebiten.DrawImageOptions{GeoM: geo}
|
do := &ebiten.DrawImageOptions{GeoM: geo}
|
||||||
|
|
||||||
for _, sprite := range i.static {
|
for _, s := range i.static {
|
||||||
do.GeoM.Translate(geo.Apply(float64(sprite.XOffset), float64(sprite.YOffset)))
|
if s.image != nil {
|
||||||
if err := screen.DrawImage(sprite.Image, do); err != nil {
|
do.GeoM.Translate(geo.Apply(float64(s.bounds.Min.X), float64(s.bounds.Min.X)))
|
||||||
return err
|
if err := screen.DrawImage(s.image, do); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
do.GeoM = geo
|
||||||
|
}
|
||||||
|
|
||||||
|
if mousePt.In(s.bounds) && s.tooltip != "" {
|
||||||
|
tooltip = s.tooltip
|
||||||
}
|
}
|
||||||
do.GeoM = geo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, widget := range i.widgets {
|
for _, widget := range i.widgets {
|
||||||
@@ -103,11 +112,16 @@ func (i *Interface) Draw(screen *ebiten.Image) error {
|
|||||||
do.GeoM = geo
|
do.GeoM = geo
|
||||||
|
|
||||||
if widget.hoverState && widget.Tooltip != "" {
|
if widget.hoverState && widget.Tooltip != "" {
|
||||||
mouseX, mouseY := ebiten.CursorPosition()
|
tooltip = widget.Tooltip
|
||||||
ebitenutil.DebugPrintAt(screen, widget.Tooltip, mouseX+16, mouseY-16)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tooltip != "" {
|
||||||
|
cX, cY := ebiten.CursorPosition()
|
||||||
|
|
||||||
|
ebitenutil.DebugPrintAt(screen, tooltip, cX+16, cY-16)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,18 +6,20 @@ import (
|
|||||||
"code.ur.gs/lupine/ordoor/internal/menus"
|
"code.ur.gs/lupine/ordoor/internal/menus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setup handlers know how to handle each type of widget
|
// Setup handlers know how to handle each type of widget.
|
||||||
var setupHandlers = map[menus.MenuType]func(i *Interface, r *menus.Record) error {
|
// TODO: it might be better to have a Widget interface and different structs for
|
||||||
menus.TypeStatic: handleStatic,
|
// each type of widget, but let's see how far we can push this model.
|
||||||
menus.TypeMenu: nil,
|
var setupHandlers = map[menus.MenuType]func(i *Interface, r *menus.Record) error{
|
||||||
menus.TypeButton: handleButton,
|
menus.TypeStatic: handleStatic,
|
||||||
menus.TypeInvokeButton: handleInvokeButton,
|
menus.TypeMenu: nil,
|
||||||
menus.TypeOverlay: handleStatic, // FIXME: more?
|
menus.TypeButton: handleButton,
|
||||||
menus.TypeHypertext: nil, // FIXME: handle this
|
menus.TypeInvokeButton: handleInvokeButton,
|
||||||
menus.TypeCheckbox: handleCheckbox,
|
menus.TypeOverlay: nil, // FIXME: What's it for?
|
||||||
menus.TypeAnimationSample: nil, // FIXME: handle this
|
menus.TypeHypertext: handleHypertext,
|
||||||
menus.TypeMainButton: handleMainButton,
|
menus.TypeCheckbox: handleCheckbox,
|
||||||
menus.TypeSlider: nil, // FIXME: handle this
|
menus.TypeAnimationSample: nil, // FIXME: handle this
|
||||||
|
menus.TypeMainButton: handleMainButton,
|
||||||
|
menus.TypeSlider: nil, // FIXME: handle this
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleStatic(i *Interface, record *menus.Record) error {
|
func handleStatic(i *Interface, record *menus.Record) error {
|
||||||
@@ -33,7 +35,32 @@ func handleStatic(i *Interface, record *menus.Record) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
i.static = append(i.static, sprite)
|
static := &staticElement{
|
||||||
|
bounds: sprite.Rect,
|
||||||
|
image: sprite.Image,
|
||||||
|
tooltip: record.Desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
i.static = append(i.static, static)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A hypertext is static, but we should only take the bounds from "SHARE", not
|
||||||
|
// display anything.
|
||||||
|
func handleHypertext(i *Interface, record *menus.Record) error {
|
||||||
|
sprite, err := i.menu.Sprite(record.Share)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
static := &staticElement{
|
||||||
|
bounds: sprite.Rect,
|
||||||
|
image: nil,
|
||||||
|
tooltip: record.Desc,
|
||||||
|
}
|
||||||
|
|
||||||
|
i.static = append(i.static, static)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -159,7 +186,6 @@ func handleMainButton(i *Interface, record *menus.Record) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Widgets need a bounding box determined by a sprite. Different widgets specify
|
// Widgets need a bounding box determined by a sprite. Different widgets specify
|
||||||
// their sprites in different attributes, so pass in the right sprite externally
|
// their sprites in different attributes, so pass in the right sprite externally
|
||||||
func (i *Interface) widgetFromRecord(record *menus.Record, spriteId int) (*Widget, error) {
|
func (i *Interface) widgetFromRecord(record *menus.Record, spriteId int) (*Widget, error) {
|
||||||
|
15
internal/ui/static_element.go
Normal file
15
internal/ui/static_element.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A static element is not a widget; it merely displays some pixels and may
|
||||||
|
// optionally have a tooltip for display within bounds
|
||||||
|
type staticElement struct {
|
||||||
|
bounds image.Rectangle
|
||||||
|
image *ebiten.Image
|
||||||
|
tooltip string
|
||||||
|
}
|
@@ -86,7 +86,11 @@ func (w *Widget) mouseButton(value bool) {
|
|||||||
|
|
||||||
func (w *Widget) Image(aniStep int) (*ebiten.Image, error) {
|
func (w *Widget) Image(aniStep int) (*ebiten.Image, error) {
|
||||||
if w.disabled {
|
if w.disabled {
|
||||||
return w.disabledImage, nil
|
if w.disabledImage != nil {
|
||||||
|
return w.disabledImage, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return w.sprite.Image, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.mouseButtonDownImage != nil && w.hoverState && w.mouseButtonState {
|
if w.mouseButtonDownImage != nil && w.hoverState && w.mouseButtonState {
|
||||||
|
Reference in New Issue
Block a user