mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-06-20 22:25:24 +00:00
627bc8ec65
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.
178 lines
4.6 KiB
Go
178 lines
4.6 KiB
Go
package d2ui
|
|
|
|
import (
|
|
"log"
|
|
"sort"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
|
)
|
|
|
|
// UIManager manages a collection of UI elements (buttons, textboxes, labels)
|
|
type UIManager struct {
|
|
asset *d2asset.AssetManager
|
|
renderer d2interface.Renderer
|
|
inputManager d2interface.InputManager
|
|
audio d2interface.AudioProvider
|
|
widgets []Widget
|
|
widgetsGroups []*WidgetGroup
|
|
clickableWidgets []ClickableWidget
|
|
cursorButtons CursorButton
|
|
CursorX int
|
|
CursorY int
|
|
pressedWidget ClickableWidget
|
|
clickSfx d2interface.SoundEffect
|
|
}
|
|
|
|
// Note: methods for creating buttons and stuff are in their respective files
|
|
|
|
// Initialize is meant to be called after the game loads all of the necessary files
|
|
// for sprites and audio
|
|
func (ui *UIManager) Initialize() {
|
|
sfx, err := ui.audio.LoadSound(d2resource.SFXButtonClick, false, false)
|
|
if err != nil {
|
|
log.Fatalf("failed to initialize ui: %v", err)
|
|
}
|
|
|
|
ui.clickSfx = sfx
|
|
|
|
if err := ui.inputManager.BindHandler(ui); err != nil {
|
|
log.Fatalf("failed to initialize ui: %v", err)
|
|
}
|
|
}
|
|
|
|
// Reset resets the state of the UI manager. Typically called for new screens
|
|
func (ui *UIManager) Reset() {
|
|
ui.widgets = nil
|
|
ui.clickableWidgets = 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
|
|
func (ui *UIManager) addWidget(widget Widget) {
|
|
err := ui.inputManager.BindHandler(widget)
|
|
if err != nil {
|
|
log.Print(err)
|
|
}
|
|
|
|
clickable, ok := widget.(ClickableWidget)
|
|
if ok {
|
|
ui.clickableWidgets = append(ui.clickableWidgets, clickable)
|
|
}
|
|
|
|
ui.widgets = append(ui.widgets, widget)
|
|
widget.bindManager(ui)
|
|
}
|
|
|
|
// OnMouseButtonUp is an event handler for input
|
|
func (ui *UIManager) OnMouseButtonUp(event d2interface.MouseEvent) bool {
|
|
ui.CursorX, ui.CursorY = event.X(), event.Y()
|
|
if event.Button() == d2enum.MouseButtonLeft {
|
|
ui.cursorButtons |= CursorButtonLeft
|
|
// activate previously pressed widget if cursor is still hovering
|
|
w := ui.pressedWidget
|
|
|
|
if w != nil && ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
|
w.Activate()
|
|
}
|
|
|
|
// unpress all widgets that are pressed
|
|
for _, w := range ui.clickableWidgets {
|
|
w.SetPressed(false)
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// OnMouseButtonDown is the mouse button down event handler
|
|
func (ui *UIManager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
|
ui.CursorX, ui.CursorY = event.X(), event.Y()
|
|
if event.Button() == d2enum.MouseButtonLeft {
|
|
// find and press a widget on screen
|
|
ui.pressedWidget = nil
|
|
for _, w := range ui.clickableWidgets {
|
|
if ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
|
w.SetPressed(true)
|
|
ui.pressedWidget = w
|
|
ui.clickSfx.Play()
|
|
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if event.Button() == d2enum.MouseButtonRight {
|
|
ui.cursorButtons |= CursorButtonRight
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// Render renders all of the UI elements
|
|
func (ui *UIManager) Render(target d2interface.Surface) {
|
|
for _, widget := range ui.widgets {
|
|
if widget.GetVisible() {
|
|
err := widget.Render(target)
|
|
if err != nil {
|
|
log.Print(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
func (ui *UIManager) contains(w Widget, x, y int) bool {
|
|
wx, wy := w.GetPosition()
|
|
ww, wh := w.GetSize()
|
|
|
|
return x >= wx && x <= wx+ww && y >= wy && y <= wy+wh
|
|
}
|
|
|
|
// Advance updates all of the UI elements
|
|
func (ui *UIManager) Advance(elapsed float64) {
|
|
for _, widget := range ui.widgets {
|
|
if widget.GetVisible() {
|
|
err := widget.Advance(elapsed)
|
|
if err != nil {
|
|
log.Print(err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// CursorButtonPressed determines if the specified button has been pressed
|
|
func (ui *UIManager) CursorButtonPressed(button CursorButton) bool {
|
|
return ui.cursorButtons&button > 0
|
|
}
|
|
|
|
// CursorPosition returns the current cursor position
|
|
func (ui *UIManager) CursorPosition() (x, y int) {
|
|
return ui.CursorX, ui.CursorY
|
|
}
|
|
|
|
// Renderer returns the renderer for this ui manager
|
|
func (ui *UIManager) Renderer() d2interface.Renderer {
|
|
return ui.renderer
|
|
}
|