1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-09 09:20:44 +00: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)
GetVisible() bool
SetVisible(visible bool)
SetRenderPriority(priority RenderPriority)
GetRenderPriority() (priority RenderPriority)
}

View File

@ -2,6 +2,7 @@ package d2ui
import (
"log"
"sort"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
@ -17,6 +18,7 @@ type UIManager struct {
inputManager d2interface.InputManager
audio d2interface.AudioProvider
widgets []Widget
widgetsGroups []*WidgetGroup
clickableWidgets []ClickableWidget
cursorButtons CursorButton
CursorX int
@ -49,6 +51,14 @@ func (ui *UIManager) Reset() {
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
func (ui *UIManager) addWidget(widget 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

View File

@ -1,5 +1,16 @@
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
type Widget interface {
Drawable
@ -19,23 +30,25 @@ type ClickableWidget interface {
// BaseWidget contains default functionality that all widgets share
type BaseWidget struct {
manager *UIManager
x int
y int
width int
height int
visible bool
manager *UIManager
x int
y int
width int
height int
renderPriority RenderPriority
visible bool
}
// NewBaseWidget creates a new BaseWidget with defaults
func NewBaseWidget(manager *UIManager) *BaseWidget {
return &BaseWidget{
manager: manager,
x: 0,
y: 0,
width: 0,
height: 0,
visible: true,
manager: manager,
x: 0,
y: 0,
width: 0,
height: 0,
visible: true,
renderPriority: RenderPriorityBackground,
}
}
@ -73,3 +86,13 @@ func (b *BaseWidget) GetVisible() (visible bool) {
func (b *BaseWidget) SetVisible(visible bool) {
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)
}
}