Work in progress on GUI (#304)

* Work in progress on GUI refactor

* Remove WIP file

* Remove WIP style
This commit is contained in:
Alex Yatskov 2020-02-17 19:11:52 -08:00 committed by GitHub
parent 1983ec395d
commit 810b168ebf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 717 additions and 181 deletions

View File

@ -19,6 +19,7 @@ type assetManager struct {
fileManager *fileManager
paletteManager *paletteManager
animationManager *animationManager
fontManager *fontManager
}
func loadPalette(palettePath string) (*d2datadict.PaletteRec, error) {

View File

@ -21,6 +21,7 @@ func Initialize() error {
fileManager = createFileManager(config, archiveManager)
paletteManager = createPaletteManager()
animationManager = createAnimationManager()
fontManager = createFontManager()
)
singleton = &assetManager{
@ -28,6 +29,7 @@ func Initialize() error {
fileManager,
paletteManager,
animationManager,
fontManager,
}
d2term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
@ -44,10 +46,11 @@ func Initialize() error {
})
d2term.BindAction("assetstat", "display asset manager cache statistics", func() {
d2term.OutputInfo("archive cache: %f%%", float64(archiveManager.cache.GetWeight())/float64(archiveManager.cache.GetBudget())*100.0)
d2term.OutputInfo("file cache: %f%%", float64(fileManager.cache.GetWeight())/float64(fileManager.cache.GetBudget())*100.0)
d2term.OutputInfo("palette cache: %f%%", float64(paletteManager.cache.GetWeight())/float64(paletteManager.cache.GetBudget())*100.0)
d2term.OutputInfo("animation cache: %f%%", float64(animationManager.cache.GetWeight())/float64(animationManager.cache.GetBudget())*100.0)
d2term.OutputInfo("archive cache: %f", float64(archiveManager.cache.GetWeight())/float64(archiveManager.cache.GetBudget())*100.0)
d2term.OutputInfo("file cache: %f", float64(fileManager.cache.GetWeight())/float64(fileManager.cache.GetBudget())*100.0)
d2term.OutputInfo("palette cache: %f", float64(paletteManager.cache.GetWeight())/float64(paletteManager.cache.GetBudget())*100.0)
d2term.OutputInfo("animation cache: %f", float64(animationManager.cache.GetWeight())/float64(animationManager.cache.GetBudget())*100.0)
d2term.OutputInfo("font cache: %f", float64(fontManager.cache.GetWeight())/float64(fontManager.cache.GetBudget())*100.0)
})
d2term.BindAction("assetclear", "clear asset manager cache", func() {
@ -55,6 +58,7 @@ func Initialize() error {
fileManager.cache.Clear()
paletteManager.cache.Clear()
animationManager.cache.Clear()
fontManager.cache.Clear()
})
return nil
@ -86,6 +90,7 @@ func FileExists(filePath string) (bool, error) {
}
func LoadAnimation(animationPath, palettePath string) (*Animation, error) {
verifyWasInit()
return LoadAnimationWithTransparency(animationPath, palettePath, 255)
}
@ -95,9 +100,15 @@ func LoadAnimationWithTransparency(animationPath, palettePath string, transparen
}
func LoadComposite(object *d2datadict.ObjectLookupRecord, palettePath string) (*Composite, error) {
verifyWasInit()
return CreateComposite(object, palettePath), nil
}
func LoadFont(tablePath, spritePath, palettePath string) (*Font, error) {
verifyWasInit()
return singleton.fontManager.loadFont(tablePath, spritePath, palettePath)
}
func verifyWasInit() {
if singleton == nil {
panic(ErrNotInit)

126
d2core/d2asset/font.go Normal file
View File

@ -0,0 +1,126 @@
package d2asset
import (
"encoding/binary"
"errors"
"image/color"
"strings"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type fontGlyph struct {
frame int
width int
height int
}
type Font struct {
sheet *Animation
glyphs map[rune]fontGlyph
color color.Color
}
func loadFont(tablePath, spritePath, palettePath string) (*Font, error) {
sheet, err := LoadAnimation(spritePath, palettePath)
if err != nil {
return nil, err
}
data, err := LoadFile(tablePath)
if err != nil {
return nil, err
}
if string(data[:5]) != "Woo!\x01" {
return nil, errors.New("invalid font table format")
}
_, maxCharHeight := sheet.GetFrameBounds()
glyphs := make(map[rune]fontGlyph)
for i := 12; i < len(data); i += 14 {
code := rune(binary.LittleEndian.Uint16(data[i : i+2]))
var glyph fontGlyph
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
glyph.width = int(data[i+3])
glyph.height = maxCharHeight // int(data[i+4])
glyphs[code] = glyph
}
font := &Font{
sheet: sheet,
glyphs: glyphs,
color: color.White,
}
return font, nil
}
func (f *Font) GetTextMetrics(text string) (int, int) {
var (
lineWidth int
lineHeight int
totalWidth int
totalHeight int
)
for _, c := range text {
if c == '\n' {
totalWidth = d2common.MaxInt(totalWidth, lineWidth)
totalHeight += lineHeight
lineWidth = 0
lineHeight = 0
} else if glyph, ok := f.glyphs[c]; ok {
lineWidth += glyph.width
lineHeight = d2common.MaxInt(lineHeight, glyph.height)
}
}
totalWidth = d2common.MaxInt(totalWidth, lineWidth)
totalHeight += lineHeight
return totalWidth, totalHeight
}
func (f *Font) Clone() *Font {
return &Font{
sheet: f.sheet,
glyphs: f.glyphs,
color: f.color,
}
}
func (f *Font) RenderText(text string, target d2render.Surface) error {
f.sheet.SetColorMod(f.color)
f.sheet.SetBlend(false)
lines := strings.Split(text, "\n")
for _, line := range lines {
var (
lineHeight int
lineLength int
)
for _, c := range line {
if glyph, ok := f.glyphs[c]; ok {
f.sheet.SetCurrentFrame(glyph.frame)
f.sheet.Render(target)
lineHeight = d2common.MaxInt(lineHeight, glyph.height)
target.PushTranslation(glyph.width, 0)
lineLength++
}
}
target.PopN(lineLength)
target.PushTranslation(0, lineHeight)
}
target.PopN(len(lines))
return nil
}

View File

@ -0,0 +1,37 @@
package d2asset
import (
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
)
const (
fontBudget = 64
)
type fontManager struct {
cache *d2common.Cache
}
func createFontManager() *fontManager {
return &fontManager{d2common.CreateCache(fontBudget)}
}
func (fm *fontManager) loadFont(tablePath, spritePath, palettePath string) (*Font, error) {
cachePath := fmt.Sprintf("%s;%s;%s", tablePath, spritePath, palettePath)
if font, found := fm.cache.Retrieve(cachePath); found {
return font.(*Font).Clone(), nil
}
font, err := loadFont(tablePath, spritePath, palettePath)
if err != nil {
return nil, err
}
if err := fm.cache.Insert(cachePath, font.Clone(), 1); err != nil {
return nil, err
}
return font, nil
}

View File

@ -11,7 +11,7 @@ var (
ErrNotInit = errors.New("gui system is not initialized")
)
var singleton *guiManager
var singleton *manager
func Initialize() error {
verifyNotInit()
@ -34,6 +34,18 @@ 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() {
verifyWasInit()
singleton.clear()

View File

@ -1,125 +0,0 @@
package d2gui
import (
"image/color"
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type guiWidget interface {
getLayer() int
render(target d2render.Surface) error
advance(elapsed float64) error
}
type guiManager struct {
cursorSprite *Sprite
loadSprite *Sprite
widgets []guiWidget
loading bool
}
func createGuiManager() (*guiManager, error) {
cursorSprite, err := CreateSprite(d2resource.CursorDefault, d2resource.PaletteUnits)
if err != nil {
return nil, err
}
loadSprite, err := CreateSprite(d2resource.LoadingScreen, d2resource.PaletteLoading)
if err != nil {
return nil, err
}
width, height := loadSprite.getSize()
loadSprite.SetPosition(400-width/2, 300+height/2)
manager := &guiManager{
cursorSprite: cursorSprite,
loadSprite: loadSprite,
}
if err := d2input.BindHandler(manager); err != nil {
return nil, err
}
return manager, nil
}
func (gui *guiManager) OnMouseMove(event d2input.MouseMoveEvent) bool {
gui.cursorSprite.SetPosition(event.X, event.Y)
return false
}
func (gui *guiManager) render(target d2render.Surface) error {
if gui.loading {
target.Clear(color.Black)
if err := gui.loadSprite.render(target); err != nil {
return err
}
} else {
for _, widget := range gui.widgets {
if err := widget.render(target); err != nil {
return err
}
}
}
if err := gui.cursorSprite.render(target); err != nil {
return err
}
return nil
}
func (gui *guiManager) advance(elapsed float64) error {
if gui.loading {
gui.loadSprite.Show()
if err := gui.loadSprite.advance(elapsed); err != nil {
return err
}
} else {
gui.loadSprite.Hide()
for _, widget := range gui.widgets {
if err := widget.advance(elapsed); err != nil {
return err
}
}
}
if err := gui.loadSprite.advance(elapsed); err != nil {
return err
}
return nil
}
func (gui *guiManager) showLoadScreen(progress float64) {
progress = math.Min(progress, 1.0)
progress = math.Max(progress, 0.0)
animation := gui.loadSprite.animation
frameCount := animation.GetFrameCount()
animation.SetCurrentFrame(int(float64(frameCount-1.0) * progress))
gui.loading = true
}
func (gui *guiManager) hideLoadScreen() {
gui.loading = false
}
func (gui *guiManager) showCursor() {
gui.cursorSprite.Show()
}
func (gui *guiManager) hideCursor() {
gui.cursorSprite.Hide()
}
func (gui *guiManager) clear() {
gui.widgets = nil
gui.hideLoadScreen()
}

60
d2core/d2gui/label.go Normal file
View File

@ -0,0 +1,60 @@
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 (l *Label) SetText(text string) *Label {
l.text = text
l.cache()
return l
}
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()
}

163
d2core/d2gui/layout.go Normal file
View File

@ -0,0 +1,163 @@
package d2gui
import (
"image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type layoutEntry struct {
widget widget
mouseOver bool
mouseDown [3]bool
}
type Layout struct {
widgetBase
entries []*layoutEntry
}
func createLayout() *Layout {
layout := new(Layout)
layout.visible = true
return layout
}
func (l *Layout) render(target d2render.Surface) error {
for _, entry := range l.entries {
if entry.widget.isVisible() {
l.renderWidget(entry.widget, target)
l.renderWidgetDebug(entry.widget, target)
}
}
return nil
}
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
}
}
}
return nil
}
func (l *Layout) renderWidget(widget widget, target d2render.Surface) {
target.PushTranslation(widget.getPosition())
defer target.Pop()
widget.render(target)
}
func (l *Layout) renderWidgetDebug(widget widget, target d2render.Surface) {
target.PushTranslation(widget.getPosition())
defer target.Pop()
drawColor := color.RGBA{R: 0x00, G: 0x00, B: 0xff, A: 0xb0}
width, height := widget.getSize()
target.DrawLine(width, 0, drawColor)
target.DrawLine(0, height, drawColor)
target.PushTranslation(width, 0)
target.DrawLine(0, height, drawColor)
target.Pop()
target.PushTranslation(0, height)
target.DrawLine(width, 0, drawColor)
target.Pop()
}
func (l *Layout) getSize() (int, int) {
return 0, 0
}
func (l *Layout) onMouseButtonDown(event d2input.MouseEvent) bool {
for _, entry := range l.entries {
eventLocal := event
if l.adjustEventCoords(entry.widget, &eventLocal.X, &eventLocal.Y) {
entry.mouseDown[event.Button] = true
}
}
return false
}
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 entry.mouseDown[event.Button] {
entry.widget.onMouseClick(eventLocal)
}
}
entry.mouseDown[event.Button] = false
}
return false
}
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 entry.mouseOver {
entry.widget.onMouseOver(eventLocal)
} else {
entry.widget.onMouseEnter(eventLocal)
}
entry.mouseOver = true
} else if entry.mouseOver {
entry.widget.onMouseLeave(eventLocal)
entry.mouseOver = false
}
}
return false
}
func (l *Layout) adjustEventCoords(widget widget, eventX, eventY *int) bool {
x, y := widget.getPosition()
width, height := widget.getSize()
*eventX -= x
*eventY -= y
if *eventX < 0 || *eventY < 0 || *eventX >= width || *eventY >= 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) addSprite(imagePath, palettePath string) *Sprite {
sprite := createSprite(imagePath, palettePath)
l.entries = append(l.entries, &layoutEntry{widget: sprite})
return sprite
}
func (l *Layout) addLabel(text string, fontStyle FontStyle) *Label {
label := createLabel(text, fontStyle)
l.entries = append(l.entries, &layoutEntry{widget: label})
return label
}
func (l *Layout) clear() {
l.entries = nil
}

