mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-01-27 03:37:53 -05:00
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
This commit is contained in:
parent
e89450daf1
commit
1f49df62d1
@ -131,7 +131,6 @@ const (
|
||||
buttonSkillTreeTabFixedHeight = 107
|
||||
|
||||
buttonMinipanelOpenCloseBaseFrame = 0
|
||||
buttonMinipanelDisabledFrame = 2
|
||||
buttonMinipanelXSegments = 1
|
||||
buttonMinipanelYSegments = 1
|
||||
|
||||
@ -278,7 +277,7 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelOpenClose: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelDisabledFrame,
|
||||
DisabledFrame: buttonMinipanelOpenCloseBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelOpenCloseBaseFrame,
|
||||
ResourceName: d2resource.MenuButton,
|
||||
@ -294,6 +293,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelCharacter: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelCharacterBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelCharacterBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -308,6 +309,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelInventory: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelInventoryBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelInventoryBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -322,6 +325,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelSkill: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelSkilltreeBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelSkilltreeBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -336,6 +341,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelParty: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelPartyBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelPartyBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -350,6 +357,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelAutomap: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelAutomapBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelAutomapBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -364,6 +373,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelMessage: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelMessageBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelMessageBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -378,6 +389,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelQuest: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelQuestBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelQuestBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -392,6 +405,8 @@ func getButtonLayouts() map[ButtonType]ButtonLayout {
|
||||
ButtonTypeMinipanelMen: {
|
||||
XSegments: buttonMinipanelXSegments,
|
||||
YSegments: buttonMinipanelYSegments,
|
||||
DisabledFrame: buttonMinipanelMenBaseFrame,
|
||||
DisabledColor: whiteAlpha100,
|
||||
BaseFrame: buttonMinipanelMenBaseFrame,
|
||||
ResourceName: d2resource.MinipanelButton,
|
||||
PaletteName: d2resource.PaletteSky,
|
||||
@ -628,7 +643,12 @@ func (v *Button) Render(target d2interface.Surface) {
|
||||
case !v.enabled:
|
||||
target.PushColor(d2util.Color(v.buttonLayout.DisabledColor))
|
||||
defer target.Pop()
|
||||
target.Render(v.disabledSurface)
|
||||
|
||||
if v.toggled {
|
||||
target.Render(v.toggledSurface)
|
||||
} else {
|
||||
target.Render(v.disabledSurface)
|
||||
}
|
||||
case v.toggled && v.pressed:
|
||||
target.Render(v.pressedToggledSurface)
|
||||
case v.pressed:
|
||||
@ -649,6 +669,11 @@ func (v *Button) Toggle() {
|
||||
v.toggled = !v.toggled
|
||||
}
|
||||
|
||||
// GetToggled returns the toggled state of the button
|
||||
func (v *Button) GetToggled() bool {
|
||||
return v.toggled
|
||||
}
|
||||
|
||||
// Advance advances the button state
|
||||
func (v *Button) Advance(_ float64) error {
|
||||
return nil
|
||||
@ -695,8 +720,7 @@ func (v *Button) SetPosition(x, y int) {
|
||||
// SetTooltip adds a tooltip to the button
|
||||
func (v *Button) SetTooltip(t *Tooltip) {
|
||||
v.tooltip = t
|
||||
v.manager.addWidget(t)
|
||||
v.OnHoverStart(func() { log.Print("HoverStart"); v.tooltip.SetVisible(true) })
|
||||
v.OnHoverStart(func() { v.tooltip.SetVisible(true) })
|
||||
v.OnHoverEnd(func() { v.tooltip.SetVisible(false) })
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ type CustomWidget struct {
|
||||
renderFunc func(target d2interface.Surface)
|
||||
cached bool
|
||||
cachedImg *d2interface.Surface
|
||||
tooltip *Tooltip
|
||||
}
|
||||
|
||||
// NewCustomWidgetCached creates a new widget and caches anything rendered via the
|
||||
@ -50,6 +51,13 @@ func (c *CustomWidget) Render(target d2interface.Surface) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetTooltip gives this widget a Tooltip that is displayed if the widget is hovered
|
||||
func (c *CustomWidget) SetTooltip(t *Tooltip) {
|
||||
c.tooltip = t
|
||||
c.OnHoverStart(func() { c.tooltip.SetVisible(true) })
|
||||
c.OnHoverEnd(func() { c.tooltip.SetVisible(false) })
|
||||
}
|
||||
|
||||
// Advance is a no-op
|
||||
func (c *CustomWidget) Advance(elapsed float64) error {
|
||||
return nil
|
||||
|
@ -58,6 +58,7 @@ func (ui *UIManager) NewTooltip(font,
|
||||
label.Alignment = HorizontalAlignCenter
|
||||
|
||||
base := NewBaseWidget(ui)
|
||||
base.SetVisible(false)
|
||||
|
||||
res := &Tooltip{
|
||||
BaseWidget: base,
|
||||
@ -68,6 +69,7 @@ func (ui *UIManager) NewTooltip(font,
|
||||
boxEnabled: true,
|
||||
}
|
||||
res.manager = ui
|
||||
ui.addTooltip(res)
|
||||
|
||||
return res
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ type UIManager struct {
|
||||
inputManager d2interface.InputManager
|
||||
audio d2interface.AudioProvider
|
||||
widgets []Widget
|
||||
tooltips []*Tooltip
|
||||
widgetsGroups []*WidgetGroup
|
||||
clickableWidgets []ClickableWidget
|
||||
cursorButtons CursorButton
|
||||
@ -53,13 +54,8 @@ 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].renderPriority < ui.widgetsGroups[j].renderPriority
|
||||
})
|
||||
func (ui *UIManager) addClickable(widget ClickableWidget) {
|
||||
ui.clickableWidgets = append(ui.clickableWidgets, widget)
|
||||
}
|
||||
|
||||
// addWidget adds a widget to the UI manager
|
||||
@ -71,13 +67,27 @@ func (ui *UIManager) addWidget(widget Widget) {
|
||||
|
||||
clickable, ok := widget.(ClickableWidget)
|
||||
if ok {
|
||||
ui.clickableWidgets = append(ui.clickableWidgets, clickable)
|
||||
ui.addClickable(clickable)
|
||||
}
|
||||
|
||||
if widgetGroup, ok := widget.(*WidgetGroup); ok {
|
||||
ui.widgetsGroups = append(ui.widgetsGroups, widgetGroup)
|
||||
}
|
||||
|
||||
ui.widgets = append(ui.widgets, widget)
|
||||
|
||||
sort.SliceStable(ui.widgets, func(i, j int) bool {
|
||||
return ui.widgets[i].GetRenderPriority() < ui.widgets[j].GetRenderPriority()
|
||||
})
|
||||
|
||||
widget.bindManager(ui)
|
||||
}
|
||||
|
||||
// addTooltip adds a widget to the UI manager
|
||||
func (ui *UIManager) addTooltip(t *Tooltip) {
|
||||
ui.tooltips = append(ui.tooltips, t)
|
||||
}
|
||||
|
||||
// OnMouseButtonUp is an event handler for input
|
||||
func (ui *UIManager) OnMouseButtonUp(event d2interface.MouseEvent) bool {
|
||||
ui.CursorX, ui.CursorY = event.X(), event.Y()
|
||||
@ -142,17 +152,17 @@ func (ui *UIManager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
||||
|
||||
// Render renders all of the UI elements
|
||||
func (ui *UIManager) Render(target d2interface.Surface) {
|
||||
for _, widgetGroup := range ui.widgetsGroups {
|
||||
if widgetGroup.GetVisible() {
|
||||
widgetGroup.Render(target)
|
||||
}
|
||||
}
|
||||
|
||||
for _, widget := range ui.widgets {
|
||||
if widget.GetVisible() {
|
||||
widget.Render(target)
|
||||
}
|
||||
}
|
||||
|
||||
for _, tooltip := range ui.tooltips {
|
||||
if tooltip.GetVisible() {
|
||||
tooltip.Render(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Advance updates all of the UI elements
|
||||
|
@ -4,18 +4,16 @@ package d2ui
|
||||
// The higher the number the later an element is drawn.
|
||||
type RenderPriority int
|
||||
|
||||
// Render priorities that determine the order in which widgets/widgetgroups are
|
||||
// rendered. The higher the later it is rendered
|
||||
const (
|
||||
// RenderPriorityBackground is the first element drawn
|
||||
RenderPriorityBackground RenderPriority = iota
|
||||
// RenderPrioritySkilltree is the priority for the skilltree
|
||||
RenderPrioritySkilltree
|
||||
// RenderPrioritySkilltreeIcon is the priority for the skilltree icons
|
||||
RenderPrioritySkilltreeIcon
|
||||
// RenderPriorityMinipanel is the priority for the minipanel icons
|
||||
RenderPriorityMinipanel
|
||||
// RenderPriorityHeroStatsPanel is the priority for the hero_stats_panel
|
||||
RenderPriorityHeroStatsPanel
|
||||
// RenderPriorityForeground is the last element drawn
|
||||
RenderPriorityHUDPanel
|
||||
RenderPriorityMinipanel
|
||||
RenderPriorityHelpPanel
|
||||
RenderPriorityForeground
|
||||
)
|
||||
|
||||
|
@ -28,7 +28,7 @@ func (ui *UIManager) NewWidgetGroup(priority RenderPriority) *WidgetGroup {
|
||||
BaseWidget: base,
|
||||
}
|
||||
|
||||
ui.addWidgetGroup(group)
|
||||
ui.addWidget(group)
|
||||
|
||||
return group
|
||||
}
|
||||
@ -40,6 +40,10 @@ func (wg *WidgetGroup) AddWidget(w Widget) {
|
||||
sort.SliceStable(wg.entries, func(i, j int) bool {
|
||||
return wg.entries[i].GetRenderPriority() < wg.entries[j].GetRenderPriority()
|
||||
})
|
||||
|
||||
if clickable, ok := w.(ClickableWidget); ok {
|
||||
wg.manager.addClickable(clickable)
|
||||
}
|
||||
}
|
||||
|
||||
// adjustSize recalculates the bounding box if a new widget is added
|
||||
@ -127,3 +131,12 @@ func (wg *WidgetGroup) OnMouseMove(x, y int) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetEnabled sets enable on all clickable widgets of this group
|
||||
func (wg *WidgetGroup) SetEnabled(enabled bool) {
|
||||
for _, entry := range wg.entries {
|
||||
if v, ok := entry.(ClickableWidget); ok {
|
||||
v.SetEnabled(enabled)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,8 +219,8 @@ func NewGameControls(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
helpOverlay := NewHelpOverlay(asset, renderer, ui, guiManager, l, keyMap)
|
||||
hud := NewHUD(asset, ui, hero, helpOverlay, miniPanel, actionableRegions, mapEngine, l, mapRenderer)
|
||||
helpOverlay := NewHelpOverlay(asset, ui, l, keyMap)
|
||||
hud := NewHUD(asset, ui, hero, miniPanel, actionableRegions, mapEngine, l, mapRenderer)
|
||||
|
||||
const blackAlpha50percent = 0x0000007f
|
||||
|
||||
@ -270,7 +270,8 @@ func NewGameControls(
|
||||
gc.inventory.SetOnCloseCb(gc.onCloseInventory)
|
||||
gc.skilltree.SetOnCloseCb(gc.onCloseSkilltree)
|
||||
|
||||
gc.escapeMenu.SetOnCloseCb(gc.hud.restoreMinipanelFromTempClose)
|
||||
gc.escapeMenu.SetOnCloseCb(gc.hud.miniPanel.restoreDisabled)
|
||||
gc.HelpOverlay.SetOnCloseCb(gc.hud.miniPanel.restoreDisabled)
|
||||
|
||||
err = gc.bindTerminalCommands(term)
|
||||
if err != nil {
|
||||
@ -397,6 +398,8 @@ func (g *GameControls) OnKeyDown(event d2interface.KeyEvent) bool {
|
||||
case d2enum.HoldRun:
|
||||
g.hud.onToggleRunButton(true)
|
||||
case d2enum.ToggleHelpScreen:
|
||||
g.hud.miniPanel.openDisabled()
|
||||
|
||||
g.HelpOverlay.Toggle()
|
||||
g.updateLayout()
|
||||
default:
|
||||
@ -646,7 +649,7 @@ func (g *GameControls) openEscMenu() {
|
||||
g.inventory.Close()
|
||||
g.skilltree.Close()
|
||||
g.heroStatsPanel.Close()
|
||||
g.hud.closeMinipanelTemporary()
|
||||
g.hud.miniPanel.closeDisabled()
|
||||
g.escapeMenu.open()
|
||||
g.updateLayout()
|
||||
}
|
||||
@ -671,6 +674,7 @@ func (g *GameControls) Load() {
|
||||
// Advance advances the state of the GameControls
|
||||
func (g *GameControls) Advance(elapsed float64) error {
|
||||
g.mapRenderer.Advance(elapsed)
|
||||
g.hud.Advance(elapsed)
|
||||
|
||||
if err := g.escapeMenu.Advance(elapsed); err != nil {
|
||||
return err
|
||||
|
@ -1,11 +1,13 @@
|
||||
package d2player
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||
)
|
||||
|
||||
@ -30,11 +32,20 @@ const (
|
||||
manaStatusOffsetY = -12
|
||||
|
||||
manaGlobeScreenOffsetX = 117
|
||||
|
||||
hpLabelX = 15
|
||||
hpLabelY = 487
|
||||
|
||||
manaLabelX = 785
|
||||
manaLabelY = 487
|
||||
)
|
||||
|
||||
// static check that globeWidget implements Widget
|
||||
var _ d2ui.Widget = &globeWidget{}
|
||||
|
||||
// static check that globeWidget implements ClickableWidget
|
||||
var _ d2ui.ClickableWidget = &globeWidget{}
|
||||
|
||||
type globeFrame struct {
|
||||
sprite *d2ui.Sprite
|
||||
offsetX int
|
||||
@ -53,14 +64,18 @@ func (gf *globeFrame) setPosition(x, y int) {
|
||||
gf.sprite.SetPosition(x+gf.offsetX, y+gf.offsetY)
|
||||
}
|
||||
|
||||
func (gf *globeFrame) getSize() (x, y int) {
|
||||
w, h := gf.sprite.GetSize()
|
||||
return w + gf.offsetX, h + gf.offsetY
|
||||
}
|
||||
|
||||
func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value *int, l d2util.LogLevel, valueMax *int) *globeWidget {
|
||||
func newGlobeWidget(ui *d2ui.UIManager,
|
||||
asset *d2asset.AssetManager,
|
||||
x, y int,
|
||||
gtype globeType,
|
||||
value *int, valueMax *int,
|
||||
l d2util.LogLevel) *globeWidget {
|
||||
var globe, overlap *globeFrame
|
||||
|
||||
var tooltipX, tooltipY int
|
||||
|
||||
var tooltipTrans string
|
||||
|
||||
base := d2ui.NewBaseWidget(ui)
|
||||
base.SetPosition(x, y)
|
||||
|
||||
@ -75,6 +90,8 @@ func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value *int, l
|
||||
offsetY: globeSpriteOffsetY,
|
||||
idx: frameHealthStatus,
|
||||
}
|
||||
tooltipX, tooltipY = hpLabelX, hpLabelY
|
||||
tooltipTrans = "panelhealth"
|
||||
} else if gtype == typeManaGlobe {
|
||||
globe = &globeFrame{
|
||||
offsetX: manaStatusOffsetX,
|
||||
@ -86,16 +103,35 @@ func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value *int, l
|
||||
offsetY: rightGlobeOffsetY,
|
||||
idx: frameRightGlobe,
|
||||
}
|
||||
tooltipX, tooltipY = manaLabelX, manaLabelY
|
||||
tooltipTrans = "panelmana"
|
||||
}
|
||||
|
||||
gw := &globeWidget{
|
||||
BaseWidget: base,
|
||||
value: value,
|
||||
valueMax: valueMax,
|
||||
globe: globe,
|
||||
overlap: overlap,
|
||||
BaseWidget: base,
|
||||
asset: asset,
|
||||
value: value,
|
||||
valueMax: valueMax,
|
||||
globe: globe,
|
||||
overlap: overlap,
|
||||
isTooltipLocked: false,
|
||||
tooltipX: tooltipX,
|
||||
tooltipY: tooltipY,
|
||||
tooltipTrans: tooltipTrans,
|
||||
}
|
||||
|
||||
gw.OnHoverStart(func() {
|
||||
if !gw.isTooltipLocked {
|
||||
gw.tooltip.SetVisible(true)
|
||||
}
|
||||
})
|
||||
|
||||
gw.OnHoverEnd(func() {
|
||||
if !gw.isTooltipLocked {
|
||||
gw.tooltip.SetVisible(false)
|
||||
}
|
||||
})
|
||||
|
||||
gw.logger = d2util.NewLogger()
|
||||
gw.logger.SetLevel(l)
|
||||
gw.logger.SetPrefix(logPrefix)
|
||||
@ -105,11 +141,19 @@ func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value *int, l
|
||||
|
||||
type globeWidget struct {
|
||||
*d2ui.BaseWidget
|
||||
asset *d2asset.AssetManager
|
||||
value *int
|
||||
valueMax *int
|
||||
globe *globeFrame
|
||||
overlap *globeFrame
|
||||
logger *d2util.Logger
|
||||
|
||||
pressed bool
|
||||
isTooltipLocked bool
|
||||
tooltip *d2ui.Tooltip
|
||||
tooltipX int
|
||||
tooltipY int
|
||||
tooltipTrans string
|
||||
}
|
||||
|
||||
func (g *globeWidget) load() {
|
||||
@ -128,6 +172,11 @@ func (g *globeWidget) load() {
|
||||
}
|
||||
|
||||
g.overlap.setFrameIndex()
|
||||
|
||||
// tooltip
|
||||
g.tooltip = g.GetManager().NewTooltip(d2resource.Font16, d2resource.PaletteUnits, d2ui.TooltipXLeft, d2ui.TooltipYTop)
|
||||
g.tooltip.SetPosition(g.tooltipX, g.tooltipY)
|
||||
g.tooltip.SetBoxEnabled(false)
|
||||
}
|
||||
|
||||
// Render draws the widget to the screen
|
||||
@ -144,10 +193,49 @@ func (g *globeWidget) Render(target d2interface.Surface) {
|
||||
g.overlap.sprite.Render(target)
|
||||
}
|
||||
|
||||
func (g *globeWidget) GetSize() (x, y int) {
|
||||
return g.overlap.getSize()
|
||||
// Contains is special here as the point of origin is at the lower left corner
|
||||
// in contrast to any other element which is top left.
|
||||
func (g *globeWidget) Contains(px, py int) bool {
|
||||
wx, wy := g.globe.sprite.GetPosition()
|
||||
width, height := g.globe.sprite.GetSize()
|
||||
|
||||
return px >= wx && px <= wx+width && py <= wy && py >= wy-height
|
||||
}
|
||||
|
||||
func (g *globeWidget) updateTooltip() {
|
||||
// Create and format string from string lookup table.
|
||||
fmtStr := g.asset.TranslateString(g.tooltipTrans)
|
||||
strPanel := fmt.Sprintf(fmtStr, *g.value, *g.valueMax)
|
||||
g.tooltip.SetText(strPanel)
|
||||
}
|
||||
|
||||
func (g *globeWidget) Advance(elapsed float64) error {
|
||||
g.updateTooltip()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *globeWidget) Activate() {
|
||||
g.isTooltipLocked = !g.isTooltipLocked
|
||||
g.tooltip.SetVisible(g.isTooltipLocked)
|
||||
}
|
||||
|
||||
func (g *globeWidget) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *globeWidget) SetEnabled(enable bool) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
func (g *globeWidget) GetPressed() bool {
|
||||
return g.pressed
|
||||
}
|
||||
|
||||
func (g *globeWidget) SetPressed(pressed bool) {
|
||||
g.pressed = pressed
|
||||
}
|
||||
|
||||
func (g *globeWidget) OnActivated(callback func()) {
|
||||
// No-op
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||
)
|
||||
|
||||
@ -159,18 +158,14 @@ const (
|
||||
// NewHelpOverlay creates a new HelpOverlay instance
|
||||
func NewHelpOverlay(
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
ui *d2ui.UIManager,
|
||||
guiManager *d2gui.GuiManager,
|
||||
l d2util.LogLevel,
|
||||
keyMap *KeyMap,
|
||||
) *HelpOverlay {
|
||||
h := &HelpOverlay{
|
||||
asset: asset,
|
||||
renderer: renderer,
|
||||
uiManager: ui,
|
||||
guiManager: guiManager,
|
||||
keyMap: keyMap,
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
keyMap: keyMap,
|
||||
}
|
||||
|
||||
h.logger = d2util.NewLogger()
|
||||
@ -182,17 +177,17 @@ func NewHelpOverlay(
|
||||
|
||||
// HelpOverlay represents the in-game overlay that toggles visibility when the h key is pressed
|
||||
type HelpOverlay struct {
|
||||
asset *d2asset.AssetManager
|
||||
isOpen bool
|
||||
renderer d2interface.Renderer
|
||||
frames []*d2ui.Sprite
|
||||
text []*d2ui.Label
|
||||
lines []line
|
||||
uiManager *d2ui.UIManager
|
||||
layout *d2gui.Layout
|
||||
closeButton *d2ui.Button
|
||||
guiManager *d2gui.GuiManager
|
||||
keyMap *KeyMap
|
||||
asset *d2asset.AssetManager
|
||||
isOpen bool
|
||||
frames []*d2ui.Sprite
|
||||
text []*d2ui.Label
|
||||
lines []line
|
||||
uiManager *d2ui.UIManager
|
||||
closeButton *d2ui.Button
|
||||
keyMap *KeyMap
|
||||
onCloseCb func()
|
||||
panelGroup *d2ui.WidgetGroup
|
||||
backgroundWidget *d2ui.CustomWidget
|
||||
|
||||
logger *d2util.Logger
|
||||
}
|
||||
@ -211,20 +206,18 @@ func (h *HelpOverlay) Toggle() {
|
||||
// Close will hide the help overlay
|
||||
func (h *HelpOverlay) Close() {
|
||||
h.isOpen = false
|
||||
h.closeButton.SetVisible(false)
|
||||
h.guiManager.SetLayout(nil)
|
||||
h.panelGroup.SetVisible(false)
|
||||
h.onCloseCb()
|
||||
}
|
||||
|
||||
// SetOnCloseCb sets the callback run when Close() is called
|
||||
func (h *HelpOverlay) SetOnCloseCb(cb func()) {
|
||||
h.onCloseCb = cb
|
||||
}
|
||||
|
||||
func (h *HelpOverlay) open() {
|
||||
h.isOpen = true
|
||||
if h.layout == nil {
|
||||
h.layout = d2gui.CreateLayout(h.renderer, d2gui.PositionTypeHorizontal, h.asset)
|
||||
}
|
||||
|
||||
h.closeButton.SetVisible(true)
|
||||
h.closeButton.SetPressed(false)
|
||||
|
||||
h.guiManager.SetLayout(h.layout)
|
||||
h.panelGroup.SetVisible(true)
|
||||
}
|
||||
|
||||
// IsOpen returns whether or not the overlay is visible/open
|
||||
@ -234,22 +227,21 @@ func (h *HelpOverlay) IsOpen() bool {
|
||||
|
||||
// IsInRect checks if the given point is within the overlay layout rectangle
|
||||
func (h *HelpOverlay) IsInRect(px, py int) bool {
|
||||
ww, hh := h.layout.GetSize()
|
||||
x, y := h.layout.GetPosition()
|
||||
|
||||
if px >= x && px <= x+ww && py >= y && py <= y+hh {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return h.panelGroup.Contains(px, py)
|
||||
}
|
||||
|
||||
// Load the overlay graphical assets
|
||||
func (h *HelpOverlay) Load() {
|
||||
h.panelGroup = h.uiManager.NewWidgetGroup(d2ui.RenderPriorityHelpPanel)
|
||||
|
||||
h.setupOverlayFrame()
|
||||
h.setupTitleAndButton()
|
||||
h.setupBulletedList()
|
||||
h.setupLabelsWithLines()
|
||||
|
||||
h.backgroundWidget = h.uiManager.NewCustomWidgetCached(h.Render, screenWidth, screenHeight)
|
||||
h.panelGroup.AddWidget(h.backgroundWidget)
|
||||
h.panelGroup.SetVisible(false)
|
||||
}
|
||||
|
||||
func (h *HelpOverlay) setupOverlayFrame() {
|
||||
@ -330,6 +322,8 @@ func (h *HelpOverlay) setupTitleAndButton() {
|
||||
h.closeButton.SetPosition(closeButtonX, closeButtonY)
|
||||
h.closeButton.SetVisible(false)
|
||||
h.closeButton.OnActivated(func() { h.Close() })
|
||||
h.closeButton.SetRenderPriority(d2ui.RenderPriorityForeground)
|
||||
h.panelGroup.AddWidget(h.closeButton)
|
||||
|
||||
newLabel = h.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
||||
newLabel.SetText(h.asset.TranslateString("strClose")) // "Close"
|
||||
@ -621,11 +615,7 @@ func (h *HelpOverlay) createCallout(c callout) {
|
||||
}
|
||||
|
||||
// Render the overlay to the given surface
|
||||
func (h *HelpOverlay) Render(target d2interface.Surface) error {
|
||||
if !h.isOpen {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HelpOverlay) Render(target d2interface.Surface) {
|
||||
for _, f := range h.frames {
|
||||
f.Render(target)
|
||||
}
|
||||
@ -639,6 +629,4 @@ func (h *HelpOverlay) Render(target d2interface.Surface) error {
|
||||
target.DrawLine(l.MoveX, l.MoveY, l.Color)
|
||||
target.Pop()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -35,16 +35,6 @@ const (
|
||||
percentStaminaBarLow = 0.25
|
||||
)
|
||||
|
||||
const (
|
||||
hpLabelX = 15
|
||||
hpLabelY = 487
|
||||
|
||||
manaLabelX = 785
|
||||
manaLabelY = 487
|
||||
|
||||
staminaExperienceY = 535
|
||||
)
|
||||
|
||||
const (
|
||||
frameHealthStatus = 0
|
||||
frameManaStatus = 1
|
||||
@ -57,8 +47,9 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
staminaBarOffsetX = 273
|
||||
staminaBarOffsetY = 572
|
||||
staminaBarOffsetX = 273
|
||||
staminaBarOffsetY = 572
|
||||
staminaExperienceY = 535
|
||||
|
||||
experienceBarOffsetX = 256
|
||||
experienceBarOffsetY = 561
|
||||
@ -68,6 +59,9 @@ const (
|
||||
|
||||
miniPanelButtonOffsetX = -8
|
||||
miniPanelButtonOffsetY = -38
|
||||
|
||||
miniPanelTooltipOffsetX = 7
|
||||
miniPanelTooltipOffsetY = -14
|
||||
)
|
||||
|
||||
const (
|
||||
@ -81,7 +75,6 @@ type HUD struct {
|
||||
actionableRegions []actionableRegion
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
help *HelpOverlay
|
||||
mapEngine *d2mapengine.MapEngine
|
||||
mapRenderer *d2maprenderer.MapRenderer
|
||||
lastMouseX int
|
||||
@ -89,14 +82,12 @@ type HUD struct {
|
||||
hero *d2mapentity.Player
|
||||
mainPanel *d2ui.Sprite
|
||||
globeSprite *d2ui.Sprite
|
||||
menuButton *d2ui.Button
|
||||
hpManaStatusSprite *d2ui.Sprite
|
||||
leftSkillResource *SkillResource
|
||||
rightSkillResource *SkillResource
|
||||
runButton *d2ui.Button
|
||||
zoneChangeText *d2ui.Label
|
||||
miniPanel *miniPanel
|
||||
isMiniPanelOpen bool
|
||||
isZoneTextShown bool
|
||||
hpStatsIsVisible bool
|
||||
manaStatsIsVisible bool
|
||||
@ -104,9 +95,6 @@ type HUD struct {
|
||||
staminaTooltip *d2ui.Tooltip
|
||||
runWalkTooltip *d2ui.Tooltip
|
||||
experienceTooltip *d2ui.Tooltip
|
||||
healthTooltip *d2ui.Tooltip
|
||||
manaTooltip *d2ui.Tooltip
|
||||
miniPanelTooltip *d2ui.Tooltip
|
||||
nameLabel *d2ui.Label
|
||||
healthGlobe *globeWidget
|
||||
manaGlobe *globeWidget
|
||||
@ -115,6 +103,7 @@ type HUD struct {
|
||||
widgetLeftSkill *d2ui.CustomWidget
|
||||
widgetRightSkill *d2ui.CustomWidget
|
||||
panelBackground *d2ui.CustomWidget
|
||||
panelGroup *d2ui.WidgetGroup
|
||||
logger *d2util.Logger
|
||||
}
|
||||
|
||||
@ -123,7 +112,6 @@ func NewHUD(
|
||||
asset *d2asset.AssetManager,
|
||||
ui *d2ui.UIManager,
|
||||
hero *d2mapentity.Player,
|
||||
help *HelpOverlay,
|
||||
miniPanel *miniPanel,
|
||||
actionableRegions []actionableRegion,
|
||||
mapEngine *d2mapengine.MapEngine,
|
||||
@ -137,14 +125,21 @@ func NewHUD(
|
||||
zoneLabel := ui.NewLabel(d2resource.Font30, d2resource.PaletteUnits)
|
||||
zoneLabel.Alignment = d2ui.HorizontalAlignCenter
|
||||
|
||||
healthGlobe := newGlobeWidget(ui, 0, screenHeight, typeHealthGlobe, &hero.Stats.Health, l, &hero.Stats.MaxHealth)
|
||||
manaGlobe := newGlobeWidget(ui, screenWidth-manaGlobeScreenOffsetX, screenHeight, typeManaGlobe, &hero.Stats.Mana, l, &hero.Stats.MaxMana)
|
||||
healthGlobe := newGlobeWidget(ui, asset,
|
||||
0, screenHeight,
|
||||
typeHealthGlobe,
|
||||
&hero.Stats.Health, &hero.Stats.MaxHealth,
|
||||
l)
|
||||
manaGlobe := newGlobeWidget(ui, asset,
|
||||
screenWidth-manaGlobeScreenOffsetX, screenHeight,
|
||||
typeManaGlobe,
|
||||
&hero.Stats.Mana, &hero.Stats.MaxMana,
|
||||
l)
|
||||
|
||||
hud := &HUD{
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
hero: hero,
|
||||
help: help,
|
||||
mapEngine: mapEngine,
|
||||
mapRenderer: mapRenderer,
|
||||
miniPanel: miniPanel,
|
||||
@ -165,15 +160,24 @@ func NewHUD(
|
||||
|
||||
// Load creates the ui elemets
|
||||
func (h *HUD) Load() {
|
||||
h.panelGroup = h.uiManager.NewWidgetGroup(d2ui.RenderPriorityHUDPanel)
|
||||
|
||||
h.loadSprites()
|
||||
|
||||
h.healthGlobe.load()
|
||||
h.manaGlobe.load()
|
||||
h.healthGlobe.SetRenderPriority(d2ui.RenderPriorityForeground)
|
||||
h.panelGroup.AddWidget(h.healthGlobe)
|
||||
|
||||
h.manaGlobe.load()
|
||||
h.manaGlobe.SetRenderPriority(d2ui.RenderPriorityForeground)
|
||||
h.panelGroup.AddWidget(h.manaGlobe)
|
||||
|
||||
h.loadTooltips()
|
||||
h.loadSkillResources()
|
||||
h.loadCustomWidgets()
|
||||
h.loadUIButtons()
|
||||
h.loadTooltips()
|
||||
|
||||
h.panelGroup.SetVisible(true)
|
||||
}
|
||||
|
||||
func (h *HUD) loadCustomWidgets() {
|
||||
@ -186,13 +190,19 @@ func (h *HUD) loadCustomWidgets() {
|
||||
|
||||
h.panelBackground = h.uiManager.NewCustomWidgetCached(h.renderPanelStatic, screenWidth, height)
|
||||
h.panelBackground.SetPosition(0, screenHeight-height)
|
||||
h.panelGroup.AddWidget(h.panelBackground)
|
||||
|
||||
// stamina bar
|
||||
h.widgetStamina = h.uiManager.NewCustomWidget(h.renderStaminaBar, staminaBarWidth, staminaBarHeight)
|
||||
h.widgetStamina.SetPosition(staminaBarOffsetX, staminaBarOffsetY)
|
||||
h.widgetStamina.SetTooltip(h.staminaTooltip)
|
||||
h.panelGroup.AddWidget(h.widgetStamina)
|
||||
|
||||
// experience bar
|
||||
h.widgetExperience = h.uiManager.NewCustomWidget(h.renderExperienceBar, expBarWidth, expBarHeight)
|
||||
h.widgetExperience.SetPosition(experienceBarOffsetX, experienceBarOffsetY)
|
||||
h.widgetExperience.SetTooltip(h.experienceTooltip)
|
||||
h.panelGroup.AddWidget(h.widgetExperience)
|
||||
|
||||
// Left skill widget
|
||||
leftRenderFunc := func(target d2interface.Surface) {
|
||||
@ -202,6 +212,7 @@ func (h *HUD) loadCustomWidgets() {
|
||||
|
||||
h.widgetLeftSkill = h.uiManager.NewCustomWidget(leftRenderFunc, skillIconWidth, skillIconHeight)
|
||||
h.widgetLeftSkill.SetPosition(leftSkillX, screenHeight)
|
||||
h.panelGroup.AddWidget(h.widgetLeftSkill)
|
||||
|
||||
// Right skill widget
|
||||
rightRenderFunc := func(target d2interface.Surface) {
|
||||
@ -211,6 +222,7 @@ func (h *HUD) loadCustomWidgets() {
|
||||
|
||||
h.widgetRightSkill = h.uiManager.NewCustomWidget(rightRenderFunc, skillIconWidth, skillIconHeight)
|
||||
h.widgetRightSkill.SetPosition(rightSkillX, screenHeight)
|
||||
h.panelGroup.AddWidget(h.widgetRightSkill)
|
||||
}
|
||||
|
||||
func (h *HUD) loadSkillResources() {
|
||||
@ -297,42 +309,31 @@ func (h *HUD) loadTooltips() {
|
||||
labelX = centerX
|
||||
labelY = staminaExperienceY - halfLabelHeight
|
||||
h.experienceTooltip.SetPosition(labelX, labelY)
|
||||
|
||||
// Health tooltip
|
||||
h.healthTooltip = h.uiManager.NewTooltip(d2resource.Font16, d2resource.PaletteUnits, d2ui.TooltipXLeft, d2ui.TooltipYTop)
|
||||
h.healthTooltip.SetPosition(hpLabelX, hpLabelY)
|
||||
h.healthTooltip.SetBoxEnabled(false)
|
||||
|
||||
// Health tooltip
|
||||
h.manaTooltip = h.uiManager.NewTooltip(d2resource.Font16, d2resource.PaletteUnits, d2ui.TooltipXLeft, d2ui.TooltipYTop)
|
||||
h.manaTooltip.SetPosition(manaLabelX, manaLabelY)
|
||||
h.manaTooltip.SetBoxEnabled(false)
|
||||
|
||||
// minipanel tooltip
|
||||
h.miniPanelTooltip = h.uiManager.NewTooltip(d2resource.Font16, d2resource.PaletteUnits, d2ui.TooltipXCenter, d2ui.TooltipYTop)
|
||||
}
|
||||
|
||||
func (h *HUD) loadUIButtons() {
|
||||
// Run button
|
||||
h.runButton = h.uiManager.NewButton(d2ui.ButtonTypeRun, "")
|
||||
|
||||
h.runButton.SetPosition(runButtonX, runButtonY)
|
||||
h.runButton.OnActivated(func() { h.onToggleRunButton(false) })
|
||||
h.runButton.SetTooltip(h.runWalkTooltip)
|
||||
h.updateRunTooltipText()
|
||||
h.panelGroup.AddWidget(h.runButton)
|
||||
|
||||
if h.hero.IsRunToggled() {
|
||||
h.runButton.Toggle()
|
||||
}
|
||||
}
|
||||
|
||||
// minipanel button
|
||||
h.menuButton = h.uiManager.NewButton(d2ui.ButtonTypeMinipanelOpenClose, "")
|
||||
//nolint:golint,gomnd // 2 is not a magic number
|
||||
x := screenWidth/2 + miniPanelButtonOffsetX
|
||||
y := screenHeight + miniPanelButtonOffsetY
|
||||
h.menuButton.SetPosition(x, y)
|
||||
h.menuButton.OnActivated(func() {
|
||||
h.menuButton.Toggle()
|
||||
h.miniPanel.Toggle()
|
||||
})
|
||||
func (h *HUD) updateRunTooltipText() {
|
||||
var stringTableKey string
|
||||
if h.hero.IsRunToggled() {
|
||||
stringTableKey = "RunOff"
|
||||
} else {
|
||||
stringTableKey = "RunOn"
|
||||
}
|
||||
|
||||
h.runWalkTooltip.SetText(h.asset.TranslateString(stringTableKey))
|
||||
}
|
||||
|
||||
func (h *HUD) onToggleRunButton(noButton bool) {
|
||||
@ -341,6 +342,7 @@ func (h *HUD) onToggleRunButton(noButton bool) {
|
||||
}
|
||||
|
||||
h.hero.ToggleRunWalk()
|
||||
h.updateRunTooltipText()
|
||||
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/800
|
||||
h.hero.SetIsRunning(h.hero.IsRunToggled())
|
||||
@ -527,87 +529,16 @@ func (h *HUD) renderNewSkillsButton(x, _ int, target d2interface.Surface) error
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint:golint,dupl // we clean this up later
|
||||
func (h *HUD) renderHealthTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
// Create and format Health string from string lookup table.
|
||||
fmtHealth := h.asset.TranslateString("panelhealth")
|
||||
healthCurr, healthMax := h.hero.Stats.Health, h.hero.Stats.MaxHealth
|
||||
strPanelHealth := fmt.Sprintf(fmtHealth, healthCurr, healthMax)
|
||||
|
||||
// Display current hp and mana stats hpGlobe or manaGlobe region is clicked
|
||||
if !(h.actionableRegions[hpGlobe].rect.IsInRect(mx, my) || h.hpStatsIsVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
h.healthTooltip.SetText(strPanelHealth)
|
||||
h.healthTooltip.Render(target)
|
||||
}
|
||||
|
||||
//nolint:golint,dupl // we clean this up later
|
||||
func (h *HUD) renderManaTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
// Create and format Mana string from string lookup table.
|
||||
fmtMana := h.asset.TranslateString("panelmana")
|
||||
manaCurr, manaMax := h.hero.Stats.Mana, h.hero.Stats.MaxMana
|
||||
strPanelMana := fmt.Sprintf(fmtMana, manaCurr, manaMax)
|
||||
|
||||
if !(h.actionableRegions[manaGlobe].rect.IsInRect(mx, my) || h.manaStatsIsVisible) {
|
||||
return
|
||||
}
|
||||
|
||||
h.manaTooltip.SetText(strPanelMana)
|
||||
h.manaTooltip.Render(target)
|
||||
}
|
||||
|
||||
func (h *HUD) renderRunWalkTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
// Display run/walk tooltip when hovered.
|
||||
// Note that whether the player is walking or running, the tooltip is the same in Diablo 2.
|
||||
if !h.actionableRegions[walkRun].rect.IsInRect(mx, my) {
|
||||
return
|
||||
}
|
||||
|
||||
var stringTableKey string
|
||||
|
||||
if h.hero.IsRunToggled() {
|
||||
stringTableKey = "RunOff"
|
||||
} else {
|
||||
stringTableKey = "RunOn"
|
||||
}
|
||||
|
||||
h.runWalkTooltip.SetText(h.asset.TranslateString(stringTableKey))
|
||||
h.runWalkTooltip.Render(target)
|
||||
}
|
||||
|
||||
func (h *HUD) renderStaminaTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
// Display stamina tooltip when hovered.
|
||||
if !h.actionableRegions[stamina].rect.IsInRect(mx, my) {
|
||||
return
|
||||
}
|
||||
|
||||
func (h *HUD) setStaminaTooltipText() {
|
||||
// Create and format Stamina string from string lookup table.
|
||||
fmtStamina := h.asset.TranslateString("panelstamina")
|
||||
staminaCurr, staminaMax := int(h.hero.Stats.Stamina), h.hero.Stats.MaxStamina
|
||||
strPanelStamina := fmt.Sprintf(fmtStamina, staminaCurr, staminaMax)
|
||||
|
||||
h.staminaTooltip.SetText(strPanelStamina)
|
||||
h.staminaTooltip.Render(target)
|
||||
}
|
||||
|
||||
func (h *HUD) renderExperienceTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
// Display experience tooltip when hovered.
|
||||
if !h.actionableRegions[xp].rect.IsInRect(mx, my) {
|
||||
return
|
||||
}
|
||||
|
||||
func (h *HUD) setExperienceTooltipText() {
|
||||
// Create and format Experience string from string lookup table.
|
||||
fmtExp := h.asset.TranslateString("panelexp")
|
||||
|
||||
@ -621,7 +552,6 @@ func (h *HUD) renderExperienceTooltip(target d2interface.Surface) {
|
||||
strPanelExp := fmt.Sprintf(fmtExp, expCurr, expMax)
|
||||
|
||||
h.experienceTooltip.SetText(strPanelExp)
|
||||
h.experienceTooltip.Render(target)
|
||||
}
|
||||
|
||||
func (h *HUD) renderForSelectableEntitiesHovered(target d2interface.Surface) {
|
||||
@ -666,30 +596,11 @@ func (h *HUD) renderForSelectableEntitiesHovered(target d2interface.Surface) {
|
||||
func (h *HUD) Render(target d2interface.Surface) error {
|
||||
h.renderForSelectableEntitiesHovered(target)
|
||||
|
||||
h.panelBackground.Render(target)
|
||||
|
||||
h.healthGlobe.Render(target)
|
||||
h.widgetLeftSkill.Render(target)
|
||||
h.widgetRightSkill.Render(target)
|
||||
h.manaGlobe.Render(target)
|
||||
h.widgetStamina.Render(target)
|
||||
h.widgetExperience.Render(target)
|
||||
|
||||
if err := h.help.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.isZoneTextShown {
|
||||
h.zoneChangeText.SetPosition(zoneChangeTextX, zoneChangeTextY)
|
||||
h.zoneChangeText.Render(target)
|
||||
}
|
||||
|
||||
h.renderHealthTooltip(target)
|
||||
h.renderManaTooltip(target)
|
||||
h.renderRunWalkTooltip(target)
|
||||
h.renderStaminaTooltip(target)
|
||||
h.renderExperienceTooltip(target)
|
||||
|
||||
if h.skillSelectMenu.IsOpen() {
|
||||
h.skillSelectMenu.Render(target)
|
||||
}
|
||||
@ -717,6 +628,21 @@ func (h *HUD) getSkillResourceByClass(class string) string {
|
||||
return entry
|
||||
}
|
||||
|
||||
// Advance updates syncs data on widgets that might have changed. I.e. the current stamina value
|
||||
// in the stamina tooltip
|
||||
func (h *HUD) Advance(elapsed float64) {
|
||||
h.setStaminaTooltipText()
|
||||
h.setExperienceTooltipText()
|
||||
|
||||
if err := h.healthGlobe.Advance(elapsed); err != nil {
|
||||
h.logger.Error(err.Error())
|
||||
}
|
||||
|
||||
if err := h.manaGlobe.Advance(elapsed); err != nil {
|
||||
h.logger.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// OnMouseMove handles mouse move events
|
||||
func (h *HUD) OnMouseMove(event d2interface.MouseMoveEvent) bool {
|
||||
mx, my := event.X(), event.Y()
|
||||
@ -728,20 +654,3 @@ func (h *HUD) OnMouseMove(event d2interface.MouseMoveEvent) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *HUD) closeMinipanelTemporary() {
|
||||
h.isMiniPanelOpen = h.miniPanel.IsOpen()
|
||||
if h.isMiniPanelOpen {
|
||||
h.menuButton.SetEnabled(false)
|
||||
h.menuButton.Toggle()
|
||||
h.miniPanel.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HUD) restoreMinipanelFromTempClose() {
|
||||
if h.isMiniPanelOpen {
|
||||
h.menuButton.SetEnabled(true)
|
||||
h.menuButton.Toggle()
|
||||
h.miniPanel.Open()
|
||||
}
|
||||
}
|
||||
|
@ -59,16 +59,21 @@ func newMiniPanel(asset *d2asset.AssetManager,
|
||||
}
|
||||
|
||||
type miniPanel struct {
|
||||
ui *d2ui.UIManager
|
||||
asset *d2asset.AssetManager
|
||||
container *d2ui.Sprite
|
||||
sprite *d2ui.Sprite
|
||||
isOpen bool
|
||||
isSinglePlayer bool
|
||||
movedLeft bool
|
||||
movedRight bool
|
||||
panelGroup *d2ui.WidgetGroup
|
||||
tooltipGroup *d2ui.WidgetGroup
|
||||
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
|
||||
}
|
||||
@ -91,8 +96,11 @@ func (m *miniPanel) createWidgets(actions *miniPanelActions) {
|
||||
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
|
||||
@ -114,6 +122,14 @@ func (m *miniPanel) createWidgets(actions *miniPanelActions) {
|
||||
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())
|
||||
@ -181,7 +197,21 @@ func (m *miniPanel) createWidgets(actions *miniPanelActions) {
|
||||
m.panelGroup.AddWidget(btn)
|
||||
}
|
||||
|
||||
m.panelGroup.SetVisible(false)
|
||||
//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 {
|
||||
@ -197,10 +227,28 @@ func (m *miniPanel) createButton(content miniPanelContent, x, y, buttonHeight in
|
||||
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
|
||||
}
|
||||
@ -214,12 +262,24 @@ func (m *miniPanel) Toggle() {
|
||||
}
|
||||
|
||||
func (m *miniPanel) Open() {
|
||||
m.panelGroup.SetVisible(true)
|
||||
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
|
||||
}
|
||||
|
||||
@ -234,7 +294,6 @@ func (m *miniPanel) moveRight() {
|
||||
|
||||
func (m *miniPanel) undoMoveRight() {
|
||||
m.panelGroup.OffsetPosition(-panelOffsetRight, 0)
|
||||
m.tooltipGroup.OffsetPosition(-panelOffsetRight, 0)
|
||||
}
|
||||
|
||||
func (m *miniPanel) moveLeft() {
|
||||
@ -258,7 +317,7 @@ func (m *miniPanel) SetMovedLeft(moveLeft bool) {
|
||||
m.panelGroup.SetVisible(false)
|
||||
} else {
|
||||
m.moveRight()
|
||||
m.panelGroup.SetVisible(true)
|
||||
m.panelGroup.SetVisible(m.isOpen)
|
||||
}
|
||||
} else {
|
||||
if moveLeft {
|
||||
@ -282,7 +341,7 @@ func (m *miniPanel) SetMovedRight(moveRight bool) {
|
||||
m.panelGroup.SetVisible(false)
|
||||
} else {
|
||||
m.moveLeft()
|
||||
m.panelGroup.SetVisible(true)
|
||||
m.panelGroup.SetVisible(m.isOpen)
|
||||
}
|
||||
} else {
|
||||
if moveRight {
|
||||
@ -294,3 +353,51 @@ func (m *miniPanel) SetMovedRight(moveRight bool) {
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user