From c67ee206cd6e2e22d4f8f300897451863d25e885 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Sun, 22 Mar 2020 23:29:40 +0000 Subject: [PATCH] Implement hypertext (badly) --- internal/ui/interface.go | 30 +++++++++++++------ internal/ui/setup_handlers.go | 54 ++++++++++++++++++++++++++--------- internal/ui/static_element.go | 15 ++++++++++ internal/ui/widget.go | 6 +++- 4 files changed, 82 insertions(+), 23 deletions(-) create mode 100644 internal/ui/static_element.go diff --git a/internal/ui/interface.go b/internal/ui/interface.go index 4fe44e8..823ed6d 100644 --- a/internal/ui/interface.go +++ b/internal/ui/interface.go @@ -23,7 +23,7 @@ import ( type Interface struct { Name string menu *assetstore.Menu - static []*assetstore.Sprite // Static elements in the interface + static []*staticElement ticks int widgets []*Widget } @@ -75,15 +75,24 @@ func (i *Interface) Update(screenX, screenY int) 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()) do := &ebiten.DrawImageOptions{GeoM: geo} - for _, sprite := range i.static { - do.GeoM.Translate(geo.Apply(float64(sprite.XOffset), float64(sprite.YOffset))) - if err := screen.DrawImage(sprite.Image, do); err != nil { - return err + for _, s := range i.static { + if s.image != nil { + do.GeoM.Translate(geo.Apply(float64(s.bounds.Min.X), float64(s.bounds.Min.X))) + 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 { @@ -103,11 +112,16 @@ func (i *Interface) Draw(screen *ebiten.Image) error { do.GeoM = geo if widget.hoverState && widget.Tooltip != "" { - mouseX, mouseY := ebiten.CursorPosition() - ebitenutil.DebugPrintAt(screen, widget.Tooltip, mouseX+16, mouseY-16) + tooltip = widget.Tooltip } } + if tooltip != "" { + cX, cY := ebiten.CursorPosition() + + ebitenutil.DebugPrintAt(screen, tooltip, cX+16, cY-16) + } + return nil } diff --git a/internal/ui/setup_handlers.go b/internal/ui/setup_handlers.go index 356d8b8..9dc778d 100644 --- a/internal/ui/setup_handlers.go +++ b/internal/ui/setup_handlers.go @@ -6,18 +6,20 @@ import ( "code.ur.gs/lupine/ordoor/internal/menus" ) -// Setup handlers know how to handle each type of widget -var setupHandlers = map[menus.MenuType]func(i *Interface, r *menus.Record) error { - menus.TypeStatic: handleStatic, - menus.TypeMenu: nil, - menus.TypeButton: handleButton, - menus.TypeInvokeButton: handleInvokeButton, - menus.TypeOverlay: handleStatic, // FIXME: more? - menus.TypeHypertext: nil, // FIXME: handle this - menus.TypeCheckbox: handleCheckbox, - menus.TypeAnimationSample: nil, // FIXME: handle this - menus.TypeMainButton: handleMainButton, - menus.TypeSlider: nil, // FIXME: handle this +// Setup handlers know how to handle each type of widget. +// TODO: it might be better to have a Widget interface and different structs for +// each type of widget, but let's see how far we can push this model. +var setupHandlers = map[menus.MenuType]func(i *Interface, r *menus.Record) error{ + menus.TypeStatic: handleStatic, + menus.TypeMenu: nil, + menus.TypeButton: handleButton, + menus.TypeInvokeButton: handleInvokeButton, + menus.TypeOverlay: nil, // FIXME: What's it for? + menus.TypeHypertext: handleHypertext, + menus.TypeCheckbox: handleCheckbox, + menus.TypeAnimationSample: nil, // FIXME: handle this + menus.TypeMainButton: handleMainButton, + menus.TypeSlider: nil, // FIXME: handle this } func handleStatic(i *Interface, record *menus.Record) error { @@ -33,7 +35,32 @@ func handleStatic(i *Interface, record *menus.Record) error { 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 } @@ -159,7 +186,6 @@ func handleMainButton(i *Interface, record *menus.Record) error { return nil } - // Widgets need a bounding box determined by a sprite. Different widgets specify // their sprites in different attributes, so pass in the right sprite externally func (i *Interface) widgetFromRecord(record *menus.Record, spriteId int) (*Widget, error) { diff --git a/internal/ui/static_element.go b/internal/ui/static_element.go new file mode 100644 index 0000000..033e952 --- /dev/null +++ b/internal/ui/static_element.go @@ -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 +} diff --git a/internal/ui/widget.go b/internal/ui/widget.go index d48d554..c7fbbbd 100644 --- a/internal/ui/widget.go +++ b/internal/ui/widget.go @@ -86,7 +86,11 @@ func (w *Widget) mouseButton(value bool) { func (w *Widget) Image(aniStep int) (*ebiten.Image, error) { 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 {