mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-27 05:35:57 -04:00
1f49df62d1
* 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
242 lines
5.2 KiB
Go
242 lines
5.2 KiB
Go
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"
|
|
)
|
|
|
|
type globeType = int
|
|
|
|
const (
|
|
typeHealthGlobe globeType = iota
|
|
typeManaGlobe
|
|
)
|
|
|
|
const (
|
|
globeHeight = 80
|
|
globeWidth = 80
|
|
|
|
globeSpriteOffsetX = 28
|
|
globeSpriteOffsetY = -5
|
|
|
|
healthStatusOffsetX = 30
|
|
healthStatusOffsetY = -13
|
|
|
|
manaStatusOffsetX = 7
|
|
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
|
|
offsetY int
|
|
idx int
|
|
gw *globeWidget
|
|
}
|
|
|
|
func (gf *globeFrame) setFrameIndex() {
|
|
if err := gf.sprite.SetCurrentFrame(gf.idx); err != nil {
|
|
gf.gw.logger.Error(err.Error())
|
|
}
|
|
}
|
|
|
|
func (gf *globeFrame) setPosition(x, y int) {
|
|
gf.sprite.SetPosition(x+gf.offsetX, y+gf.offsetY)
|
|
}
|
|
|
|
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)
|
|
|
|
if gtype == typeHealthGlobe {
|
|
globe = &globeFrame{
|
|
offsetX: healthStatusOffsetX,
|
|
offsetY: healthStatusOffsetY,
|
|
idx: frameHealthStatus,
|
|
}
|
|
overlap = &globeFrame{
|
|
offsetX: globeSpriteOffsetX,
|
|
offsetY: globeSpriteOffsetY,
|
|
idx: frameHealthStatus,
|
|
}
|
|
tooltipX, tooltipY = hpLabelX, hpLabelY
|
|
tooltipTrans = "panelhealth"
|
|
} else if gtype == typeManaGlobe {
|
|
globe = &globeFrame{
|
|
offsetX: manaStatusOffsetX,
|
|
offsetY: manaStatusOffsetY,
|
|
idx: frameManaStatus,
|
|
}
|
|
overlap = &globeFrame{
|
|
offsetX: rightGlobeOffsetX,
|
|
offsetY: rightGlobeOffsetY,
|
|
idx: frameRightGlobe,
|
|
}
|
|
tooltipX, tooltipY = manaLabelX, manaLabelY
|
|
tooltipTrans = "panelmana"
|
|
}
|
|
|
|
gw := &globeWidget{
|
|
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)
|
|
|
|
return gw
|
|
}
|
|
|
|
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() {
|
|
var err error
|
|
|
|
g.globe.sprite, err = g.GetManager().NewSprite(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
|
if err != nil {
|
|
g.logger.Error(err.Error())
|
|
}
|
|
|
|
g.globe.setFrameIndex()
|
|
|
|
g.overlap.sprite, err = g.GetManager().NewSprite(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
|
if err != nil {
|
|
g.logger.Error(err.Error())
|
|
}
|
|
|
|
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
|
|
func (g *globeWidget) Render(target d2interface.Surface) {
|
|
valuePercent := float64(*g.value) / float64(*g.valueMax)
|
|
barHeight := int(valuePercent * float64(globeHeight))
|
|
|
|
maskRect := image.Rect(0, globeHeight-barHeight, globeWidth, globeHeight)
|
|
|
|
g.globe.setPosition(g.GetPosition())
|
|
g.globe.sprite.RenderSection(target, maskRect)
|
|
|
|
g.overlap.setPosition(g.GetPosition())
|
|
g.overlap.sprite.Render(target)
|
|
}
|
|
|
|
// 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
|
|
}
|