mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-06-11 18:20:42 +00:00
Fixed font rendering. Added basic button stuff.
This commit is contained in:
parent
f485f803c8
commit
b0de898fff
|
@ -5,9 +5,9 @@ import "github.com/hajimehoshi/ebiten"
|
||||||
// Drawable represents an instance that can be drawn
|
// Drawable represents an instance that can be drawn
|
||||||
type Drawable interface {
|
type Drawable interface {
|
||||||
Draw(target *ebiten.Image)
|
Draw(target *ebiten.Image)
|
||||||
GetSize() (uint32, uint32)
|
GetSize() (width, height uint32)
|
||||||
MoveTo(x, y int)
|
MoveTo(x, y int)
|
||||||
GetLocation() (int, int)
|
GetLocation() (x, y int)
|
||||||
GetVisible() bool
|
GetVisible() bool
|
||||||
SetVisible(bool)
|
SetVisible(visible bool)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
type Sprite struct {
|
type Sprite struct {
|
||||||
Directions uint32
|
Directions uint32
|
||||||
FramesPerDirection uint32
|
FramesPerDirection uint32
|
||||||
Frames []SpriteFrame
|
Frames []*SpriteFrame
|
||||||
X, Y int
|
X, Y int
|
||||||
Frame, Direction uint8
|
Frame, Direction uint8
|
||||||
Blend bool
|
Blend bool
|
||||||
|
@ -34,6 +34,7 @@ type SpriteFrame struct {
|
||||||
Length uint32
|
Length uint32
|
||||||
ImageData []int16
|
ImageData []int16
|
||||||
Image *ebiten.Image
|
Image *ebiten.Image
|
||||||
|
Loaded bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSprite creates an instance of a sprite
|
// CreateSprite creates an instance of a sprite
|
||||||
|
@ -57,10 +58,10 @@ func CreateSprite(data []byte, palette Palette) *Sprite {
|
||||||
framePointers[i] = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
framePointers[i] = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
||||||
dataPointer += 4
|
dataPointer += 4
|
||||||
}
|
}
|
||||||
result.Frames = make([]SpriteFrame, totalFrames)
|
result.Frames = make([]*SpriteFrame, totalFrames)
|
||||||
for i := uint32(0); i < totalFrames; i++ {
|
for i := uint32(0); i < totalFrames; i++ {
|
||||||
dataPointer = framePointers[i]
|
dataPointer = framePointers[i]
|
||||||
|
result.Frames[i] = &SpriteFrame{}
|
||||||
result.Frames[i].Flip = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
result.Frames[i].Flip = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
||||||
dataPointer += 4
|
dataPointer += 4
|
||||||
result.Frames[i].Width = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
result.Frames[i].Width = binary.LittleEndian.Uint32(data[dataPointer : dataPointer+4])
|
||||||
|
@ -120,6 +121,7 @@ func CreateSprite(data []byte, palette Palette) *Sprite {
|
||||||
newData[(ii*4)+3] = 0xFF
|
newData[(ii*4)+3] = 0xFF
|
||||||
}
|
}
|
||||||
result.Frames[ix].Image.ReplacePixels(newData)
|
result.Frames[ix].Image.ReplacePixels(newData)
|
||||||
|
result.Frames[ix].Loaded = true
|
||||||
}(i, dataPointer)
|
}(i, dataPointer)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -156,11 +158,16 @@ func (v *Sprite) Draw(target *ebiten.Image) {
|
||||||
float64((int32(v.Y) - int32(frame.Height) + frame.OffsetY)),
|
float64((int32(v.Y) - int32(frame.Height) + frame.OffsetY)),
|
||||||
)
|
)
|
||||||
if v.Blend {
|
if v.Blend {
|
||||||
opts.CompositeMode = ebiten.CompositeModeLighter
|
opts.CompositeMode = ebiten.CompositeModeSourceOver
|
||||||
|
} else {
|
||||||
|
opts.CompositeMode = ebiten.CompositeModeSourceOver
|
||||||
}
|
}
|
||||||
if v.ColorMod != nil {
|
if v.ColorMod != nil {
|
||||||
opts.ColorM = ColorToColorM(v.ColorMod)
|
opts.ColorM = ColorToColorM(v.ColorMod)
|
||||||
}
|
}
|
||||||
|
for frame.Image == nil {
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
target.DrawImage(frame.Image, opts)
|
target.DrawImage(frame.Image, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,10 +187,15 @@ func (v *Sprite) DrawSegments(target *ebiten.Image, xSegments, ySegments, offset
|
||||||
)
|
)
|
||||||
if v.Blend {
|
if v.Blend {
|
||||||
opts.CompositeMode = ebiten.CompositeModeLighter
|
opts.CompositeMode = ebiten.CompositeModeLighter
|
||||||
|
} else {
|
||||||
|
opts.CompositeMode = ebiten.CompositeModeSourceOver
|
||||||
}
|
}
|
||||||
if v.ColorMod != nil {
|
if v.ColorMod != nil {
|
||||||
opts.ColorM = ColorToColorM(v.ColorMod)
|
opts.ColorM = ColorToColorM(v.ColorMod)
|
||||||
}
|
}
|
||||||
|
for frame.Image == nil {
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
target.DrawImage(frame.Image, opts)
|
target.DrawImage(frame.Image, opts)
|
||||||
xOffset += int32(frame.Width)
|
xOffset += int32(frame.Width)
|
||||||
biggestYOffset = MaxInt32(biggestYOffset, int32(frame.Height))
|
biggestYOffset = MaxInt32(biggestYOffset, int32(frame.Height))
|
||||||
|
|
|
@ -104,8 +104,11 @@ func (v *Engine) mapMpqFiles() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mutex sync.Mutex
|
||||||
|
|
||||||
// LoadFile loads a file from the specified mpq and returns the data as a byte array
|
// LoadFile loads a file from the specified mpq and returns the data as a byte array
|
||||||
func (v *Engine) LoadFile(fileName string) []byte {
|
func (v *Engine) LoadFile(fileName string) []byte {
|
||||||
|
mutex.Lock()
|
||||||
// TODO: May want to cache some things if performance becomes an issue
|
// TODO: May want to cache some things if performance becomes an issue
|
||||||
mpqFile := v.Files[strings.ToLower(fileName)]
|
mpqFile := v.Files[strings.ToLower(fileName)]
|
||||||
mpq, err := MPQ.Load(mpqFile)
|
mpq, err := MPQ.Load(mpqFile)
|
||||||
|
@ -120,7 +123,7 @@ func (v *Engine) LoadFile(fileName string) []byte {
|
||||||
mpqStream := MPQ.CreateStream(mpq, blockTableEntry, fileName)
|
mpqStream := MPQ.CreateStream(mpq, blockTableEntry, fileName)
|
||||||
result := make([]byte, blockTableEntry.UncompressedFileSize)
|
result := make([]byte, blockTableEntry.UncompressedFileSize)
|
||||||
mpqStream.Read(result, 0, blockTableEntry.UncompressedFileSize)
|
mpqStream.Read(result, 0, blockTableEntry.UncompressedFileSize)
|
||||||
|
mutex.Unlock()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ type MainMenu struct {
|
||||||
diabloLogoRight *Common.Sprite
|
diabloLogoRight *Common.Sprite
|
||||||
diabloLogoLeftBack *Common.Sprite
|
diabloLogoLeftBack *Common.Sprite
|
||||||
diabloLogoRightBack *Common.Sprite
|
diabloLogoRightBack *Common.Sprite
|
||||||
|
exitDiabloButton *UI.Button
|
||||||
copyrightLabel *UI.Label
|
copyrightLabel *UI.Label
|
||||||
copyrightLabel2 *UI.Label
|
copyrightLabel2 *UI.Label
|
||||||
showTrademarkScreen bool
|
showTrademarkScreen bool
|
||||||
|
@ -48,14 +49,14 @@ func (v *MainMenu) Load() []func() {
|
||||||
v.copyrightLabel = UI.CreateLabel(v.fileProvider, ResourcePaths.FontFormal12, Palettes.Static)
|
v.copyrightLabel = UI.CreateLabel(v.fileProvider, ResourcePaths.FontFormal12, Palettes.Static)
|
||||||
v.copyrightLabel.Alignment = UI.LabelAlignCenter
|
v.copyrightLabel.Alignment = UI.LabelAlignCenter
|
||||||
v.copyrightLabel.SetText("Diablo 2 is © Copyright 2000-2016 Blizzard Entertainment")
|
v.copyrightLabel.SetText("Diablo 2 is © Copyright 2000-2016 Blizzard Entertainment")
|
||||||
v.copyrightLabel.ColorMod = color.RGBA{188, 168, 140, 255}
|
v.copyrightLabel.Color = color.RGBA{188, 168, 140, 255}
|
||||||
v.copyrightLabel.MoveTo(400, 500)
|
v.copyrightLabel.MoveTo(400, 500)
|
||||||
},
|
},
|
||||||
func() {
|
func() {
|
||||||
v.copyrightLabel2 = UI.CreateLabel(v.fileProvider, ResourcePaths.FontFormal12, Palettes.Static)
|
v.copyrightLabel2 = UI.CreateLabel(v.fileProvider, ResourcePaths.FontFormal12, Palettes.Static)
|
||||||
v.copyrightLabel2.Alignment = UI.LabelAlignCenter
|
v.copyrightLabel2.Alignment = UI.LabelAlignCenter
|
||||||
v.copyrightLabel2.SetText("All Rights Reserved.")
|
v.copyrightLabel2.SetText("All Rights Reserved.")
|
||||||
v.copyrightLabel2.ColorMod = color.RGBA{188, 168, 140, 255}
|
v.copyrightLabel2.Color = color.RGBA{188, 168, 140, 255}
|
||||||
v.copyrightLabel2.MoveTo(400, 525)
|
v.copyrightLabel2.MoveTo(400, 525)
|
||||||
},
|
},
|
||||||
func() {
|
func() {
|
||||||
|
@ -86,6 +87,12 @@ func (v *MainMenu) Load() []func() {
|
||||||
v.diabloLogoRightBack = v.fileProvider.LoadSprite(ResourcePaths.Diablo2LogoBlackRight, Palettes.Units)
|
v.diabloLogoRightBack = v.fileProvider.LoadSprite(ResourcePaths.Diablo2LogoBlackRight, Palettes.Units)
|
||||||
v.diabloLogoRightBack.MoveTo(400, 120)
|
v.diabloLogoRightBack.MoveTo(400, 120)
|
||||||
},
|
},
|
||||||
|
func() {
|
||||||
|
v.exitDiabloButton = UI.CreateButton(v.fileProvider, "EXIT DIABLO II")
|
||||||
|
v.exitDiabloButton.MoveTo(264, 535)
|
||||||
|
v.exitDiabloButton.SetVisible(false)
|
||||||
|
v.uiManager.AddWidget(v.exitDiabloButton)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +127,7 @@ func (v *MainMenu) Update() {
|
||||||
if v.uiManager.CursorButtonPressed(UI.CursorButtonLeft) {
|
if v.uiManager.CursorButtonPressed(UI.CursorButtonLeft) {
|
||||||
v.leftButtonHeld = true
|
v.leftButtonHeld = true
|
||||||
v.showTrademarkScreen = false
|
v.showTrademarkScreen = false
|
||||||
|
v.exitDiabloButton.SetVisible(true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
100
UI/Button.go
100
UI/Button.go
|
@ -1,8 +1,98 @@
|
||||||
package UI
|
package UI
|
||||||
|
|
||||||
// Button defines an object that acts like a button
|
import (
|
||||||
type Button interface {
|
"image/color"
|
||||||
Widget
|
|
||||||
isPressed() bool
|
"github.com/essial/OpenDiablo2/Common"
|
||||||
setPressed(bool)
|
"github.com/essial/OpenDiablo2/Palettes"
|
||||||
|
"github.com/essial/OpenDiablo2/ResourcePaths"
|
||||||
|
"github.com/hajimehoshi/ebiten"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Button defines a standard wide UI button
|
||||||
|
type Button struct {
|
||||||
|
enabled bool
|
||||||
|
x, y int
|
||||||
|
width, height uint32
|
||||||
|
visible bool
|
||||||
|
pressed bool
|
||||||
|
fileProvider Common.FileProvider
|
||||||
|
normalImage *ebiten.Image
|
||||||
|
pressedImage *ebiten.Image
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateButton creates an instance of Button
|
||||||
|
func CreateButton(fileProvider Common.FileProvider, text string) *Button {
|
||||||
|
result := &Button{
|
||||||
|
fileProvider: fileProvider,
|
||||||
|
width: 272,
|
||||||
|
height: 35,
|
||||||
|
visible: true,
|
||||||
|
enabled: true,
|
||||||
|
pressed: false,
|
||||||
|
}
|
||||||
|
font := GetFont(ResourcePaths.FontExocet10, Palettes.Units, fileProvider)
|
||||||
|
result.normalImage, _ = ebiten.NewImage(272, 35, ebiten.FilterNearest)
|
||||||
|
result.pressedImage, _ = ebiten.NewImage(272, 35, ebiten.FilterNearest)
|
||||||
|
textWidth, textHeight := font.GetTextMetrics(text)
|
||||||
|
textX := (272 / 2) - (textWidth / 2)
|
||||||
|
textY := (35 / 2) - (textHeight / 2) + 5
|
||||||
|
buttonSprite := fileProvider.LoadSprite(ResourcePaths.WideButtonBlank, Palettes.Units)
|
||||||
|
buttonSprite.MoveTo(0, 0)
|
||||||
|
buttonSprite.Blend = true
|
||||||
|
buttonSprite.DrawSegments(result.normalImage, 2, 1, 0)
|
||||||
|
font.Draw(int(textX), int(textY), text, color.RGBA{100, 100, 100, 255}, result.normalImage)
|
||||||
|
buttonSprite.DrawSegments(result.pressedImage, 2, 1, 1)
|
||||||
|
font.Draw(int(textX-2), int(textY+2), text, color.Black, result.pressedImage)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw renders the button
|
||||||
|
func (v *Button) Draw(target *ebiten.Image) {
|
||||||
|
opts := &ebiten.DrawImageOptions{
|
||||||
|
CompositeMode: ebiten.CompositeModeSourceAtop,
|
||||||
|
Filter: ebiten.FilterNearest,
|
||||||
|
}
|
||||||
|
opts.GeoM.Translate(float64(v.x), float64(v.y))
|
||||||
|
if v.pressed {
|
||||||
|
target.DrawImage(v.pressedImage, opts)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
target.DrawImage(v.normalImage, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEnabled returns the enabled state
|
||||||
|
func (v *Button) GetEnabled() bool {
|
||||||
|
return v.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEnabled sets the enabled state
|
||||||
|
func (v *Button) SetEnabled(enabled bool) {
|
||||||
|
v.enabled = enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSize returns the size of the button
|
||||||
|
func (v *Button) GetSize() (uint32, uint32) {
|
||||||
|
return v.width, v.height
|
||||||
|
}
|
||||||
|
|
||||||
|
// MoveTo moves the button
|
||||||
|
func (v *Button) MoveTo(x, y int) {
|
||||||
|
v.x = x
|
||||||
|
v.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLocation returns the location of the button
|
||||||
|
func (v *Button) GetLocation() (x, y int) {
|
||||||
|
return v.x, v.y
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVisible returns the visibility of the button
|
||||||
|
func (v *Button) GetVisible() bool {
|
||||||
|
return v.visible
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetVisible sets the visibility of the button
|
||||||
|
func (v *Button) SetVisible(visible bool) {
|
||||||
|
v.visible = visible
|
||||||
}
|
}
|
||||||
|
|
40
UI/Font.go
40
UI/Font.go
|
@ -1,8 +1,11 @@
|
||||||
package UI
|
package UI
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
"github.com/essial/OpenDiablo2/Common"
|
"github.com/essial/OpenDiablo2/Common"
|
||||||
"github.com/essial/OpenDiablo2/Palettes"
|
"github.com/essial/OpenDiablo2/Palettes"
|
||||||
|
"github.com/hajimehoshi/ebiten"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fontCache = map[string]*Font{}
|
var fontCache = map[string]*Font{}
|
||||||
|
@ -15,8 +18,8 @@ type FontSize struct {
|
||||||
|
|
||||||
// Font represents a font
|
// Font represents a font
|
||||||
type Font struct {
|
type Font struct {
|
||||||
FontSprite *Common.Sprite
|
fontSprite *Common.Sprite
|
||||||
Metrics map[uint8]FontSize
|
metrics map[uint8]FontSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFont creates or loads an existing font
|
// GetFont creates or loads an existing font
|
||||||
|
@ -33,9 +36,9 @@ func GetFont(font string, palette Palettes.Palette, fileProvider Common.FileProv
|
||||||
// CreateFont creates an instance of a MPQ Font
|
// CreateFont creates an instance of a MPQ Font
|
||||||
func CreateFont(font string, palette Palettes.Palette, fileProvider Common.FileProvider) *Font {
|
func CreateFont(font string, palette Palettes.Palette, fileProvider Common.FileProvider) *Font {
|
||||||
result := &Font{
|
result := &Font{
|
||||||
Metrics: make(map[uint8]FontSize),
|
metrics: make(map[uint8]FontSize),
|
||||||
}
|
}
|
||||||
result.FontSprite = fileProvider.LoadSprite(font+".dc6", palette)
|
result.fontSprite = fileProvider.LoadSprite(font+".dc6", palette)
|
||||||
woo := "Woo!\x01"
|
woo := "Woo!\x01"
|
||||||
fontData := fileProvider.LoadFile(font + ".tbl")
|
fontData := fileProvider.LoadFile(font + ".tbl")
|
||||||
if string(fontData[0:5]) != woo {
|
if string(fontData[0:5]) != woo {
|
||||||
|
@ -46,7 +49,34 @@ func CreateFont(font string, palette Palettes.Palette, fileProvider Common.FileP
|
||||||
Width: fontData[i+3],
|
Width: fontData[i+3],
|
||||||
Height: fontData[i+4],
|
Height: fontData[i+4],
|
||||||
}
|
}
|
||||||
result.Metrics[fontData[i+8]] = fontSize
|
result.metrics[fontData[i+8]] = fontSize
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTextMetrics returns the size of the specified text
|
||||||
|
func (v *Font) GetTextMetrics(text string) (width, height uint32) {
|
||||||
|
width = uint32(0)
|
||||||
|
height = uint32(0)
|
||||||
|
for _, ch := range text {
|
||||||
|
metric := v.metrics[uint8(ch)]
|
||||||
|
width += uint32(metric.Width)
|
||||||
|
height = Common.Max(height, uint32(metric.Height))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw draws the font on the target surface
|
||||||
|
func (v *Font) Draw(x, y int, text string, color color.Color, target *ebiten.Image) {
|
||||||
|
v.fontSprite.ColorMod = color
|
||||||
|
v.fontSprite.Blend = true
|
||||||
|
_, height := v.GetTextMetrics(text)
|
||||||
|
for _, ch := range text {
|
||||||
|
char := uint8(ch)
|
||||||
|
metric := v.metrics[char]
|
||||||
|
v.fontSprite.Frame = char
|
||||||
|
v.fontSprite.MoveTo(x, y+int(height))
|
||||||
|
v.fontSprite.Draw(target)
|
||||||
|
x += int(metric.Width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ const (
|
||||||
|
|
||||||
// Manager represents the UI manager
|
// Manager represents the UI manager
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
widgets []*Widget
|
widgets []Widget
|
||||||
cursorSprite *Common.Sprite
|
cursorSprite *Common.Sprite
|
||||||
cursorButtons CursorButton
|
cursorButtons CursorButton
|
||||||
CursorX int
|
CursorX int
|
||||||
|
@ -29,7 +29,7 @@ type Manager struct {
|
||||||
// CreateManager creates a new instance of a UI manager
|
// CreateManager creates a new instance of a UI manager
|
||||||
func CreateManager(provider Common.FileProvider) *Manager {
|
func CreateManager(provider Common.FileProvider) *Manager {
|
||||||
result := &Manager{
|
result := &Manager{
|
||||||
widgets: make([]*Widget, 0),
|
widgets: make([]Widget, 0),
|
||||||
cursorSprite: provider.LoadSprite(ResourcePaths.CursorDefault, Palettes.Units),
|
cursorSprite: provider.LoadSprite(ResourcePaths.CursorDefault, Palettes.Units),
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -37,16 +37,23 @@ func CreateManager(provider Common.FileProvider) *Manager {
|
||||||
|
|
||||||
// Reset resets the state of the UI manager. Typically called for new scenes
|
// Reset resets the state of the UI manager. Typically called for new scenes
|
||||||
func (v *Manager) Reset() {
|
func (v *Manager) Reset() {
|
||||||
v.widgets = make([]*Widget, 0)
|
v.widgets = make([]Widget, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddWidget adds a widget to the UI manager
|
// AddWidget adds a widget to the UI manager
|
||||||
func (v *Manager) AddWidget(widget *Widget) {
|
func (v *Manager) AddWidget(widget Widget) {
|
||||||
v.widgets = append(v.widgets, widget)
|
v.widgets = append(v.widgets, widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw renders all of the UI elements
|
// Draw renders all of the UI elements
|
||||||
func (v *Manager) Draw(screen *ebiten.Image) {
|
func (v *Manager) Draw(screen *ebiten.Image) {
|
||||||
|
for _, widget := range v.widgets {
|
||||||
|
if !widget.GetVisible() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
widget.Draw(screen)
|
||||||
|
}
|
||||||
|
|
||||||
cx, cy := ebiten.CursorPosition()
|
cx, cy := ebiten.CursorPosition()
|
||||||
v.cursorSprite.MoveTo(cx, cy)
|
v.cursorSprite.MoveTo(cx, cy)
|
||||||
v.cursorSprite.Draw(screen)
|
v.cursorSprite.Draw(screen)
|
||||||
|
|
|
@ -30,14 +30,14 @@ type Label struct {
|
||||||
Alignment LabelAlignment
|
Alignment LabelAlignment
|
||||||
font *Font
|
font *Font
|
||||||
imageData *ebiten.Image
|
imageData *ebiten.Image
|
||||||
ColorMod color.Color
|
Color color.Color
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateLabel creates a new instance of a UI label
|
// CreateLabel creates a new instance of a UI label
|
||||||
func CreateLabel(provider Common.FileProvider, font string, palette Palettes.Palette) *Label {
|
func CreateLabel(provider Common.FileProvider, font string, palette Palettes.Palette) *Label {
|
||||||
result := &Label{
|
result := &Label{
|
||||||
Alignment: LabelAlignLeft,
|
Alignment: LabelAlignLeft,
|
||||||
ColorMod: nil,
|
Color: color.White,
|
||||||
font: GetFont(font, palette, provider),
|
font: GetFont(font, palette, provider),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,17 +64,6 @@ func (v *Label) Draw(target *ebiten.Image) {
|
||||||
target.DrawImage(v.imageData, opts)
|
target.DrawImage(v.imageData, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *Label) calculateSize() (uint32, uint32) {
|
|
||||||
width := uint32(0)
|
|
||||||
height := uint32(0)
|
|
||||||
for _, ch := range v.text {
|
|
||||||
metric := v.font.Metrics[uint8(ch)]
|
|
||||||
width += uint32(metric.Width)
|
|
||||||
height = Common.Max(height, uint32(metric.Height))
|
|
||||||
}
|
|
||||||
return width, height
|
|
||||||
}
|
|
||||||
|
|
||||||
// MoveTo moves the label to the specified location
|
// MoveTo moves the label to the specified location
|
||||||
func (v *Label) MoveTo(x, y int) {
|
func (v *Label) MoveTo(x, y int) {
|
||||||
v.X = x
|
v.X = x
|
||||||
|
@ -85,20 +74,11 @@ func (v *Label) cacheImage() {
|
||||||
if v.imageData != nil {
|
if v.imageData != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
width, height := v.calculateSize()
|
width, height := v.font.GetTextMetrics(v.text)
|
||||||
v.Width = width
|
v.Width = width
|
||||||
v.Height = height
|
v.Height = height
|
||||||
v.imageData, _ = ebiten.NewImage(int(width), int(height), ebiten.FilterNearest)
|
v.imageData, _ = ebiten.NewImage(int(width), int(height), ebiten.FilterNearest)
|
||||||
x := uint32(0)
|
v.font.Draw(0, 0, v.text, v.Color, v.imageData)
|
||||||
v.font.FontSprite.ColorMod = v.ColorMod
|
|
||||||
for _, ch := range v.text {
|
|
||||||
char := uint8(ch)
|
|
||||||
metric := v.font.Metrics[char]
|
|
||||||
v.font.FontSprite.Frame = char
|
|
||||||
v.font.FontSprite.MoveTo(int(x), int(height))
|
|
||||||
v.font.FontSprite.Draw(v.imageData)
|
|
||||||
x += uint32(metric.Width)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetText sets the label's text
|
// SetText sets the label's text
|
||||||
|
|
|
@ -7,6 +7,6 @@ import (
|
||||||
// Widget defines an object that is a UI widget
|
// Widget defines an object that is a UI widget
|
||||||
type Widget interface {
|
type Widget interface {
|
||||||
Common.Drawable
|
Common.Drawable
|
||||||
getEnabled() bool
|
GetEnabled() bool
|
||||||
setEnabled(bool)
|
SetEnabled(enabled bool)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user