1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-30 15:15:56 -04:00
OpenDiablo2/d2game/d2player/mini_panel.go
juander-ux 1f49df62d1
Ui hud polishing (#938)
* d2ui/tooltip: Make it invisible by default

* d2ui/button: Add GetToggled() method

* d2player/HUD: Add tooltip for minipanel button

* d2ui/button: Add disabled frame to minipanel buttons

* d2ui/widget_group: Add SetEnable method for clickable widgets

* d2player/mini_panel: move menu button here from HUD

* d2ui/button: toggled buttons take preference over disabled buttons

* d2player/help_overlay: Make panel only use widgets

* d2player/hud: Group most widgets into widget group

* d2ui/custom_widget: Allow tooltip to be attached

* d2player/hud: Attach staminaBar tooltip to staminaBar

* d2player/hud: Attach experienceBar tooltip to experienceBar widget

* d2ui/ui_manager: Always draw tooltips last

* d2player/help_overlay: It should be drawn over the HUD

* d2player/globeWidget: Move tooltip here from HUD

* d2core/tooltip: Automatically add tooltips to the uiManager

* d2core/ui_manager: Remove special handling of widgetGroups for rendering

* d2player/help_overlay: Add button to widget group

* d2player/hud: Attack runwalk tooltip to button

* d2player/mini_panel: Add panelButton to its own widget group

* d2core/widget_group: When a clickable is added, it's also added to uiManager

* d2player/globeWidget: make tooltip un/lock on click

* d2player/hud: Add runbutton to widget group

* d2player/mini_panel: Add group for tooltips

this allows us to move the tooltip with the panelbuttons. They can't be
in the general panelGroup as they would all become visible when the
panel is opened.

* d2core/button: Remove debug log when a button with tooltip is hovered
2020-11-21 02:35:32 -08:00

404 lines
8.5 KiB
Go

package d2player
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
const (
miniPanelX = 325
miniPanelY = 526
panelOffsetLeft = 130
panelOffsetRight = 130
)
const (
containerOffsetX = -75
containerOffsetY = -49
buttonOffsetX = -72
buttonOffsetY = -52
)
type miniPanelContent struct {
buttonType d2ui.ButtonType
onActivate func()
tooltip string
}
type miniPanelActions struct {
characterToggle func()
inventoryToggle func()
skilltreeToggle func()
partyToggle func()
automapToggle func()
messageToggle func()
questToggle func()
menuToggle func()
}
func newMiniPanel(asset *d2asset.AssetManager,
uiManager *d2ui.UIManager,
l d2util.LogLevel,
isSinglePlayer bool) *miniPanel {
mp := &miniPanel{
ui: uiManager,
asset: asset,
isOpen: false,
isSinglePlayer: isSinglePlayer,
}
mp.logger = d2util.NewLogger()
mp.logger.SetLevel(l)
mp.logger.SetPrefix(logPrefix)
return mp
}
type miniPanel struct {
ui *d2ui.UIManager
asset *d2asset.AssetManager
container *d2ui.Sprite
sprite *d2ui.Sprite
menuButton *d2ui.Button
miniPanelTooltip *d2ui.Tooltip
isOpen bool
tempIsOpen bool
disabled bool
isSinglePlayer bool
movedLeft bool
movedRight bool
panelGroup *d2ui.WidgetGroup
groupAlwaysVis *d2ui.WidgetGroup
tooltipGroup *d2ui.WidgetGroup
logger *d2util.Logger
}
func (m *miniPanel) load(actions *miniPanelActions) {
var err error
m.sprite, err = m.ui.NewSprite(d2resource.MinipanelButton, d2resource.PaletteSky)
if err != nil {
m.logger.Error(err.Error())
return
}
m.createWidgets(actions)
}
func (m *miniPanel) createWidgets(actions *miniPanelActions) {
var err error
m.panelGroup = m.ui.NewWidgetGroup(d2ui.RenderPriorityMinipanel)
m.panelGroup.SetPosition(miniPanelX, miniPanelY)
m.groupAlwaysVis = m.ui.NewWidgetGroup(d2ui.RenderPriorityMinipanel)
m.tooltipGroup = m.ui.NewWidgetGroup(d2ui.RenderPriorityForeground)
// container sprite
miniPanelContainerPath := d2resource.Minipanel
if m.isSinglePlayer {
miniPanelContainerPath = d2resource.MinipanelSmall
}
m.container, err = m.ui.NewSprite(miniPanelContainerPath, d2resource.PaletteSky)
if err != nil {
m.logger.Error(err.Error())
return
}
if err = m.container.SetCurrentFrame(0); err != nil {
m.logger.Error(err.Error())
return
}
// nolint:golint,gomnd // divide by 2 does not need a magic number
x, y := screenWidth/2+containerOffsetX, screenHeight+containerOffsetY
m.container.SetPosition(x, y)
m.panelGroup.AddWidget(m.container)
m.createButtons(actions)
m.panelGroup.SetVisible(false)
}
func (m *miniPanel) createButtons(actions *miniPanelActions) {
var x, y int
buttonWidth, buttonHeight, err := m.sprite.GetFrameSize(0)
if err != nil {
m.logger.Error(err.Error())
return
}
buttonWidth++
// nolint:golint,gomnd // divide by 2 does not need a magic number
x, y = screenWidth/2+buttonOffsetX, screenHeight+buttonOffsetY-buttonHeight
buttonsFirst := []miniPanelContent{
{d2ui.ButtonTypeMinipanelCharacter,
actions.characterToggle,
m.asset.TranslateString("minipanelchar"),
},
{d2ui.ButtonTypeMinipanelInventory,
actions.inventoryToggle,
m.asset.TranslateString("minipanelinv"),
},
{d2ui.ButtonTypeMinipanelSkill,
actions.skilltreeToggle,
m.asset.TranslateString("minipaneltree"),
},
}
for i := range buttonsFirst {
btn := m.createButton(buttonsFirst[i], x+(i*buttonWidth), y, buttonHeight)
m.panelGroup.AddWidget(btn)
}
idxOffset := len(buttonsFirst)
if !m.isSinglePlayer {
partyContent := miniPanelContent{d2ui.ButtonTypeMinipanelParty,
actions.partyToggle,
m.asset.TranslateString("minipanelparty"),
}
btn := m.createButton(partyContent, x+(3*buttonWidth), y, buttonHeight)
m.panelGroup.AddWidget(btn)
idxOffset++
}
buttonsLast := []miniPanelContent{
{d2ui.ButtonTypeMinipanelAutomap,
actions.automapToggle,
m.asset.TranslateString("minipanelautomap"),
},
{d2ui.ButtonTypeMinipanelMessage,
actions.messageToggle,
m.asset.TranslateString("minipanelmessage"),
},
{d2ui.ButtonTypeMinipanelQuest,
actions.questToggle,
m.asset.TranslateString("minipanelquest"),
},
{d2ui.ButtonTypeMinipanelMen,
actions.menuToggle,
m.asset.TranslateString("minipanelmenubtn"),
},
}
for i := range buttonsLast {
idx := i + idxOffset
btn := m.createButton(buttonsLast[i], x+(idx*buttonWidth), y, buttonHeight)
m.panelGroup.AddWidget(btn)
}
//nolint:gomnd // divide by 2 is not a magic number
x = screenWidth/2 + miniPanelButtonOffsetX
y = screenHeight + miniPanelButtonOffsetY
// minipanel open/close tooltip
m.miniPanelTooltip = m.ui.NewTooltip(d2resource.Font16, d2resource.PaletteUnits, d2ui.TooltipXCenter, d2ui.TooltipYTop)
m.miniPanelTooltip.SetPosition(x+miniPanelTooltipOffsetX, y+miniPanelTooltipOffsetY)
// minipanel button
m.menuButton = m.ui.NewButton(d2ui.ButtonTypeMinipanelOpenClose, "")
m.menuButton.SetPosition(x, y)
m.menuButton.OnActivated(m.onMenuButtonClicked)
m.menuButton.SetTooltip(m.miniPanelTooltip)
m.updateMinipanelTooltipText()
m.groupAlwaysVis.AddWidget(m.menuButton)
}
func (m *miniPanel) createButton(content miniPanelContent, x, y, buttonHeight int) *d2ui.Button {
// Tooltip
tt := m.ui.NewTooltip(d2resource.Font16, d2resource.PaletteSky, d2ui.TooltipXCenter, d2ui.TooltipYTop)
tt.SetPosition(x, y-buttonHeight)
tt.SetText(content.tooltip)
tt.SetVisible(false)
m.tooltipGroup.AddWidget(tt)
// Button
btn := m.ui.NewButton(content.buttonType, "")
btn.SetPosition(x, y)
btn.OnActivated(content.onActivate)
btn.SetTooltip(tt)
btn.SetRenderPriority(d2ui.RenderPriorityForeground)
return btn
}
func (m *miniPanel) onMenuButtonClicked() {
m.menuButton.Toggle()
m.Toggle()
m.updateMinipanelTooltipText()
}
func (m *miniPanel) updateMinipanelTooltipText() {
var stringTableKey string
if m.menuButton.GetToggled() {
stringTableKey = "panelcmini"
} else {
stringTableKey = "panelmini"
}
m.miniPanelTooltip.SetText(m.asset.TranslateString(stringTableKey))
}
func (m *miniPanel) IsOpen() bool {
return m.isOpen
}
func (m *miniPanel) Toggle() {
if m.isOpen {
m.Close()
} else {
m.Open()
}
}
func (m *miniPanel) Open() {
if !m.movedLeft && !m.movedRight {
m.panelGroup.SetVisible(true)
}
if !m.menuButton.GetToggled() {
m.menuButton.Toggle()
}
m.isOpen = true
}
func (m *miniPanel) Close() {
m.panelGroup.SetVisible(false)
if m.menuButton.GetToggled() {
m.menuButton.Toggle()
}
m.isOpen = false
}
func (m *miniPanel) IsInRect(px, py int) bool {
return m.panelGroup.Contains(px, py)
}
func (m *miniPanel) moveRight() {
m.panelGroup.OffsetPosition(panelOffsetRight, 0)
m.tooltipGroup.OffsetPosition(panelOffsetRight, 0)
}
func (m *miniPanel) undoMoveRight() {
m.panelGroup.OffsetPosition(-panelOffsetRight, 0)
}
func (m *miniPanel) moveLeft() {
m.panelGroup.OffsetPosition(-panelOffsetLeft, 0)
m.tooltipGroup.OffsetPosition(-panelOffsetLeft, 0)
}
func (m *miniPanel) undoMoveLeft() {
m.panelGroup.OffsetPosition(panelOffsetLeft, 0)
m.tooltipGroup.OffsetPosition(panelOffsetLeft, 0)
}
func (m *miniPanel) SetMovedLeft(moveLeft bool) {
if m.movedLeft == moveLeft {
return
}
if m.movedRight {
if moveLeft {
m.undoMoveRight()
m.panelGroup.SetVisible(false)
} else {
m.moveRight()
m.panelGroup.SetVisible(m.isOpen)
}
} else {
if moveLeft {
m.moveLeft()
} else {
m.undoMoveLeft()
}
}
m.movedLeft = moveLeft
}
func (m *miniPanel) SetMovedRight(moveRight bool) {
if m.movedRight == moveRight {
return
}
if m.movedLeft {
if moveRight {
m.undoMoveLeft()
m.panelGroup.SetVisible(false)
} else {
m.moveLeft()
m.panelGroup.SetVisible(m.isOpen)
}
} else {
if moveRight {
m.moveRight()
} else {
m.undoMoveRight()
}
}
m.movedRight = moveRight
}
func (m *miniPanel) openDisabled() {
if m.disabled {
return
}
m.tempIsOpen = m.isOpen
if !m.isOpen {
m.Open()
}
m.menuButton.SetEnabled(false)
m.panelGroup.SetEnabled(false)
m.disabled = true
}
func (m *miniPanel) closeDisabled() {
if m.disabled {
return
}
m.tempIsOpen = m.isOpen
if m.isOpen {
m.Close()
}
m.menuButton.SetEnabled(false)
m.panelGroup.SetEnabled(false)
m.disabled = true
}
func (m *miniPanel) restoreDisabled() {
if !m.disabled {
return
}
m.disabled = false
m.menuButton.SetEnabled(true)
m.panelGroup.SetEnabled(true)
if m.tempIsOpen {
m.Open()
} else {
m.Close()
}
}