1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-18 02:16:23 -05:00
OpenDiablo2/d2core/d2gui/button.go
Maxime Lavigne (malavv) 0a78a1adcc
Centralized usage of Fonts to fix cache #515 (#556)
The split between d2ui and d2asset Font version caused incorrect caching between the two. After looking at d2interface.Font, I saw the d2asset was the most recent and more tightly and cleanly packaged.

I therefore removed the old d2ui.Font and embedded the d2asset version in the d2ui.Label and d2ui.Button.

Looking at the code of d2ui, it would be logical to completly swap it for their d2gui version. But at least for the moment, the d2ui.Button as more functionality since it embeds a Label (instead of a font), and this label now has multiline horizontal alignement.
2020-07-07 20:16:22 -04:00

133 lines
2.9 KiB
Go

package d2gui
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
type buttonState int
const (
buttonStateDefault buttonState = iota
buttonStatePressed
buttonStateToggled
buttonStatePressedToggled
)
// Button is a user actionable drawable toggle switch
type Button struct {
widgetBase
width int
height int
state buttonState
surfaces []d2interface.Surface
}
func createButton(renderer d2interface.Renderer, text string, buttonStyle ButtonStyle) (*Button, error) {
config, ok := buttonStyleConfigs[buttonStyle]
if !ok {
return nil, errors.New("invalid button style")
}
animation, err := d2asset.LoadAnimation(config.animationPath, config.palettePath)
if err != nil {
return nil, err
}
var buttonWidth int
for i := 0; i < config.segmentsX; i++ {
w, _, err := animation.GetFrameSize(i)
if err != nil {
return nil, err
}
buttonWidth += w
}
var buttonHeight int
for i := 0; i < config.segmentsY; i++ {
_, h, err := animation.GetFrameSize(i * config.segmentsY)
if err != nil {
return nil, err
}
buttonHeight += h
}
font, err := loadFont(config.fontStyle)
if err != nil {
return nil, err
}
textColor := color.RGBA{R: 0x64, G: 0x64, B: 0x64, A: 0xff}
textWidth, textHeight := font.GetTextMetrics(text)
textX := buttonWidth/2 - textWidth/2
textY := buttonHeight/2 - textHeight/2 + config.textOffset
surfaceCount := animation.GetFrameCount() / (config.segmentsX * config.segmentsY)
surfaces := make([]d2interface.Surface, surfaceCount)
for i := 0; i < surfaceCount; i++ {
surface, err := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
if err != nil {
return nil, err
}
if err := renderSegmented(animation, config.segmentsX, config.segmentsY, i, surface); err != nil {
return nil, err
}
font.SetColor(textColor)
var textOffsetX, textOffsetY int
switch buttonState(i) {
case buttonStatePressed, buttonStatePressedToggled:
textOffsetX = -2
textOffsetY = 2
}
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
err = font.RenderText(text, surface)
surface.Pop()
if err != nil {
return nil, err
}
surfaces[i] = surface
}
button := &Button{width: buttonWidth, height: buttonHeight, surfaces: surfaces}
button.SetVisible(true)
return button, nil
}
func (b *Button) onMouseButtonDown(event d2interface.MouseEvent) bool {
b.state = buttonStatePressed
return false
}
func (b *Button) onMouseButtonUp(event d2interface.MouseEvent) bool {
b.state = buttonStateDefault
return false
}
func (b *Button) onMouseLeave(event d2interface.MouseMoveEvent) bool {
b.state = buttonStateDefault
return false
}
func (b *Button) render(target d2interface.Surface) error {
return target.Render(b.surfaces[b.state])
}
func (b *Button) getSize() (int, int) {
return b.width, b.height
}