1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-02-13 20:16:41 -05:00
OpenDiablo2/d2core/d2label/label.go
gravestench deb63a95c8 changes to d2components, d2systems, d2ui, d2enum
go.mod, go.sum:
* updating akara, bugfix in akara.EntityManager.RemoveEntity

d2core
* adding d2core/d2label
* adding d2core/d2bitmapfont

d2ui
* exporting some constants for use elsewhere

d2components
* added bitmap font component (for ui labels)
* added FileLoaded tag component to simplify asset loading filters
* added locale component
* FilePath component renamed to File
* sprite component now contains the sprite and palette path as strings
* adding ui label component

d2enum
* added locale as file type for file "/data/local/use"

d2systems
* changed most info prints to debug prints
* removed unused scene graph testing file (oops!)
* terminal is now rendered above mouse cursor scene
* adding ui widget system for use by the game object factory
* adding test scene for ui labels created with the ui widget system

d2systems/AppBootstrap
* added command line args for profiler
* `--testscene labels` launches the label test
* now adds the local file for processing
* game loop init logic now inside of Init method (the call to
world.Update does this)

d2systems/AssetLoader
* loads the locale file and adds a locale component that other systems
can use
* adds a FileLoaded component after finished loading a file which other
systems can use (like the loading scene)

d2systems/FileSourceResolver
* Now looks for and uses the locale for language/charset filepath
substitution

d2systems/GameClientBootstrap
* game loop init moved to end of AppBootstrap.Init

d2systems/GameObjectFactory
* embedding UI widget factory system

d2systems/BaseScene
* made base scene a little more clear by breaking the process into more
methods

d2systems/LoadingScene
* simplified the entity subscriptions by using the new FileLoaded
component

d2systems/SceneObjectFactory
* adding method for adding labels, buttons to scenes (buttons still WIP)

d2systems/SceneSpriteSystem
* the sprite system now maintains a cache of rendered sprites
2020-12-08 11:24:10 -08:00

185 lines
4.4 KiB
Go

package d2label
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"image/color"
"regexp"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2bitmapfont"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
// New creates a new label, initializing the unexported fields
func New() *Label {
return &Label{
colors: map[int]color.Color{0: color.White},
}
}
// Label represents a user interface label
type Label struct {
dirty bool // used to flag when to re-render the label
text string
textWithColorTokens string
Alignment d2ui.HorizontalAlign
Font *d2bitmapfont.BitmapFont
colors map[int]color.Color
backgroundColor color.Color
}
func (v *Label) Render(target d2interface.Surface) {
lines := strings.Split(v.GetText(), "\n")
yOffset := 0
lastColor := v.colors[0]
v.Font.SetColor(lastColor)
for _, line := range lines {
lw, lh := v.GetTextMetrics(line)
characters := []rune(line)
if v.backgroundColor != nil {
target.Clear(v.backgroundColor)
}
target.PushTranslation(v.GetAlignOffset(lw), yOffset)
for idx := range characters {
character := string(characters[idx])
charWidth, _ := v.GetTextMetrics(character)
if v.colors[idx] != nil {
lastColor = v.colors[idx]
v.Font.SetColor(lastColor)
}
_ = v.Font.RenderText(character, target)
target.PushTranslation(charWidth, 0)
}
target.PopN(len(characters))
yOffset += lh
target.Pop()
}
v.dirty = false
}
// IsDirty returns if the label needs to be re-rendered
func (v *Label) IsDirty() bool {
return v.dirty
}
// GetSize returns the size of the label
func (v *Label) GetSize() (width, height int) {
return v.Font.GetTextMetrics(v.text)
}
// GetTextMetrics returns the width and height of the enclosing rectangle in Pixels.
func (v *Label) GetTextMetrics(text string) (width, height int) {
return v.Font.GetTextMetrics(text)
}
// SetText sets the label's text
func (v *Label) SetText(newText string) {
if v.text == newText {
return
}
v.text = newText
v.dirty = true
v.textWithColorTokens = v.processColorTokens(v.text)
}
// GetText returns the label's textWithColorTokens
func (v *Label) GetText() string {
return v.text
}
// SetBackgroundColor sets the background highlight color
func (v *Label) SetBackgroundColor(c color.Color) {
v.dirty = true
v.backgroundColor = c
}
func (v *Label) processColorTokens(str string) string {
tokenMatch := regexp.MustCompile(d2ui.ColorTokenMatch)
tokenStrMatch := regexp.MustCompile(d2ui.ColorStrMatch)
empty := []byte("")
tokenPosition := 0
withoutTokens := string(tokenMatch.ReplaceAll([]byte(str), empty)) // remove tokens from string
matches := tokenStrMatch.FindAll([]byte(str), -1)
if len(matches) == 0 {
v.colors[0] = getColor(d2ui.ColorTokenWhite)
}
// we find the index of each token and update the color map.
// the key in the map is the starting index of each color token, the value is the color
for idx := range matches {
match := matches[idx]
matchToken := tokenMatch.Find(match)
matchStr := string(tokenMatch.ReplaceAll(match, empty))
token := d2ui.ColorToken(matchToken)
theColor := getColor(token)
if theColor == nil {
continue
}
if v.colors == nil {
v.colors = make(map[int]color.Color)
}
v.colors[tokenPosition] = theColor
tokenPosition += len(matchStr)
}
return withoutTokens
}
func (v *Label) GetAlignOffset(textWidth int) int {
switch v.Alignment {
case d2ui.HorizontalAlignLeft:
return 0
case d2ui.HorizontalAlignCenter:
return -textWidth / 2
case d2ui.HorizontalAlignRight:
return -textWidth
default:
return 0
}
}
func getColor(token d2ui.ColorToken) color.Color {
// https://github.com/OpenDiablo2/OpenDiablo2/issues/823
colors := map[d2ui.ColorToken]color.Color{
d2ui.ColorTokenGrey: d2util.Color(d2ui.ColorGrey100Alpha),
d2ui.ColorTokenWhite: d2util.Color(d2ui.ColorWhite100Alpha),
d2ui.ColorTokenBlue: d2util.Color(d2ui.ColorBlue100Alpha),
d2ui.ColorTokenYellow: d2util.Color(d2ui.ColorYellow100Alpha),
d2ui.ColorTokenGreen: d2util.Color(d2ui.ColorGreen100Alpha),
d2ui.ColorTokenGold: d2util.Color(d2ui.ColorGold100Alpha),
d2ui.ColorTokenOrange: d2util.Color(d2ui.ColorOrange100Alpha),
d2ui.ColorTokenRed: d2util.Color(d2ui.ColorRed100Alpha),
d2ui.ColorTokenBlack: d2util.Color(d2ui.ColorBlack100Alpha),
}
chosen := colors[token]
if chosen == nil {
return nil
}
return chosen
}