1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2025-02-20 23:47:16 -05:00

d2ui: Add WidgetGroup

this allows us to groups screens together, such that they can be
de-/activated by de-/activating the group instead of every ui element by
hand.

Before we were deactivating buttons and stopped rendering to deactivate ui
elements. This tied the renderer to these elements.
This commit is contained in:
juander 2020-11-06 13:28:24 +01:00
parent 881d5f1f71
commit 627bc8ec65
4 changed files with 148 additions and 12 deletions

View File

@ -14,4 +14,6 @@ type Drawable interface {
OffsetPosition(xo, yo int) OffsetPosition(xo, yo int)
GetVisible() bool GetVisible() bool
SetVisible(visible bool) SetVisible(visible bool)
SetRenderPriority(priority RenderPriority)
GetRenderPriority() (priority RenderPriority)
} }

View File

@ -2,6 +2,7 @@ package d2ui
import ( import (
"log" "log"
"sort"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
@ -17,6 +18,7 @@ type UIManager struct {
inputManager d2interface.InputManager inputManager d2interface.InputManager
audio d2interface.AudioProvider audio d2interface.AudioProvider
widgets []Widget widgets []Widget
widgetsGroups []*WidgetGroup
clickableWidgets []ClickableWidget clickableWidgets []ClickableWidget
cursorButtons CursorButton cursorButtons CursorButton
CursorX int CursorX int
@ -49,6 +51,14 @@ func (ui *UIManager) Reset() {
ui.pressedWidget = nil ui.pressedWidget = nil
} }
// addWidgetGroup adds a widgetGroup to the UI manager and sorts by priority
func (ui *UIManager) addWidgetGroup(group *WidgetGroup) {
ui.widgetsGroups = append(ui.widgetsGroups, group)
sort.SliceStable(ui.widgetsGroups, func(i, j int) bool {
return ui.widgetsGroups[i].priority < ui.widgetsGroups[j].priority
})
}
// addWidget adds a widget to the UI manager // addWidget adds a widget to the UI manager
func (ui *UIManager) addWidget(widget Widget) { func (ui *UIManager) addWidget(widget Widget) {
err := ui.inputManager.BindHandler(widget) err := ui.inputManager.BindHandler(widget)
@ -120,6 +130,15 @@ func (ui *UIManager) Render(target d2interface.Surface) {
} }
} }
} }
for _, widgetGroup := range ui.widgetsGroups {
if widgetGroup.GetVisible() {
err := widgetGroup.Render(target)
if err != nil {
log.Print(err)
}
}
}
} }
// contains determines whether a given x,y coordinate lands within a Widget // contains determines whether a given x,y coordinate lands within a Widget

View File

@ -1,5 +1,16 @@
package d2ui package d2ui
// RenderPriority determines in which order ui elements are drawn.
// The higher the number the later an element is drawn.
type RenderPriority int
const (
// RenderPriorityBackground is the first element drawn
RenderPriorityBackground RenderPriority = iota
// RenderPriorityForeground is the last element drawn
RenderPriorityForeground
)
// Widget defines an object that is a UI widget // Widget defines an object that is a UI widget
type Widget interface { type Widget interface {
Drawable Drawable
@ -24,6 +35,7 @@ type BaseWidget struct {
y int y int
width int width int
height int height int
renderPriority RenderPriority
visible bool visible bool
} }
@ -36,6 +48,7 @@ func NewBaseWidget(manager *UIManager) *BaseWidget {
width: 0, width: 0,
height: 0, height: 0,
visible: true, visible: true,
renderPriority: RenderPriorityBackground,
} }
} }
@ -73,3 +86,13 @@ func (b *BaseWidget) GetVisible() (visible bool) {
func (b *BaseWidget) SetVisible(visible bool) { func (b *BaseWidget) SetVisible(visible bool) {
b.visible = visible b.visible = visible
} }
// GetRenderPriority returns the order in which this widget is rendered
func (b *BaseWidget) GetRenderPriority() (prio RenderPriority) {
return b.renderPriority
}
// SetRenderPriority sets the order in which this widget is rendered
func (b *BaseWidget) SetRenderPriority(prio RenderPriority) {
b.renderPriority = prio
}

View File

@ -0,0 +1,92 @@
package d2ui
import (
"sort"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
)
// static check that WidgetGroup implements widget
var _ Widget = &WidgetGroup{}
// WidgetGroup allows the grouping of widgets to apply actions to all
// widgets at once.
type WidgetGroup struct {
*BaseWidget
entries []Widget
priority RenderPriority
}
// NewWidgetGroup creates a new widget group
func (ui *UIManager) NewWidgetGroup(priority RenderPriority) *WidgetGroup {
base := NewBaseWidget(ui)
base.SetRenderPriority(priority)
group := &WidgetGroup{
BaseWidget: base,
}
ui.addWidgetGroup(group)
return group
}
// AddWidget adds a widget to the group
func (wg *WidgetGroup) AddWidget(w Widget) {
wg.adjustSize(w)
wg.entries = append(wg.entries, w)
sort.SliceStable(wg.entries, func(i, j int) bool {
return wg.entries[i].GetRenderPriority() < wg.entries[j].GetRenderPriority()
})
}
// adjustSize recalculates the bounding box if a new widget is added
func (wg *WidgetGroup) adjustSize(w Widget) {
x, y := w.GetPosition()
width, height := w.GetSize()
if x+width > wg.width {
wg.width = x + width
}
if wg.x > x {
wg.width += wg.x - x
wg.x = x
}
if y+height > wg.height {
wg.height = x + height
}
if wg.y > y {
wg.height += wg.y - y
wg.y = y
}
}
// Advance is a no-op here
func (wg *WidgetGroup) Advance(elapsed float64) error {
// No-op
return nil
}
// Render draw the widgets to the screen
func (wg *WidgetGroup) Render(target d2interface.Surface) error {
for _, entry := range wg.entries {
if entry.GetVisible() {
err := entry.Render(target)
if err != nil {
return err
}
}
}
return nil
}
// SetVisible sets the visibility of all widgets in the group
func (wg *WidgetGroup) SetVisible(visible bool) {
for _, entry := range wg.entries {
entry.SetVisible(visible)
}
}