141
d2core/d2gui/manager.go Normal file
View File

@ -0,0 +1,141 @@
package d2gui
import (
"image/color"
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type manager struct {
Layout
cursorAnim *d2asset.Animation
cursorX int
cursorY int
cursorVisible bool
loadingAnim *d2asset.Animation
loading bool
}
func createGuiManager() (*manager, error) {
cursorAnim, err := d2asset.LoadAnimation(d2resource.CursorDefault, d2resource.PaletteUnits)
if err != nil {
return nil, err
}
loadingAnim, err := d2asset.LoadAnimation(d2resource.LoadingScreen, d2resource.PaletteLoading)
if err != nil {
return nil, err
}
manager := &manager{
cursorAnim: cursorAnim,
loadingAnim: loadingAnim,
cursorVisible: true,
}
if err := d2input.BindHandler(manager); err != nil {
return nil, err
}
return manager, nil
}
func (m *manager) OnMouseButtonDown(event d2input.MouseEvent) bool {
return m.Layout.onMouseButtonDown(event)
}
func (m *manager) OnMouseButtonUp(event d2input.MouseEvent) bool {
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)
}
func (m *manager) render(target d2render.Surface) error {
if m.loading {
if err := m.renderLoadScreen(target); err != nil {
return err
}
} else {
if err := m.Layout.render(target); err != nil {
return err
}
}
if m.cursorVisible {
if err := m.renderCursor(target); err != nil {
return err
}
}
return nil
}
func (m *manager) renderLoadScreen(target d2render.Surface) error {
target.Clear(color.Black)
screenWidth, screenHeight := target.GetSize()
animWidth, animHeight := m.loadingAnim.GetCurrentFrameSize()
target.PushTranslation(screenWidth/2-animWidth/2, screenHeight/2+animHeight/2)
target.PushTranslation(0, -animHeight)
defer target.PopN(2)
return m.loadingAnim.Render(target)
}
func (m *manager) renderCursor(target d2render.Surface) error {
_, height := m.cursorAnim.GetCurrentFrameSize()
target.PushTranslation(m.cursorX, m.cursorY)
target.PushTranslation(0, -height)
defer target.PopN(2)
return m.cursorAnim.Render(target)
}
func (m *manager) advance(elapsed float64) error {
if !m.loading {
if err := m.Layout.advance(elapsed); err != nil {
return err
}
}
return nil
}
func (m *manager) showLoadScreen(progress float64) {
progress = math.Min(progress, 1.0)
progress = math.Max(progress, 0.0)
animation := m.loadingAnim
frameCount := animation.GetFrameCount()
animation.SetCurrentFrame(int(float64(frameCount-1.0) * progress))
m.loading = true
}
func (m *manager) hideLoadScreen() {
m.loading = false
}
func (m *manager) showCursor() {
m.cursorVisible = true
}
func (m *manager) hideCursor() {
m.cursorVisible = false
}
func (m *manager) clear() {
m.Layout.clear()
m.hideLoadScreen()
}

