Added tooltips.
This commit is contained in:
parent
f57a9dd845
commit
013fe4bdb6
@ -21,7 +21,7 @@ type BuyFlowerButton struct {
|
|||||||
|
|
||||||
func NewBuyFlowerButton(icon, iconDisabled, flowerID string, flower FlowerDescriptor, onClick EventContextFn) *BuyFlowerButton {
|
func NewBuyFlowerButton(icon, iconDisabled, flowerID string, flower FlowerDescriptor, onClick EventContextFn) *BuyFlowerButton {
|
||||||
return &BuyFlowerButton{
|
return &BuyFlowerButton{
|
||||||
IconButton: *NewIconButtonConfig(icon, onClick, func(b *IconButton) {
|
IconButton: *NewIconButtonConfigure(icon, onClick, func(b *IconButton) {
|
||||||
b.IconDisabled = iconDisabled
|
b.IconDisabled = iconDisabled
|
||||||
b.IsDisabled = !flower.Unlocked
|
b.IsDisabled = !flower.Unlocked
|
||||||
}),
|
}),
|
||||||
|
@ -136,6 +136,8 @@ func run() error {
|
|||||||
app.Arrange(ctx, tins2020.RectAbs(0, 0, w, h))
|
app.Arrange(ctx, tins2020.RectAbs(0, 0, w, h))
|
||||||
ctx.Settings.Window.Size = tins2020.PtPtr(w, h)
|
ctx.Settings.Window.Size = tins2020.PtPtr(w, h)
|
||||||
}
|
}
|
||||||
|
case *sdl.MouseMotionEvent:
|
||||||
|
ctx.MousePosition = tins2020.Pt(e.X, e.Y)
|
||||||
}
|
}
|
||||||
app.Handle(ctx, event)
|
app.Handle(ctx, event)
|
||||||
}
|
}
|
||||||
|
13
context.go
13
context.go
@ -6,12 +6,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Renderer *sdl.Renderer
|
Renderer *sdl.Renderer
|
||||||
Fonts Fonts
|
Fonts Fonts
|
||||||
Resources Resources
|
Resources Resources
|
||||||
Textures Textures
|
Textures Textures
|
||||||
Settings Settings
|
Settings Settings
|
||||||
ShouldQuit bool
|
MousePosition Point
|
||||||
|
ShouldQuit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContext(res *rice.Box) (*Context, error) {
|
func NewContext(res *rice.Box) (*Context, error) {
|
||||||
|
23
control.go
23
control.go
@ -22,12 +22,35 @@ func EmptyEvent(fn EventFn) EventContextFn {
|
|||||||
type ControlBase struct {
|
type ControlBase struct {
|
||||||
Bounds Rectangle
|
Bounds Rectangle
|
||||||
|
|
||||||
|
FontName string
|
||||||
|
Foreground sdl.Color
|
||||||
|
|
||||||
IsDisabled bool
|
IsDisabled bool
|
||||||
IsMouseOver bool
|
IsMouseOver bool
|
||||||
|
|
||||||
OnLeftMouseButtonClick EventContextFn
|
OnLeftMouseButtonClick EventContextFn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ControlBase) ActualForeground() sdl.Color {
|
||||||
|
var none sdl.Color
|
||||||
|
if c.Foreground == none {
|
||||||
|
return MustHexColor("#ffffff")
|
||||||
|
}
|
||||||
|
return c.Foreground
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ControlBase) ActualFont(ctx *Context) *Font {
|
||||||
|
name := c.ActualFontName()
|
||||||
|
return ctx.Fonts.Font(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ControlBase) ActualFontName() string {
|
||||||
|
if len(c.FontName) == 0 {
|
||||||
|
return "default"
|
||||||
|
}
|
||||||
|
return c.FontName
|
||||||
|
}
|
||||||
|
|
||||||
func (b *ControlBase) Arrange(ctx *Context, bounds Rectangle) { b.Bounds = bounds }
|
func (b *ControlBase) Arrange(ctx *Context, bounds Rectangle) { b.Bounds = bounds }
|
||||||
|
|
||||||
func (b *ControlBase) Init(*Context) error { return nil }
|
func (b *ControlBase) Init(*Context) error { return nil }
|
||||||
|
@ -100,44 +100,61 @@ func (c *GameControls) Init(ctx *Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.top.Orientation = OrientationHorizontal
|
c.top.Orientation = OrientationHorizontal
|
||||||
c.pause = NewIconButtonConfig("control-pause", EmptyEvent(func() {
|
c.pause = NewIconButtonConfigure("control-pause", EmptyEvent(func() {
|
||||||
c.game.Pause()
|
c.game.Pause()
|
||||||
}), func(b *IconButton) {
|
}), func(b *IconButton) {
|
||||||
b.IconDisabled = "control-pause-disabled"
|
b.IconDisabled = "control-pause-disabled"
|
||||||
|
b.Tooltip.Text = "Pause game"
|
||||||
})
|
})
|
||||||
c.run = NewIconButtonConfig("control-run", EmptyEvent(func() {
|
c.run = NewIconButtonConfigure("control-run", EmptyEvent(func() {
|
||||||
c.game.Run()
|
c.game.Run()
|
||||||
}), func(b *IconButton) {
|
}), func(b *IconButton) {
|
||||||
b.IconDisabled = "control-run-disabled"
|
b.IconDisabled = "control-run-disabled"
|
||||||
|
b.Tooltip.Text = "Run game at normal speed"
|
||||||
})
|
})
|
||||||
c.runFast = NewIconButtonConfig("control-run-fast", EmptyEvent(func() {
|
c.runFast = NewIconButtonConfigure("control-run-fast", EmptyEvent(func() {
|
||||||
c.game.RunFast()
|
c.game.RunFast()
|
||||||
}), func(b *IconButton) {
|
}), func(b *IconButton) {
|
||||||
b.IconDisabled = "control-run-fast-disabled"
|
b.IconDisabled = "control-run-fast-disabled"
|
||||||
|
b.Tooltip.Text = "Run game at fast speed"
|
||||||
})
|
})
|
||||||
c.speedChanged(c.game.Speed)
|
c.speedChanged(c.game.Speed)
|
||||||
c.top.Buttons = []Control{c.pause, c.run, c.runFast}
|
c.top.Buttons = []Control{c.pause, c.run, c.runFast}
|
||||||
|
|
||||||
c.menu.Background = MustHexColor("#356dad")
|
c.menu.Background = MustHexColor("#356dad")
|
||||||
c.menu.Buttons = []Control{
|
c.menu.Buttons = []Control{
|
||||||
NewIconButtonConfig("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
NewIconButtonConfigure("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
||||||
b.IsDisabled = true
|
b.IsDisabled = true
|
||||||
b.IconDisabled = "#afafaf"
|
b.IconDisabled = "#afafaf"
|
||||||
}),
|
}),
|
||||||
NewIconButton("control-save", func(*Context) { c.game.Save() }),
|
NewIconButtonConfigure("control-save", func(*Context) { c.game.Save() }, func(b *IconButton) {
|
||||||
NewIconButton("control-load", func(ctx *Context) {
|
b.Tooltip.Text = "Save game (overwrites previous save; no confirmation)"
|
||||||
|
}),
|
||||||
|
NewIconButtonConfigure("control-load", func(ctx *Context) {
|
||||||
c.game.Load()
|
c.game.Load()
|
||||||
c.updateFlowerControls(ctx)
|
c.updateFlowerControls(ctx)
|
||||||
|
}, func(b *IconButton) {
|
||||||
|
b.Tooltip.Text = "Load last saved game (no confirmation)"
|
||||||
}),
|
}),
|
||||||
NewIconButton("control-new", func(ctx *Context) {
|
NewIconButtonConfigure("control-new", func(ctx *Context) {
|
||||||
c.game.New()
|
c.game.New()
|
||||||
c.updateFlowerControls(ctx)
|
c.updateFlowerControls(ctx)
|
||||||
|
}, func(b *IconButton) {
|
||||||
|
b.Tooltip.Text = "Start new game (no confirmation)"
|
||||||
|
}),
|
||||||
|
NewIconButtonConfigure("control-information", c.dialogs.ShowIntro, func(b *IconButton) {
|
||||||
|
b.Tooltip.Text = "Show information/intro"
|
||||||
}),
|
}),
|
||||||
NewIconButton("control-information", c.dialogs.ShowIntro),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.shovel = NewIconButtonConfig("control-shovel", func(*Context) { c.game.SelectShovel() }, func(b *IconButton) { b.IconHeight = 32 })
|
c.shovel = NewIconButtonConfigure("control-shovel", func(*Context) { c.game.SelectShovel() }, func(b *IconButton) {
|
||||||
c.research = NewIconButtonConfig("control-research", c.dialogs.ShowResearch, func(b *IconButton) { b.IconHeight = 32 })
|
b.IconHeight = 32
|
||||||
|
b.Tooltip.Text = "Select harvest tool (key: H)"
|
||||||
|
})
|
||||||
|
c.research = NewIconButtonConfigure("control-research", c.dialogs.ShowResearch, func(b *IconButton) {
|
||||||
|
b.IconHeight = 32
|
||||||
|
b.Tooltip.Text = "Conduct research (key: R)"
|
||||||
|
})
|
||||||
c.otherTools.Buttons = []Control{c.shovel, c.research}
|
c.otherTools.Buttons = []Control{c.shovel, c.research}
|
||||||
|
|
||||||
c.Container.AddChild(&c.menu)
|
c.Container.AddChild(&c.menu)
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package tins2020
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
type HoverEffect int
|
type HoverEffect int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -19,6 +23,7 @@ type IconButton struct {
|
|||||||
IconActive HoverEffect
|
IconActive HoverEffect
|
||||||
IconHover HoverEffect
|
IconHover HoverEffect
|
||||||
|
|
||||||
|
Tooltip Tooltip
|
||||||
IsActive bool
|
IsActive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +36,7 @@ func NewIconButton(icon string, onClick EventContextFn) *IconButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIconButtonConfig(icon string, onClick EventContextFn, configure func(*IconButton)) *IconButton {
|
func NewIconButtonConfigure(icon string, onClick EventContextFn, configure func(*IconButton)) *IconButton {
|
||||||
button := NewIconButton(icon, onClick)
|
button := NewIconButton(icon, onClick)
|
||||||
configure(button)
|
configure(button)
|
||||||
return button
|
return button
|
||||||
@ -57,6 +62,31 @@ func (b *IconButton) activeTexture(ctx *Context) *Texture {
|
|||||||
return ctx.Textures.Texture(b.Icon)
|
return ctx.Textures.Texture(b.Icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *IconButton) Arrange(ctx *Context, bounds Rectangle) {
|
||||||
|
b.ControlBase.Arrange(ctx, bounds)
|
||||||
|
b.Tooltip.Arrange(ctx, bounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *IconButton) Handle(ctx *Context, event sdl.Event) bool {
|
||||||
|
if b.ControlBase.Handle(ctx, event) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if b.Tooltip.Handle(ctx, event) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *IconButton) Init(ctx *Context) error {
|
||||||
|
if err := b.ControlBase.Init(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := b.Tooltip.Init(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *IconButton) Render(ctx *Context) {
|
func (b *IconButton) Render(ctx *Context) {
|
||||||
iconTexture := b.activeTexture(ctx)
|
iconTexture := b.activeTexture(ctx)
|
||||||
|
|
||||||
@ -81,6 +111,10 @@ func (b *IconButton) Render(ctx *Context) {
|
|||||||
ctx.Renderer.FillRect(b.Bounds.SDLPtr())
|
ctx.Renderer.FillRect(b.Bounds.SDLPtr())
|
||||||
}
|
}
|
||||||
iconTexture.SetColor(White)
|
iconTexture.SetColor(White)
|
||||||
|
|
||||||
|
if len(b.Tooltip.Text) > 0 && b.IsMouseOver {
|
||||||
|
b.Tooltip.Render(ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Scale int
|
type Scale int
|
||||||
|
27
label.go
27
label.go
@ -2,37 +2,18 @@ package tins2020
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Label struct {
|
type Label struct {
|
||||||
ControlBase
|
ControlBase
|
||||||
|
|
||||||
FontColor sdl.Color
|
|
||||||
FontName string
|
|
||||||
Text string
|
Text string
|
||||||
Alignment TextAlignment
|
Alignment TextAlignment
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Label) fontColor() sdl.Color {
|
|
||||||
var none sdl.Color
|
|
||||||
if l.FontColor == none {
|
|
||||||
return MustHexColor("#ffffff")
|
|
||||||
}
|
|
||||||
return l.FontColor
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Label) fontName() string {
|
|
||||||
if len(l.FontName) == 0 {
|
|
||||||
return "default"
|
|
||||||
}
|
|
||||||
return l.FontName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *Label) Render(ctx *Context) {
|
func (l *Label) Render(ctx *Context) {
|
||||||
font := ctx.Fonts.Font(l.fontName())
|
font := ctx.Fonts.Font(l.ActualFontName())
|
||||||
color := l.fontColor()
|
color := l.ActualForeground()
|
||||||
bottom := l.Bounds.Y + l.Bounds.H
|
bottom := l.Bounds.Y + l.Bounds.H
|
||||||
switch l.Alignment {
|
switch l.Alignment {
|
||||||
case TextAlignmentCenter:
|
case TextAlignmentCenter:
|
||||||
@ -49,8 +30,8 @@ type Paragraph struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Paragraph) Render(ctx *Context) {
|
func (p *Paragraph) Render(ctx *Context) {
|
||||||
font := ctx.Fonts.Font(p.fontName())
|
font := ctx.Fonts.Font(p.ActualFontName())
|
||||||
color := p.fontColor()
|
color := p.ActualForeground()
|
||||||
fontHeight := int32(font.Height())
|
fontHeight := int32(font.Height())
|
||||||
lines := strings.Split(p.Text, "\n")
|
lines := strings.Split(p.Text, "\n")
|
||||||
|
|
||||||
|
@ -62,11 +62,10 @@ func (d *LargeDialog) Arrange(ctx *Context, bounds Rectangle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *LargeDialog) Init(ctx *Context) error {
|
func (d *LargeDialog) Init(ctx *Context) error {
|
||||||
d.title = Label{
|
d.title.Text = "Botanim"
|
||||||
Text: "Botanim",
|
d.title.FontName = "title"
|
||||||
FontName: "title",
|
d.title.Alignment = TextAlignmentCenter
|
||||||
Alignment: TextAlignmentCenter,
|
|
||||||
}
|
|
||||||
d.close = IconButton{
|
d.close = IconButton{
|
||||||
Icon: "control-cancel",
|
Icon: "control-cancel",
|
||||||
IconHover: HoverEffectColor,
|
IconHover: HoverEffectColor,
|
||||||
|
59
tooltip.go
Normal file
59
tooltip.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import "github.com/veandco/go-sdl2/sdl"
|
||||||
|
|
||||||
|
type Tooltip struct {
|
||||||
|
ControlBase
|
||||||
|
|
||||||
|
Text string
|
||||||
|
}
|
||||||
|
|
||||||
|
const tooltipBorderThickness = 1
|
||||||
|
const tooltipHorizontalPadding = 4
|
||||||
|
const tooltipMouseDistance = 12
|
||||||
|
|
||||||
|
func (t *Tooltip) Handle(ctx *Context, event sdl.Event) bool {
|
||||||
|
if len(t.Text) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
font := ctx.Fonts.Font(t.ActualFontName())
|
||||||
|
windowW, windowH, err := ctx.Renderer.GetOutputSize()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
labelW, labelH, err := font.SizeUTF8(t.Text)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
mouse := ctx.MousePosition
|
||||||
|
width := int32(labelW) + 2*tooltipBorderThickness + 2*tooltipHorizontalPadding
|
||||||
|
height := int32(labelH) + 2*tooltipBorderThickness
|
||||||
|
|
||||||
|
left := mouse.X + tooltipMouseDistance
|
||||||
|
top := mouse.Y + tooltipMouseDistance
|
||||||
|
if left+width > windowW {
|
||||||
|
left = mouse.X - tooltipMouseDistance - width
|
||||||
|
}
|
||||||
|
if top+height > windowH {
|
||||||
|
top = mouse.Y - tooltipMouseDistance - height
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Bounds = Rect(left, top, width, height)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Tooltip) Render(ctx *Context) {
|
||||||
|
SetDrawColor(ctx.Renderer, Black)
|
||||||
|
ctx.Renderer.FillRect(t.Bounds.SDLPtr())
|
||||||
|
|
||||||
|
SetDrawColor(ctx.Renderer, White)
|
||||||
|
ctx.Renderer.DrawRect(t.Bounds.SDLPtr())
|
||||||
|
|
||||||
|
font := t.ActualFont(ctx)
|
||||||
|
|
||||||
|
bottomLeft := Pt(t.Bounds.X+tooltipBorderThickness+tooltipHorizontalPadding, t.Bounds.Y+t.Bounds.H-tooltipBorderThickness)
|
||||||
|
font.RenderCopy(ctx.Renderer, t.Text, bottomLeft, White)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user