1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-07-01 11:25:26 +00:00

Continued work on GUI (#316)

* Configuration cleanup

* Cleanup

* Continued UI work
This commit is contained in:
Alex Yatskov 2020-02-24 19:35:21 -08:00 committed by GitHub
parent 2285c31b53
commit 6f2c212417
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 668 additions and 192 deletions

View File

@ -60,6 +60,10 @@ func loadFont(tablePath, spritePath, palettePath string) (*Font, error) {
return font, nil
}
func (f *Font) SetColor(color color.Color) {
f.color = color
}
func (f *Font) GetTextMetrics(text string) (int, int) {
var (
lineWidth int

131
d2core/d2gui/button.go Normal file
View File

@ -0,0 +1,131 @@
package d2gui
import (
"errors"
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type buttonState int
const (
buttonStateDefault buttonState = iota
buttonStatePressed
buttonStateToggled
buttonStatePressedToggled
)
type Button struct {
widgetBase
width int
height int
state buttonState
surfaces []d2render.Surface
}
func createButton(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([]d2render.Surface, surfaceCount)
for i := 0; i < surfaceCount; i++ {
surface, err := d2render.NewSurface(buttonWidth, buttonHeight, d2render.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
break
}
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 d2input.MouseEvent) bool {
b.state = buttonStatePressed
return false
}
func (b *Button) onMouseButtonUp(event d2input.MouseEvent) bool {
b.state = buttonStateDefault
return false
}
func (b *Button) onMouseLeave(event d2input.MouseMoveEvent) bool {
b.state = buttonStateDefault
return false
}
func (b *Button) render(target d2render.Surface) error {
return target.Render(b.surfaces[b.state])
}
func (b *Button) getSize() (int, int) {
return b.width, b.height
}

46
d2core/d2gui/common.go Normal file
View File

@ -0,0 +1,46 @@
package d2gui
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
func loadFont(fontStyle FontStyle) (*d2asset.Font, error) {
config, ok := fontStyleConfigs[fontStyle]
if !ok {
return nil, errors.New("invalid font style")
}
return d2asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
}
func renderSegmented(animation *d2asset.Animation, segmentsX, segmentsY, frameOffset int, target d2render.Surface) error {
var currentY int
for y := 0; y < segmentsY; y++ {
var currentX int
var maxHeight int
for x := 0; x < segmentsX; x++ {
if err := animation.SetCurrentFrame(x + y*segmentsX + frameOffset*segmentsX*segmentsY); err != nil {
return err
}
target.PushTranslation(x+currentX, y+currentY)
err := animation.Render(target)
target.Pop()
if err != nil {
return err
}
width, height := animation.GetCurrentFrameSize()
maxHeight = d2common.MaxInt(maxHeight, height)
currentX += width
}
currentY += maxHeight
}
return nil
}

View File

@ -34,21 +34,14 @@ func Advance(elapsed float64) error {
return singleton.advance(elapsed)
}
func AddLayout() *Layout {
return singleton.addLayout()
}
func AddSprite(imagePath, palettePath string) *Sprite {
return singleton.addSprite(imagePath, palettePath)
}
func AddLabel(text string, fontStyle FontStyle) *Label {
return singleton.addLabel(text, fontStyle)
}
func Clear() {
func CreateLayout(positionType PositionType) *Layout {
verifyWasInit()
singleton.clear()
return createLayout(positionType)
}
func SetLayout(layout *Layout) {
verifyWasInit()
singleton.SetLayout(layout)
}
func ShowLoadScreen(progress float64) {

View File

@ -1,60 +1,41 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type Label struct {
widgetBase
text string
font *d2asset.Font
surface d2render.Surface
}
func createLabel(text string, fontStyle FontStyle) *Label {
font, _ := loadFont(fontStyle)
label := &Label{font: font}
label.SetText(text)
label.visible = true
return label
}
func createLabel(text string, fontStyle FontStyle) (*Label, error) {
font, err := loadFont(fontStyle)
if err != nil {
return nil, err
}
func (l *Label) SetText(text string) *Label {
l.text = text
l.cache()
return l
width, height := font.GetTextMetrics(text)
surface, err := d2render.NewSurface(width, height, d2render.FilterNearest)
if err != nil {
return nil, err
}
if err := font.RenderText(text, surface); err != nil {
return nil, err
}
label := &Label{surface: surface}
label.SetVisible(true)
return label, nil
}
func (l *Label) render(target d2render.Surface) error {
if l.surface == nil {
return nil
}
return target.Render(l.surface)
}
func (l *Label) cache() error {
l.surface = nil
if l.font == nil {
return nil
}
width, height := l.font.GetTextMetrics(l.text)
var err error
if l.surface, err = d2render.NewSurface(width, height, d2render.FilterNearest); err != nil {
return err
}
return l.font.RenderText(l.text, l.surface)
}
func (l *Label) getSize() (int, int) {
if l.surface == nil {
return 0, 0
}
return l.surface.GetSize()
}

View File

@ -3,6 +3,7 @@ package d2gui
import (
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
@ -10,26 +11,136 @@ import (
type layoutEntry struct {
widget widget
x int
y int
width int
height int
mouseOver bool
mouseDown [3]bool
}
type VerticalAlign int
const (
VerticalAlignTop VerticalAlign = iota
VerticalAlignMiddle
VerticalAlignBottom
)
type HorizontalAlign int
const (
HorizontalAlignLeft HorizontalAlign = iota
HorizontalAlignCenter
HorizontalAlignRight
)
type PositionType int
const (
PositionTypeAbsolute PositionType = iota
PositionTypeVertical
PositionTypeHorizontal
)
type Layout struct {
widgetBase
entries []*layoutEntry
width int
height int
verticalAlign VerticalAlign
horizontalAlign HorizontalAlign
positionType PositionType
entries []*layoutEntry
}
func createLayout() *Layout {
layout := new(Layout)
layout.visible = true
func createLayout(positionType PositionType) *Layout {
layout := &Layout{positionType: positionType}
layout.SetVisible(true)
return layout
}
func (l *Layout) SetSize(width, height int) {
l.width = width
l.height = height
}
func (l *Layout) SetVerticalAlign(verticalAlign VerticalAlign) {
l.verticalAlign = verticalAlign
}
func (l *Layout) SetHorizontalAlign(horizontalAlign HorizontalAlign) {
l.horizontalAlign = horizontalAlign
}
func (l *Layout) AddLayout(positionType PositionType) *Layout {
layout := createLayout(positionType)
l.entries = append(l.entries, &layoutEntry{widget: layout})
return layout
}
func (l *Layout) AddSpacerStatic(width, height int) *SpacerStatic {
spacer := createSpacerStatic(width, height)
l.entries = append(l.entries, &layoutEntry{widget: spacer})
return spacer
}
func (l *Layout) AddSpacerDynamic() *SpacerDynamic {
spacer := createSpacerDynamic()
l.entries = append(l.entries, &layoutEntry{widget: spacer})
return spacer
}
func (l *Layout) AddSprite(imagePath, palettePath string) (*Sprite, error) {
sprite, err := createSprite(imagePath, palettePath)
if err != nil {
return nil, err
}
l.entries = append(l.entries, &layoutEntry{widget: sprite})
return sprite, nil
}
func (l *Layout) AddLabel(text string, fontStyle FontStyle) (*Label, error) {
label, err := createLabel(text, fontStyle)
if err != nil {
return nil, err
}
l.entries = append(l.entries, &layoutEntry{widget: label})
return label, nil
}
func (l *Layout) AddButton(text string, buttonStyle ButtonStyle) (*Button, error) {
button, err := createButton(text, buttonStyle)
if err != nil {
return nil, err
}
l.entries = append(l.entries, &layoutEntry{widget: button})
return button, nil
}
func (l *Layout) Clear() {
l.entries = nil
}
func (l *Layout) render(target d2render.Surface) error {
l.adjustEntryPlacement()
for _, entry := range l.entries {
if entry.widget.isVisible() {
l.renderWidget(entry.widget, target)
l.renderWidgetDebug(entry.widget, target)
if !entry.widget.isVisible() {
continue
}
if err := l.renderEntry(entry, target); err != nil {
return err
}
if err := l.renderEntryDebug(entry, target); err != nil {
return err
}
}
@ -38,51 +149,88 @@ func (l *Layout) render(target d2render.Surface) error {
func (l *Layout) advance(elapsed float64) error {
for _, entry := range l.entries {
if entry.widget.isVisible() {
if err := entry.widget.advance(elapsed); err != nil {
return err
}
if err := entry.widget.advance(elapsed); err != nil {
return err
}
}
return nil
}
func (l *Layout) renderWidget(widget widget, target d2render.Surface) {
target.PushTranslation(widget.getPosition())
func (l *Layout) renderEntry(entry *layoutEntry, target d2render.Surface) error {
target.PushTranslation(entry.x, entry.y)
defer target.Pop()
widget.render(target)
return entry.widget.render(target)
}
func (l *Layout) renderWidgetDebug(widget widget, target d2render.Surface) {
target.PushTranslation(widget.getPosition())
func (l *Layout) renderEntryDebug(entry *layoutEntry, target d2render.Surface) error {
target.PushTranslation(entry.x, entry.y)
defer target.Pop()
drawColor := color.RGBA{R: 0x00, G: 0x00, B: 0xff, A: 0xb0}
drawColor := color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}
switch entry.widget.(type) {
case *Layout:
drawColor = color.RGBA{R: 0xff, G: 0x00, B: 0xff, A: 0xff}
case *SpacerStatic, *SpacerDynamic:
drawColor = color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xff}
case *Label:
drawColor = color.RGBA{R: 0x00, G: 0x00, B: 0xff, A: 0xff}
case *Button:
drawColor = color.RGBA{R: 0xff, G: 0xff, B: 0x00, A: 0xff}
}
width, height := widget.getSize()
target.DrawLine(width, 0, drawColor)
target.DrawLine(0, height, drawColor)
target.DrawLine(entry.width, 0, drawColor)
target.DrawLine(0, entry.height, drawColor)
target.PushTranslation(width, 0)
target.DrawLine(0, height, drawColor)
target.PushTranslation(entry.width, 0)
target.DrawLine(0, entry.height, drawColor)
target.Pop()
target.PushTranslation(0, height)
target.DrawLine(width, 0, drawColor)
target.PushTranslation(0, entry.height)
target.DrawLine(entry.width, 0, drawColor)
target.Pop()
return nil
}
func (l *Layout) getContentSize() (int, int) {
var width, height int
for _, entry := range l.entries {
x, y := entry.widget.getPosition()
w, h := entry.widget.getSize()
switch l.positionType {
case PositionTypeVertical:
width = d2common.MaxInt(width, w)
height += h
break
case PositionTypeHorizontal:
width += w
height = d2common.MaxInt(height, h)
break
case PositionTypeAbsolute:
width = d2common.MaxInt(width, x+w)
height = d2common.MaxInt(height, y+h)
break
}
}
return width, height
}
func (l *Layout) getSize() (int, int) {
return 0, 0
width, height := l.getContentSize()
return d2common.MaxInt(width, l.width), d2common.MaxInt(height, l.height)
}
func (l *Layout) onMouseButtonDown(event d2input.MouseEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEventCoords(entry.widget, &eventLocal.X, &eventLocal.Y) {
if l.adjustEntryEvent(entry, &eventLocal.X, &eventLocal.Y) {
entry.widget.onMouseButtonDown(eventLocal)
entry.mouseDown[event.Button] = true
}
}
@ -94,9 +242,10 @@ func (l *Layout) onMouseButtonUp(event d2input.MouseEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEventCoords(entry.widget, &eventLocal.X, &eventLocal.Y) {
if l.adjustEntryEvent(entry, &eventLocal.X, &eventLocal.Y) {
if entry.mouseDown[event.Button] {
entry.widget.onMouseClick(eventLocal)
entry.widget.onMouseButtonClick(eventLocal)
entry.widget.onMouseButtonUp(eventLocal)
}
}
@ -110,7 +259,8 @@ func (l *Layout) onMouseMove(event d2input.MouseMoveEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEventCoords(entry.widget, &eventLocal.X, &eventLocal.Y) {
if l.adjustEntryEvent(entry, &eventLocal.X, &eventLocal.Y) {
entry.widget.onMouseMove(eventLocal)
if entry.mouseOver {
entry.widget.onMouseOver(eventLocal)
} else {
@ -126,38 +276,90 @@ func (l *Layout) onMouseMove(event d2input.MouseMoveEvent) bool {
return false
}
func (l *Layout) adjustEventCoords(widget widget, eventX, eventY *int) bool {
x, y := widget.getPosition()
width, height := widget.getSize()
func (l *Layout) adjustEntryEvent(entry *layoutEntry, eventX, eventY *int) bool {
*eventX -= entry.x
*eventY -= entry.y
*eventX -= x
*eventY -= y
if *eventX < 0 || *eventY < 0 || *eventX >= width || *eventY >= height {
if *eventX < 0 || *eventY < 0 || *eventX >= entry.width || *eventY >= entry.height {
return false
}
return true
}
func (l *Layout) addLayout() *Layout {
layout := createLayout()
l.entries = append(l.entries, &layoutEntry{widget: layout})
return layout
}
func (l *Layout) adjustEntryPlacement() {
width, height := l.getSize()
func (l *Layout) addSprite(imagePath, palettePath string) *Sprite {
sprite := createSprite(imagePath, palettePath)
l.entries = append(l.entries, &layoutEntry{widget: sprite})
return sprite
}
var expanderCount int
for _, entry := range l.entries {
if entry.widget.isVisible() && entry.widget.isExpanding() {
expanderCount++
}
}
func (l *Layout) addLabel(text string, fontStyle FontStyle) *Label {
label := createLabel(text, fontStyle)
l.entries = append(l.entries, &layoutEntry{widget: label})
return label
}
var expanderWidth, expanderHeight int
if expanderCount > 0 {
contentWidth, contentHeight := l.getContentSize()
func (l *Layout) clear() {
l.entries = nil
switch l.positionType {
case PositionTypeVertical:
expanderHeight = (height - contentHeight) / expanderCount
break
case PositionTypeHorizontal:
expanderWidth = (width - contentWidth) / expanderCount
break
}
expanderWidth = d2common.MaxInt(0, expanderWidth)
expanderHeight = d2common.MaxInt(0, expanderHeight)
}
var offsetX, offsetY int
for _, entry := range l.entries {
if !entry.widget.isVisible() {
continue
}
if entry.widget.isExpanding() {
entry.width, entry.height = expanderWidth, expanderHeight
} else {
entry.width, entry.height = entry.widget.getSize()
}
switch l.positionType {
case PositionTypeVertical:
entry.y = offsetY
offsetY += entry.height
switch l.horizontalAlign {
case HorizontalAlignLeft:
entry.x = 0
break
case HorizontalAlignCenter:
entry.x = width/2 - entry.width/2
break
case HorizontalAlignRight:
entry.x = width - entry.width
break
}
break
case PositionTypeHorizontal:
entry.x = offsetX
offsetX += entry.width
switch l.verticalAlign {
case VerticalAlignTop:
entry.y = 0
break
case VerticalAlignMiddle:
entry.y = height/2 - entry.height/2
break
case VerticalAlignBottom:
entry.y = height - entry.height
break
}
break
case PositionTypeAbsolute:
entry.x, entry.y = entry.widget.getPosition()
break
}
}
}

View File

@ -11,7 +11,7 @@ import (
)
type manager struct {
Layout
layout *Layout
cursorAnim *d2asset.Animation
cursorX int
@ -46,19 +46,35 @@ func createGuiManager() (*manager, error) {
return manager, nil
}
func (m *manager) SetLayout(layout *Layout) {
m.layout = layout
}
func (m *manager) OnMouseButtonDown(event d2input.MouseEvent) bool {
return m.Layout.onMouseButtonDown(event)
if m.layout == nil {
return false
}
return m.layout.onMouseButtonDown(event)
}
func (m *manager) OnMouseButtonUp(event d2input.MouseEvent) bool {
return m.Layout.onMouseButtonUp(event)
if m.layout == nil {
return false
}
return m.layout.onMouseButtonUp(event)
}
func (m *manager) OnMouseMove(event d2input.MouseMoveEvent) bool {
m.cursorX = event.X
m.cursorY = event.Y
return m.Layout.onMouseMove(event)
if m.layout == nil {
return false
}
return m.layout.onMouseMove(event)
}
func (m *manager) render(target d2render.Surface) error {
@ -66,8 +82,9 @@ func (m *manager) render(target d2render.Surface) error {
if err := m.renderLoadScreen(target); err != nil {
return err
}
} else {
if err := m.Layout.render(target); err != nil {
} else if m.layout != nil {
m.layout.SetSize(target.GetSize())
if err := m.layout.render(target); err != nil {
return err
}
}
@ -103,8 +120,8 @@ func (m *manager) renderCursor(target d2render.Surface) error {
}
func (m *manager) advance(elapsed float64) error {
if !m.loading {
if err := m.Layout.advance(elapsed); err != nil {
if !m.loading && m.layout != nil {
if err := m.layout.advance(elapsed); err != nil {
return err
}
}
@ -136,6 +153,6 @@ func (m *manager) hideCursor() {
}
func (m *manager) clear() {
m.Layout.clear()
m.SetLayout(nil)
m.hideLoadScreen()
}

31
d2core/d2gui/spacer.go Normal file
View File

@ -0,0 +1,31 @@
package d2gui
type SpacerStatic struct {
widgetBase
width int
height int
}
func createSpacerStatic(width, height int) *SpacerStatic {
spacer := &SpacerStatic{width: width, height: height}
spacer.SetVisible(true)
return spacer
}
func (s *SpacerStatic) getSize() (int, int) {
return s.width, s.height
}
type SpacerDynamic struct {
widgetBase
}
func createSpacerDynamic() *SpacerDynamic {
spacer := &SpacerDynamic{}
spacer.SetVisible(true)
spacer.SetExpanding(true)
return spacer
}

View File

@ -1,7 +1,6 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
@ -16,11 +15,17 @@ type Sprite struct {
animation *d2asset.Animation
}
func createSprite(imagePath, palettePath string) *Sprite {
sprite := new(Sprite)
sprite.animation, _ = d2asset.LoadAnimation(imagePath, palettePath)
sprite.visible = true
return sprite
func createSprite(imagePath, palettePath string) (*Sprite, error) {
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
if err != nil {
return nil, err
}
sprite := &Sprite{}
sprite.animation = animation
sprite.SetVisible(true)
return sprite, nil
}
func (s *Sprite) SetSegmented(segmentsX, segmentsY, frameOffset int) {
@ -30,57 +35,13 @@ func (s *Sprite) SetSegmented(segmentsX, segmentsY, frameOffset int) {
}
func (s *Sprite) render(target d2render.Surface) error {
if s.animation == nil {
return nil
}
_, height := s.animation.GetCurrentFrameSize()
target.PushTranslation(0, -height)
defer target.Pop()
if s.segmentsX == 0 && s.segmentsY == 0 {
return s.animation.Render(target)
}
var currentY int
for y := 0; y < s.segmentsY; y++ {
var currentX int
var maxHeight int
for x := 0; x < s.segmentsX; x++ {
if err := s.animation.SetCurrentFrame(x + y*s.segmentsX + s.frameOffset*s.segmentsX*s.segmentsY); err != nil {
return err
}
target.PushTranslation(s.x+currentX, s.y+currentY)
err := s.animation.Render(target)
target.Pop()
if err != nil {
return err
}
width, height := s.animation.GetCurrentFrameSize()
maxHeight = d2common.MaxInt(maxHeight, height)
currentX += width
}
currentY += maxHeight
}
return nil
return renderSegmented(s.animation, s.segmentsX, s.segmentsY, s.frameOffset, target)
}
func (s *Sprite) advance(elapsed float64) error {
if s.animation == nil {
return nil
}
return s.animation.Advance(elapsed)
}
func (s *Sprite) getSize() (int, int) {
if s.animation == nil {
return 0, 0
}
return s.animation.GetCurrentFrameSize()
}

View File

@ -2,7 +2,6 @@ package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
type FontStyle int
@ -11,9 +10,11 @@ const (
FontStyle16Units FontStyle = iota
FontStyle30Units
FontStyle42Units
FontStyleExocet10
FontStyleFormal10Static
FontStyleFormal11Units
FontStyleFormal12Static
FontStyleRediculous
)
type fontStyleConfig struct {
@ -25,12 +26,37 @@ var fontStyleConfigs = map[FontStyle]fontStyleConfig{
FontStyle16Units: {d2resource.Font16, d2resource.PaletteUnits},
FontStyle30Units: {d2resource.Font30, d2resource.PaletteUnits},
FontStyle42Units: {d2resource.Font42, d2resource.PaletteUnits},
FontStyleExocet10: {d2resource.FontExocet10, d2resource.PaletteUnits},
FontStyleFormal10Static: {d2resource.FontFormal10, d2resource.PaletteStatic},
FontStyleFormal11Units: {d2resource.FontFormal11, d2resource.PaletteUnits},
FontStyleFormal12Static: {d2resource.FontFormal12, d2resource.PaletteStatic},
FontStyleRediculous: {d2resource.FontRediculous, d2resource.PaletteUnits},
}
func loadFont(fontStyle FontStyle) (*d2asset.Font, error) {
config := fontStyleConfigs[fontStyle]
return d2asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
type ButtonStyle int
type buttonStyleConfig struct {
segmentsX int
segmentsY int
animationPath string
palettePath string
fontStyle FontStyle
textOffset int
}
const (
ButtonStyleMedium ButtonStyle = iota
ButtonStyleNarrow
ButtonStyleOkCancel
ButtonStyleShort
ButtonStyleTall
ButtonStyleWide
)
var buttonStyleConfigs = map[ButtonStyle]buttonStyleConfig{
ButtonStyleMedium: {1, 1, d2resource.MediumButtonBlank, d2resource.PaletteUnits, FontStyleExocet10, 0},
ButtonStyleOkCancel: {1, 1, d2resource.CancelButton, d2resource.PaletteUnits, FontStyleRediculous, 0},
ButtonStyleShort: {1, 1, d2resource.ShortButtonBlank, d2resource.PaletteUnits, FontStyleRediculous, -1},
ButtonStyleTall: {1, 1, d2resource.TallButtonBlank, d2resource.PaletteUnits, FontStyleExocet10, 5},
ButtonStyleWide: {2, 1, d2resource.WideButtonBlank, d2resource.PaletteUnits, FontStyleExocet10, 1},
}

View File

@ -12,26 +12,30 @@ type widget interface {
render(target d2render.Surface) error
advance(elapsed float64) error
onMouseEnter(event d2input.MouseMoveEvent)
onMouseLeave(event d2input.MouseMoveEvent)
onMouseOver(event d2input.MouseMoveEvent)
onMouseClick(event d2input.MouseEvent)
onMouseMove(event d2input.MouseMoveEvent) bool
onMouseEnter(event d2input.MouseMoveEvent) bool
onMouseLeave(event d2input.MouseMoveEvent) bool
onMouseOver(event d2input.MouseMoveEvent) bool
onMouseButtonDown(event d2input.MouseEvent) bool
onMouseButtonUp(event d2input.MouseEvent) bool
onMouseButtonClick(event d2input.MouseEvent) bool
getPosition() (int, int)
getSize() (int, int)
getLayer() int
isVisible() bool
isExpanding() bool
}
type widgetBase struct {
x int
y int
layer int
visible bool
x int
y int
layer int
visible bool
expanding bool
mouseEnterHandler MouseMoveHandler
mouseLeaveHandler MouseMoveHandler
mouseMoveHandler MouseMoveHandler
mouseClickHandler MouseHandler
}
@ -48,6 +52,10 @@ func (w *widgetBase) SetVisible(visible bool) {
w.visible = visible
}
func (w *widgetBase) SetExpanding(expanding bool) {
w.expanding = expanding
}
func (w *widgetBase) SetMouseEnterHandler(handler MouseMoveHandler) {
w.mouseEnterHandler = handler
}
@ -56,10 +64,6 @@ func (w *widgetBase) SetMouseLeaveHandler(handler MouseMoveHandler) {
w.mouseLeaveHandler = handler
}
func (w *widgetBase) SetMouseMoveHandler(handler MouseMoveHandler) {
w.mouseMoveHandler = handler
}
func (w *widgetBase) SetMouseClickHandler(handler MouseHandler) {
w.mouseClickHandler = handler
}
@ -68,6 +72,10 @@ func (w *widgetBase) getPosition() (int, int) {
return w.x, w.y
}
func (w *widgetBase) getSize() (int, int) {
return 0, 0
}
func (w *widgetBase) getLayer() int {
return w.layer
}
@ -76,30 +84,54 @@ func (w *widgetBase) isVisible() bool {
return w.visible
}
func (w *widgetBase) isExpanding() bool {
return w.expanding
}
func (w *widgetBase) render(target d2render.Surface) error {
return nil
}
func (w *widgetBase) advance(elapsed float64) error {
return nil
}
func (w *widgetBase) onMouseEnter(event d2input.MouseMoveEvent) {
func (w *widgetBase) onMouseEnter(event d2input.MouseMoveEvent) bool {
if w.mouseEnterHandler != nil {
w.mouseEnterHandler(event)
}
return false
}
func (w *widgetBase) onMouseLeave(event d2input.MouseMoveEvent) {
func (w *widgetBase) onMouseLeave(event d2input.MouseMoveEvent) bool {
if w.mouseLeaveHandler != nil {
w.mouseLeaveHandler(event)
}
return false
}
func (w *widgetBase) onMouseOver(event d2input.MouseMoveEvent) {
if w.mouseMoveHandler != nil {
w.mouseMoveHandler(event)
}
}
func (w *widgetBase) onMouseClick(event d2input.MouseEvent) {
func (w *widgetBase) onMouseButtonClick(event d2input.MouseEvent) bool {
if w.mouseClickHandler != nil {
w.mouseClickHandler(event)
}
return false
}
func (w *widgetBase) onMouseMove(event d2input.MouseMoveEvent) bool {
return false
}
func (w *widgetBase) onMouseOver(event d2input.MouseMoveEvent) bool {
return false
}
func (w *widgetBase) onMouseButtonDown(event d2input.MouseEvent) bool {
return false
}
func (w *widgetBase) onMouseButtonUp(event d2input.MouseEvent) bool {
return false
}

View File

@ -43,7 +43,7 @@ func Advance(elapsed float64) error {
}
d2ui.Reset()
d2gui.Clear()
d2gui.SetLayout(nil)
if _, ok := singleton.nextScene.(SceneLoadHandler); ok {
d2gui.ShowLoadScreen(0)

View File

@ -0,0 +1,49 @@
package d2gamescene
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type GuiTestMain struct{}
func CreateGuiTestMain() *GuiTestMain {
return &GuiTestMain{}
}
func (g *GuiTestMain) OnLoad() error {
layout := d2gui.CreateLayout(d2gui.PositionTypeHorizontal)
//
layoutLeft := layout.AddLayout(d2gui.PositionTypeVertical)
layoutLeft.SetHorizontalAlign(d2gui.HorizontalAlignCenter)
layoutLeft.AddLabel("FontStyle16Units", d2gui.FontStyle16Units)
layoutLeft.AddSpacerStatic(0, 100)
layoutLeft.AddLabel("FontStyle30Units", d2gui.FontStyle30Units)
layoutLeft.AddLabel("FontStyle42Units", d2gui.FontStyle42Units)
layoutLeft.AddLabel("FontStyleFormal10Static", d2gui.FontStyleFormal10Static)
layoutLeft.AddLabel("FontStyleFormal11Units", d2gui.FontStyleFormal11Units)
layoutLeft.AddLabel("FontStyleFormal12Static", d2gui.FontStyleFormal12Static)
layout.AddSpacerDynamic()
layoutRight := layout.AddLayout(d2gui.PositionTypeVertical)
layoutRight.SetHorizontalAlign(d2gui.HorizontalAlignRight)
layoutRight.AddButton("Medium", d2gui.ButtonStyleMedium)
layoutRight.AddButton("Narrow", d2gui.ButtonStyleNarrow)
layoutRight.AddButton("OkCancel", d2gui.ButtonStyleOkCancel)
layoutRight.AddButton("Short", d2gui.ButtonStyleShort)
layoutRight.AddButton("Wide", d2gui.ButtonStyleWide)
layout.SetVerticalAlign(d2gui.VerticalAlignMiddle)
d2gui.SetLayout(layout)
return nil
}
func (g *GuiTestMain) Render(screen d2render.Surface) error {
return nil
}
func (g *GuiTestMain) Advance(tickTime float64) error {
return nil
}

View File

@ -153,6 +153,9 @@ func initialize() error {
d2term.BindAction("quit", "exits the game", func() {
os.Exit(0)
})
d2term.BindAction("scene-gui", "enters the gui playground scene", func() {
d2scene.SetNextScene(d2gamescene.CreateGuiTestMain())
})
if err := d2asset.Initialize(); err != nil {
return err