View File

@ -7,29 +7,20 @@ import (
)
type Sprite struct {
x int
y int
widgetBase
segmentsX int
segmentsY int
frameOffset int
visible bool
animation *d2asset.Animation
}
func CreateSprite(imagePath, palettePath string) (*Sprite, error) {
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
if err != nil {
return nil, err
}
sprite := &Sprite{
animation: animation,
visible: true,
}
return sprite, nil
func createSprite(imagePath, palettePath string) *Sprite {
sprite := new(Sprite)
sprite.animation, _ = d2asset.LoadAnimation(imagePath, palettePath)
sprite.visible = true
return sprite
}
func (s *Sprite) SetSegmented(segmentsX, segmentsY, frameOffset int) {
@ -38,34 +29,13 @@ func (s *Sprite) SetSegmented(segmentsX, segmentsY, frameOffset int) {
s.frameOffset = frameOffset
}
func (s *Sprite) SetPosition(x, y int) {
s.x = x
s.y = y
}
func (s *Sprite) Show() {
s.visible = true
}
func (s *Sprite) Hide() {
s.visible = false
}
func (s *Sprite) getPosition() (int, int) {
return s.x, s.y
}
func (s *Sprite) getSize() (int, int) {
return s.animation.GetCurrentFrameSize()
}
func (s *Sprite) render(target d2render.Surface) error {
if !s.visible {
if s.animation == nil {
return nil
}
_, height := s.animation.GetCurrentFrameSize()
target.PushTranslation(s.x, s.y-height)
target.PushTranslation(0, -height)
defer target.Pop()
if s.segmentsX == 0 && s.segmentsY == 0 {
@ -100,5 +70,17 @@ func (s *Sprite) render(target d2render.Surface) error {
}
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()
}

36
d2core/d2gui/style.go Normal file
View File

@ -0,0 +1,36 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
type FontStyle int
const (
FontStyle16Units FontStyle = iota
FontStyle30Units
FontStyle42Units
FontStyleFormal10Static
FontStyleFormal11Units
FontStyleFormal12Static
)
type fontStyleConfig struct {
fontBasePath string
palettePath string
}
var fontStyleConfigs = map[FontStyle]fontStyleConfig{
FontStyle16Units: {d2resource.Font16, d2resource.PaletteUnits},
FontStyle30Units: {d2resource.Font30, d2resource.PaletteUnits},
FontStyle42Units: {d2resource.Font42, d2resource.PaletteUnits},
FontStyleFormal10Static: {d2resource.FontFormal10, d2resource.PaletteStatic},
FontStyleFormal11Units: {d2resource.FontFormal11, d2resource.PaletteUnits},
FontStyleFormal12Static: {d2resource.FontFormal12, d2resource.PaletteStatic},
}
func loadFont(fontStyle FontStyle) (*d2asset.Font, error) {
config := fontStyleConfigs[fontStyle]
return d2asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
}

105
d2core/d2gui/widget.go Normal file
View File

@ -0,0 +1,105 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type MouseHandler func(d2input.MouseEvent)
type MouseMoveHandler func(d2input.MouseMoveEvent)
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)
getPosition() (int, int)
getSize() (int, int)
getLayer() int
isVisible() bool
}
type widgetBase struct {
x int
y int
layer int
visible bool
mouseEnterHandler MouseMoveHandler
mouseLeaveHandler MouseMoveHandler
mouseMoveHandler MouseMoveHandler
mouseClickHandler MouseHandler
}
func (w *widgetBase) SetPosition(x, y int) {
w.x = x
w.y = y
}
func (w *widgetBase) SetLayer(layer int) {
w.layer = layer
}
func (w *widgetBase) SetVisible(visible bool) {
w.visible = visible
}
func (w *widgetBase) SetMouseEnterHandler(handler MouseMoveHandler) {
w.mouseEnterHandler = handler
}
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
}
func (w *widgetBase) getPosition() (int, int) {
return w.x, w.y
}
func (w *widgetBase) getLayer() int {
return w.layer
}
func (w *widgetBase) isVisible() bool {
return w.visible
}
func (w *widgetBase) advance(elapsed float64) error {
return nil
}
func (w *widgetBase) onMouseEnter(event d2input.MouseMoveEvent) {
if w.mouseEnterHandler != nil {
w.mouseEnterHandler(event)
}
}
func (w *widgetBase) onMouseLeave(event d2input.MouseMoveEvent) {
if w.mouseLeaveHandler != nil {
w.mouseLeaveHandler(event)
}
}
func (w *widgetBase) onMouseOver(event d2input.MouseMoveEvent) {
if w.mouseMoveHandler != nil {
w.mouseMoveHandler(event)
}
}
func (w *widgetBase) onMouseClick(event d2input.MouseEvent) {
if w.mouseClickHandler != nil {
w.mouseClickHandler(event)
}
}

View File

@ -1,13 +0,0 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type widget interface {
Render(target d2render.Surface) error
Advance(elapsed float64) error
}
type widgetManager struct {
}