mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 07:37:48 -05:00
Ui panel refactor part 2 (#921)
* d2ui/skilltree: Don't render availSPLabel this is handled by the ui_manager now. * d2ui/custom_widget: Allow them to be cached into static images * d2player/hero_stats_panel: Remove render() function from game_controls all ui elements are now grouped into a WidgetGroup, thus rendering is done by the ui manager. * d2player/hero_stats_panel: Remove unnecessary widgets from struct we don't need to store them in the HeroStatsPanel struct anymore as they are completly handled by the uiManager. * d2ui/widget_group: Remove priority member this is already defined by the BaseWidget. * d2ui/widget: Move uiManager.contains() to the baseWidgets this method makes more sense on a widget anyways. * d2ui/widget: Add methods to handle widget hovering * d2ui/custom_widget: Require define width/height since the custom render() method can do whatever, we need the user to specify the width/height such that GetSize() calls are meaningful. * d2ui/widget: Allow widgets to return the uiManager * d2player/HUD: Refactor health/mana globe into its own widget * d2player/hud: Refactor load() seperate each type of loading into its own method. * d2player/HUD: Move stamina/exp bar into widgets * d2player/HUD: Refactor left/right skills into widget * d2ui/custom_widget: cached custom widgets should use widget.x/y since we render to an image, we use widget.x/y to position the cached image. * d2player/HUD: User cached custom widget for all static images
This commit is contained in:
parent
0d691dbffa
commit
12821147ce
@ -9,11 +9,29 @@ var _ Widget = &CustomWidget{}
|
|||||||
type CustomWidget struct {
|
type CustomWidget struct {
|
||||||
*BaseWidget
|
*BaseWidget
|
||||||
renderFunc func(target d2interface.Surface)
|
renderFunc func(target d2interface.Surface)
|
||||||
|
cached bool
|
||||||
|
cachedImg *d2interface.Surface
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCustomWidgetCached creates a new widget and caches anything rendered via the
|
||||||
|
// renderFunc into a static image to be displayed
|
||||||
|
func (ui *UIManager) NewCustomWidgetCached(renderFunc func(target d2interface.Surface), width, height int) *CustomWidget {
|
||||||
|
c := ui.NewCustomWidget(renderFunc, width, height)
|
||||||
|
c.cached = true
|
||||||
|
|
||||||
|
// render using the renderFunc to a cache
|
||||||
|
surface := ui.Renderer().NewSurface(width, height)
|
||||||
|
c.cachedImg = &surface
|
||||||
|
renderFunc(*c.cachedImg)
|
||||||
|
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCustomWidget creates a new widget with custom render function
|
// NewCustomWidget creates a new widget with custom render function
|
||||||
func (ui *UIManager) NewCustomWidget(renderFunc func(target d2interface.Surface)) *CustomWidget {
|
func (ui *UIManager) NewCustomWidget(renderFunc func(target d2interface.Surface), width, height int) *CustomWidget {
|
||||||
base := NewBaseWidget(ui)
|
base := NewBaseWidget(ui)
|
||||||
|
base.width = width
|
||||||
|
base.height = height
|
||||||
|
|
||||||
return &CustomWidget{
|
return &CustomWidget{
|
||||||
BaseWidget: base,
|
BaseWidget: base,
|
||||||
@ -23,7 +41,13 @@ func (ui *UIManager) NewCustomWidget(renderFunc func(target d2interface.Surface)
|
|||||||
|
|
||||||
// Render draws the custom widget
|
// Render draws the custom widget
|
||||||
func (c *CustomWidget) Render(target d2interface.Surface) {
|
func (c *CustomWidget) Render(target d2interface.Surface) {
|
||||||
|
if c.cached {
|
||||||
|
target.PushTranslation(c.GetPosition())
|
||||||
|
target.Render(*c.cachedImg)
|
||||||
|
target.Pop()
|
||||||
|
} else {
|
||||||
c.renderFunc(target)
|
c.renderFunc(target)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance is a no-op
|
// Advance is a no-op
|
||||||
|
@ -54,8 +54,9 @@ func (ui *UIManager) Reset() {
|
|||||||
// addWidgetGroup adds a widgetGroup to the UI manager and sorts by priority
|
// addWidgetGroup adds a widgetGroup to the UI manager and sorts by priority
|
||||||
func (ui *UIManager) addWidgetGroup(group *WidgetGroup) {
|
func (ui *UIManager) addWidgetGroup(group *WidgetGroup) {
|
||||||
ui.widgetsGroups = append(ui.widgetsGroups, group)
|
ui.widgetsGroups = append(ui.widgetsGroups, group)
|
||||||
|
|
||||||
sort.SliceStable(ui.widgetsGroups, func(i, j int) bool {
|
sort.SliceStable(ui.widgetsGroups, func(i, j int) bool {
|
||||||
return ui.widgetsGroups[i].priority < ui.widgetsGroups[j].priority
|
return ui.widgetsGroups[i].renderPriority < ui.widgetsGroups[j].renderPriority
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +84,7 @@ func (ui *UIManager) OnMouseButtonUp(event d2interface.MouseEvent) bool {
|
|||||||
// activate previously pressed widget if cursor is still hovering
|
// activate previously pressed widget if cursor is still hovering
|
||||||
w := ui.pressedWidget
|
w := ui.pressedWidget
|
||||||
|
|
||||||
if w != nil && ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
if w != nil && w.Contains(ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
||||||
w.Activate()
|
w.Activate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +97,17 @@ func (ui *UIManager) OnMouseButtonUp(event d2interface.MouseEvent) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnMouseMove is the mouse move event handler
|
||||||
|
func (ui *UIManager) OnMouseMove(event d2interface.MouseMoveEvent) bool {
|
||||||
|
for _, w := range ui.widgetsGroups {
|
||||||
|
if w.GetVisible() {
|
||||||
|
w.OnMouseMove(event.X(), event.Y())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// OnMouseButtonDown is the mouse button down event handler
|
// OnMouseButtonDown is the mouse button down event handler
|
||||||
func (ui *UIManager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
func (ui *UIManager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
||||||
ui.CursorX, ui.CursorY = event.X(), event.Y()
|
ui.CursorX, ui.CursorY = event.X(), event.Y()
|
||||||
@ -103,7 +115,7 @@ func (ui *UIManager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
|||||||
// find and press a widget on screen
|
// find and press a widget on screen
|
||||||
ui.pressedWidget = nil
|
ui.pressedWidget = nil
|
||||||
for _, w := range ui.clickableWidgets {
|
for _, w := range ui.clickableWidgets {
|
||||||
if ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
if w.Contains(ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
||||||
w.SetPressed(true)
|
w.SetPressed(true)
|
||||||
ui.pressedWidget = w
|
ui.pressedWidget = w
|
||||||
ui.clickSfx.Play()
|
ui.clickSfx.Play()
|
||||||
@ -135,14 +147,6 @@ func (ui *UIManager) Render(target d2interface.Surface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// Advance updates all of the UI elements
|
||||||
func (ui *UIManager) Advance(elapsed float64) {
|
func (ui *UIManager) Advance(elapsed float64) {
|
||||||
for _, widget := range ui.widgets {
|
for _, widget := range ui.widgets {
|
||||||
|
@ -11,6 +11,8 @@ const (
|
|||||||
RenderPrioritySkilltree
|
RenderPrioritySkilltree
|
||||||
// RenderPrioritySkilltreeIcon is the priority for the skilltree icons
|
// RenderPrioritySkilltreeIcon is the priority for the skilltree icons
|
||||||
RenderPrioritySkilltreeIcon
|
RenderPrioritySkilltreeIcon
|
||||||
|
// RenderPriorityHeroStatsPanel is the priority for the hero_stats_panel
|
||||||
|
RenderPriorityHeroStatsPanel
|
||||||
// RenderPriorityForeground is the last element drawn
|
// RenderPriorityForeground is the last element drawn
|
||||||
RenderPriorityForeground
|
RenderPriorityForeground
|
||||||
)
|
)
|
||||||
@ -19,6 +21,13 @@ const (
|
|||||||
type Widget interface {
|
type Widget interface {
|
||||||
Drawable
|
Drawable
|
||||||
bindManager(ui *UIManager)
|
bindManager(ui *UIManager)
|
||||||
|
GetManager() (ui *UIManager)
|
||||||
|
OnHoverStart(callback func())
|
||||||
|
OnHoverEnd(callback func())
|
||||||
|
isHovered() bool
|
||||||
|
hoverStart()
|
||||||
|
hoverEnd()
|
||||||
|
Contains(x, y int) (contained bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClickableWidget defines an object that can be clicked
|
// ClickableWidget defines an object that can be clicked
|
||||||
@ -41,6 +50,10 @@ type BaseWidget struct {
|
|||||||
height int
|
height int
|
||||||
renderPriority RenderPriority
|
renderPriority RenderPriority
|
||||||
visible bool
|
visible bool
|
||||||
|
|
||||||
|
hovered bool
|
||||||
|
onHoverStartCb func()
|
||||||
|
onHoverEndCb func()
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBaseWidget creates a new BaseWidget with defaults
|
// NewBaseWidget creates a new BaseWidget with defaults
|
||||||
@ -100,3 +113,46 @@ func (b *BaseWidget) GetRenderPriority() (prio RenderPriority) {
|
|||||||
func (b *BaseWidget) SetRenderPriority(prio RenderPriority) {
|
func (b *BaseWidget) SetRenderPriority(prio RenderPriority) {
|
||||||
b.renderPriority = prio
|
b.renderPriority = prio
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnHoverStart sets a function that is called if the hovering of the widget starts
|
||||||
|
func (b *BaseWidget) OnHoverStart(callback func()) {
|
||||||
|
b.onHoverStartCb = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
// HoverStart is called when the hovering of the widget starts
|
||||||
|
func (b *BaseWidget) hoverStart() {
|
||||||
|
b.hovered = true
|
||||||
|
if b.onHoverStartCb != nil {
|
||||||
|
b.onHoverStartCb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnHoverEnd sets a function that is called if the hovering of the widget ends
|
||||||
|
func (b *BaseWidget) OnHoverEnd(callback func()) {
|
||||||
|
b.onHoverEndCb = callback
|
||||||
|
}
|
||||||
|
|
||||||
|
// hoverEnd is called when the widget hovering ends
|
||||||
|
func (b *BaseWidget) hoverEnd() {
|
||||||
|
b.hovered = false
|
||||||
|
if b.onHoverEndCb != nil {
|
||||||
|
b.onHoverEndCb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseWidget) isHovered() bool {
|
||||||
|
return b.hovered
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains determines whether a given x,y coordinate lands within a Widget
|
||||||
|
func (b *BaseWidget) Contains(x, y int) bool {
|
||||||
|
wx, wy := b.GetPosition()
|
||||||
|
ww, wh := b.GetSize()
|
||||||
|
|
||||||
|
return x >= wx && x <= wx+ww && y >= wy && y <= wy+wh
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetManager returns the uiManager
|
||||||
|
func (b *BaseWidget) GetManager() (ui *UIManager) {
|
||||||
|
return b.manager
|
||||||
|
}
|
||||||
|
@ -14,7 +14,6 @@ var _ Widget = &WidgetGroup{}
|
|||||||
type WidgetGroup struct {
|
type WidgetGroup struct {
|
||||||
*BaseWidget
|
*BaseWidget
|
||||||
entries []Widget
|
entries []Widget
|
||||||
priority RenderPriority
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWidgetGroup creates a new widget group
|
// NewWidgetGroup creates a new widget group
|
||||||
@ -85,3 +84,16 @@ func (wg *WidgetGroup) SetVisible(visible bool) {
|
|||||||
entry.SetVisible(visible)
|
entry.SetVisible(visible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnMouseMove handles mouse move events
|
||||||
|
func (wg *WidgetGroup) OnMouseMove(x, y int) {
|
||||||
|
for _, entry := range wg.entries {
|
||||||
|
if entry.Contains(x, y) && entry.GetVisible() {
|
||||||
|
if !entry.isHovered() {
|
||||||
|
entry.hoverStart()
|
||||||
|
}
|
||||||
|
} else if entry.isHovered() {
|
||||||
|
entry.hoverEnd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -57,7 +57,7 @@ const (
|
|||||||
leftSkillX,
|
leftSkillX,
|
||||||
leftSkillY,
|
leftSkillY,
|
||||||
leftSkillWidth,
|
leftSkillWidth,
|
||||||
leftSkillHeight = 115, 550, 50, 50
|
leftSkillHeight = 117, 550, 50, 50
|
||||||
|
|
||||||
newStatsX,
|
newStatsX,
|
||||||
newStatsY,
|
newStatsY,
|
||||||
@ -92,7 +92,7 @@ const (
|
|||||||
rightSkillX,
|
rightSkillX,
|
||||||
rightSkillY,
|
rightSkillY,
|
||||||
rightSkillWidth,
|
rightSkillWidth,
|
||||||
rightSkillHeight = 634, 550, 50, 50
|
rightSkillHeight = 635, 550, 50, 50
|
||||||
|
|
||||||
hpGlobeX,
|
hpGlobeX,
|
||||||
hpGlobeY,
|
hpGlobeY,
|
||||||
@ -783,7 +783,6 @@ func (g *GameControls) Render(target d2interface.Surface) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameControls) renderPanels(target d2interface.Surface) error {
|
func (g *GameControls) renderPanels(target d2interface.Surface) error {
|
||||||
g.heroStatsPanel.Render(target)
|
|
||||||
g.inventory.Render(target)
|
g.inventory.Render(target)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
145
d2game/d2player/globeWidget.go
Normal file
145
d2game/d2player/globeWidget.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package d2player
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||||
|
"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
|
||||||
|
)
|
||||||
|
|
||||||
|
// static check that globeWidget implements Widget
|
||||||
|
var _ d2ui.Widget = &globeWidget{}
|
||||||
|
|
||||||
|
type globeFrame struct {
|
||||||
|
sprite *d2ui.Sprite
|
||||||
|
offsetX int
|
||||||
|
offsetY int
|
||||||
|
idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gf *globeFrame) setFrameIndex() {
|
||||||
|
if err := gf.sprite.SetCurrentFrame(gf.idx); err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
type globeWidget struct {
|
||||||
|
*d2ui.BaseWidget
|
||||||
|
value *int
|
||||||
|
valueMax *int
|
||||||
|
globe *globeFrame
|
||||||
|
overlap *globeFrame
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGlobeWidget(ui *d2ui.UIManager, x, y int, gtype globeType, value, valueMax *int) *globeWidget {
|
||||||
|
var globe, overlap *globeFrame
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
} else if gtype == typeManaGlobe {
|
||||||
|
globe = &globeFrame{
|
||||||
|
offsetX: manaStatusOffsetX,
|
||||||
|
offsetY: manaStatusOffsetY,
|
||||||
|
idx: frameManaStatus,
|
||||||
|
}
|
||||||
|
overlap = &globeFrame{
|
||||||
|
offsetX: rightGlobeOffsetX,
|
||||||
|
offsetY: rightGlobeOffsetY,
|
||||||
|
idx: frameRightGlobe,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &globeWidget{
|
||||||
|
BaseWidget: base,
|
||||||
|
value: value,
|
||||||
|
valueMax: valueMax,
|
||||||
|
globe: globe,
|
||||||
|
overlap: overlap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *globeWidget) load() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
g.globe.sprite, err = g.GetManager().NewSprite(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.globe.setFrameIndex()
|
||||||
|
|
||||||
|
g.overlap.sprite, err = g.GetManager().NewSprite(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.overlap.setFrameIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *globeWidget) GetSize() (x, y int) {
|
||||||
|
return g.overlap.getSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *globeWidget) Advance(elapsed float64) error {
|
||||||
|
return nil
|
||||||
|
}
|
@ -86,16 +86,13 @@ type StatsPanelLabels struct {
|
|||||||
type HeroStatsPanel struct {
|
type HeroStatsPanel struct {
|
||||||
asset *d2asset.AssetManager
|
asset *d2asset.AssetManager
|
||||||
uiManager *d2ui.UIManager
|
uiManager *d2ui.UIManager
|
||||||
frame *d2ui.UIFrame
|
|
||||||
panel *d2ui.Sprite
|
panel *d2ui.Sprite
|
||||||
heroState *d2hero.HeroStatsState
|
heroState *d2hero.HeroStatsState
|
||||||
heroName string
|
heroName string
|
||||||
heroClass d2enum.Hero
|
heroClass d2enum.Hero
|
||||||
renderer d2interface.Renderer
|
|
||||||
staticMenuImageCache *d2interface.Surface
|
|
||||||
labels *StatsPanelLabels
|
labels *StatsPanelLabels
|
||||||
closeButton *d2ui.Button
|
|
||||||
onCloseCb func()
|
onCloseCb func()
|
||||||
|
panelGroup *d2ui.WidgetGroup
|
||||||
|
|
||||||
originX int
|
originX int
|
||||||
originY int
|
originY int
|
||||||
@ -111,7 +108,6 @@ func NewHeroStatsPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, heroName
|
|||||||
return &HeroStatsPanel{
|
return &HeroStatsPanel{
|
||||||
asset: asset,
|
asset: asset,
|
||||||
uiManager: ui,
|
uiManager: ui,
|
||||||
renderer: ui.Renderer(),
|
|
||||||
originX: originX,
|
originX: originX,
|
||||||
originY: originY,
|
originY: originY,
|
||||||
heroState: heroState,
|
heroState: heroState,
|
||||||
@ -125,19 +121,30 @@ func NewHeroStatsPanel(asset *d2asset.AssetManager, ui *d2ui.UIManager, heroName
|
|||||||
func (s *HeroStatsPanel) Load() {
|
func (s *HeroStatsPanel) Load() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
s.frame = d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
|
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPriorityHeroStatsPanel)
|
||||||
|
|
||||||
s.closeButton = s.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
|
frame := d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameLeft)
|
||||||
s.closeButton.SetVisible(false)
|
s.panelGroup.AddWidget(frame)
|
||||||
s.closeButton.SetPosition(heroStatsCloseButtonX, heroStatsCloseButtonY)
|
|
||||||
s.closeButton.OnActivated(func() { s.Close() })
|
|
||||||
|
|
||||||
s.panel, err = s.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
s.panel, err = s.uiManager.NewSprite(d2resource.InventoryCharacterPanel, d2resource.PaletteSky)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fw, fh := frame.GetFrameBounds()
|
||||||
|
fc := frame.GetFrameCount()
|
||||||
|
w, h := fw*fc, fh*fc
|
||||||
|
staticPanel := s.uiManager.NewCustomWidgetCached(s.renderStaticMenu, w, h)
|
||||||
|
s.panelGroup.AddWidget(staticPanel)
|
||||||
|
|
||||||
|
closeButton := s.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
|
||||||
|
closeButton.SetVisible(false)
|
||||||
|
closeButton.SetPosition(heroStatsCloseButtonX, heroStatsCloseButtonY)
|
||||||
|
closeButton.OnActivated(func() { s.Close() })
|
||||||
|
s.panelGroup.AddWidget(closeButton)
|
||||||
|
|
||||||
s.initStatValueLabels()
|
s.initStatValueLabels()
|
||||||
|
s.panelGroup.SetVisible(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsOpen returns true if the hero status panel is open
|
// IsOpen returns true if the hero status panel is open
|
||||||
@ -157,13 +164,13 @@ func (s *HeroStatsPanel) Toggle() {
|
|||||||
// Open opens the hero status panel
|
// Open opens the hero status panel
|
||||||
func (s *HeroStatsPanel) Open() {
|
func (s *HeroStatsPanel) Open() {
|
||||||
s.isOpen = true
|
s.isOpen = true
|
||||||
s.closeButton.SetVisible(true)
|
s.panelGroup.SetVisible(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closed the hero status panel
|
// Close closed the hero status panel
|
||||||
func (s *HeroStatsPanel) Close() {
|
func (s *HeroStatsPanel) Close() {
|
||||||
s.isOpen = false
|
s.isOpen = false
|
||||||
s.closeButton.SetVisible(false)
|
s.panelGroup.SetVisible(false)
|
||||||
s.onCloseCb()
|
s.onCloseCb()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,43 +179,21 @@ func (s *HeroStatsPanel) SetOnCloseCb(cb func()) {
|
|||||||
s.onCloseCb = cb
|
s.onCloseCb = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render renders the hero status panel
|
// Advance updates labels on the panel
|
||||||
func (s *HeroStatsPanel) Render(target d2interface.Surface) {
|
func (s *HeroStatsPanel) Advance(elapsed float64) {
|
||||||
if !s.isOpen {
|
if !s.isOpen {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.staticMenuImageCache == nil {
|
s.setStatValues()
|
||||||
frameWidth, frameHeight := s.frame.GetFrameBounds()
|
|
||||||
framesCount := s.frame.GetFrameCount()
|
|
||||||
surface := s.renderer.NewSurface(frameWidth*framesCount, frameHeight*framesCount)
|
|
||||||
|
|
||||||
s.staticMenuImageCache = &surface
|
|
||||||
|
|
||||||
err := s.renderStaticMenu(*s.staticMenuImageCache)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
target.Render(*s.staticMenuImageCache)
|
|
||||||
|
|
||||||
s.renderStatValues(target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
|
func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) {
|
||||||
if err := s.renderStaticPanelFrames(target); err != nil {
|
s.renderStaticPanelFrames(target)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.renderStaticLabels(target)
|
s.renderStaticLabels(target)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) error {
|
func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) {
|
||||||
s.frame.Render(target)
|
|
||||||
|
|
||||||
frames := []int{
|
frames := []int{
|
||||||
statsPanelTopLeft,
|
statsPanelTopLeft,
|
||||||
statsPanelTopRight,
|
statsPanelTopRight,
|
||||||
@ -221,7 +206,7 @@ func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) err
|
|||||||
|
|
||||||
for _, frameIndex := range frames {
|
for _, frameIndex := range frames {
|
||||||
if err := s.panel.SetCurrentFrame(frameIndex); err != nil {
|
if err := s.panel.SetCurrentFrame(frameIndex); err != nil {
|
||||||
return err
|
log.Printf("%e", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w, h := s.panel.GetCurrentFrameSize()
|
w, h := s.panel.GetCurrentFrameSize()
|
||||||
@ -241,8 +226,6 @@ func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) err
|
|||||||
|
|
||||||
s.panel.Render(target)
|
s.panel.Render(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HeroStatsPanel) renderStaticLabels(target d2interface.Surface) {
|
func (s *HeroStatsPanel) renderStaticLabels(target d2interface.Surface) {
|
||||||
@ -322,30 +305,24 @@ func (s *HeroStatsPanel) initStatValueLabels() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HeroStatsPanel) renderStatValues(target d2interface.Surface) {
|
func (s *HeroStatsPanel) setStatValues() {
|
||||||
s.renderStatValueNum(s.labels.Level, s.heroState.Level, target)
|
s.labels.Level.SetText(strconv.Itoa(s.heroState.Level))
|
||||||
s.renderStatValueNum(s.labels.Experience, s.heroState.Experience, target)
|
s.labels.Experience.SetText(strconv.Itoa(s.heroState.Experience))
|
||||||
s.renderStatValueNum(s.labels.NextLevelExp, s.heroState.NextLevelExp, target)
|
s.labels.NextLevelExp.SetText(strconv.Itoa(s.heroState.NextLevelExp))
|
||||||
|
|
||||||
s.renderStatValueNum(s.labels.Strength, s.heroState.Strength, target)
|
s.labels.Strength.SetText(strconv.Itoa(s.heroState.Strength))
|
||||||
s.renderStatValueNum(s.labels.Dexterity, s.heroState.Dexterity, target)
|
s.labels.Dexterity.SetText(strconv.Itoa(s.heroState.Dexterity))
|
||||||
s.renderStatValueNum(s.labels.Vitality, s.heroState.Vitality, target)
|
s.labels.Vitality.SetText(strconv.Itoa(s.heroState.Vitality))
|
||||||
s.renderStatValueNum(s.labels.Energy, s.heroState.Energy, target)
|
s.labels.Energy.SetText(strconv.Itoa(s.heroState.Energy))
|
||||||
|
|
||||||
s.renderStatValueNum(s.labels.MaxHealth, s.heroState.MaxHealth, target)
|
s.labels.MaxHealth.SetText(strconv.Itoa(s.heroState.MaxHealth))
|
||||||
s.renderStatValueNum(s.labels.Health, s.heroState.Health, target)
|
s.labels.Health.SetText(strconv.Itoa(s.heroState.Health))
|
||||||
|
|
||||||
s.renderStatValueNum(s.labels.MaxStamina, s.heroState.MaxStamina, target)
|
s.labels.MaxStamina.SetText(strconv.Itoa(s.heroState.MaxStamina))
|
||||||
s.renderStatValueNum(s.labels.Stamina, int(s.heroState.Stamina), target)
|
s.labels.Stamina.SetText(strconv.Itoa(int(s.heroState.Stamina)))
|
||||||
|
|
||||||
s.renderStatValueNum(s.labels.MaxMana, s.heroState.MaxMana, target)
|
s.labels.MaxMana.SetText(strconv.Itoa(s.heroState.MaxMana))
|
||||||
s.renderStatValueNum(s.labels.Mana, s.heroState.Mana, target)
|
s.labels.Mana.SetText(strconv.Itoa(s.heroState.Mana))
|
||||||
}
|
|
||||||
|
|
||||||
func (s *HeroStatsPanel) renderStatValueNum(label *d2ui.Label, value int,
|
|
||||||
target d2interface.Surface) {
|
|
||||||
label.SetText(strconv.Itoa(value))
|
|
||||||
label.Render(target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HeroStatsPanel) createStatValueLabel(stat, x, y int) *d2ui.Label {
|
func (s *HeroStatsPanel) createStatValueLabel(stat, x, y int) *d2ui.Label {
|
||||||
@ -361,6 +338,7 @@ func (s *HeroStatsPanel) createTextLabel(element PanelText) *d2ui.Label {
|
|||||||
|
|
||||||
label.SetText(element.Text)
|
label.SetText(element.Text)
|
||||||
label.SetPosition(element.X, element.Y)
|
label.SetPosition(element.X, element.Y)
|
||||||
|
s.panelGroup.AddWidget(label)
|
||||||
|
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package d2player
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
@ -30,10 +29,9 @@ const (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
expBarWidth = 120.0
|
expBarWidth = 120.0
|
||||||
|
expBarHeight = 4
|
||||||
staminaBarWidth = 102.0
|
staminaBarWidth = 102.0
|
||||||
staminaBarHeight = 19.0
|
staminaBarHeight = 19.0
|
||||||
globeHeight = 80
|
|
||||||
globeWidth = 80
|
|
||||||
hoverLabelOuterPad = 5
|
hoverLabelOuterPad = 5
|
||||||
percentStaminaBarLow = 0.25
|
percentStaminaBarLow = 0.25
|
||||||
)
|
)
|
||||||
@ -61,15 +59,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
manaStatusOffsetX = 7
|
|
||||||
manaStatusOffsetY = -12
|
|
||||||
|
|
||||||
healthStatusOffsetX = 30
|
|
||||||
healthStatusOffsetY = -13
|
|
||||||
|
|
||||||
globeSpriteOffsetX = 28
|
|
||||||
globeSpriteOffsetY = -5
|
|
||||||
|
|
||||||
staminaBarOffsetX = 273
|
staminaBarOffsetX = 273
|
||||||
staminaBarOffsetY = 572
|
staminaBarOffsetY = 572
|
||||||
|
|
||||||
@ -120,6 +109,13 @@ type HUD struct {
|
|||||||
manaTooltip *d2ui.Tooltip
|
manaTooltip *d2ui.Tooltip
|
||||||
miniPanelTooltip *d2ui.Tooltip
|
miniPanelTooltip *d2ui.Tooltip
|
||||||
nameLabel *d2ui.Label
|
nameLabel *d2ui.Label
|
||||||
|
healthGlobe *globeWidget
|
||||||
|
manaGlobe *globeWidget
|
||||||
|
widgetStamina *d2ui.CustomWidget
|
||||||
|
widgetExperience *d2ui.CustomWidget
|
||||||
|
widgetLeftSkill *d2ui.CustomWidget
|
||||||
|
widgetRightSkill *d2ui.CustomWidget
|
||||||
|
panelBackground *d2ui.CustomWidget
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHUD creates a HUD object
|
// NewHUD creates a HUD object
|
||||||
@ -140,6 +136,9 @@ func NewHUD(
|
|||||||
zoneLabel := ui.NewLabel(d2resource.Font30, d2resource.PaletteUnits)
|
zoneLabel := ui.NewLabel(d2resource.Font30, d2resource.PaletteUnits)
|
||||||
zoneLabel.Alignment = d2ui.HorizontalAlignCenter
|
zoneLabel.Alignment = d2ui.HorizontalAlignCenter
|
||||||
|
|
||||||
|
healthGlobe := newGlobeWidget(ui, 0, screenHeight, typeHealthGlobe, &hero.Stats.Health, &hero.Stats.MaxHealth)
|
||||||
|
manaGlobe := newGlobeWidget(ui, screenWidth-manaGlobeScreenOffsetX, screenHeight, typeManaGlobe, &hero.Stats.Mana, &hero.Stats.MaxMana)
|
||||||
|
|
||||||
return &HUD{
|
return &HUD{
|
||||||
asset: asset,
|
asset: asset,
|
||||||
uiManager: ui,
|
uiManager: ui,
|
||||||
@ -152,11 +151,84 @@ func NewHUD(
|
|||||||
nameLabel: nameLabel,
|
nameLabel: nameLabel,
|
||||||
skillSelectMenu: NewSkillSelectMenu(asset, ui, hero),
|
skillSelectMenu: NewSkillSelectMenu(asset, ui, hero),
|
||||||
zoneChangeText: zoneLabel,
|
zoneChangeText: zoneLabel,
|
||||||
|
healthGlobe: healthGlobe,
|
||||||
|
manaGlobe: manaGlobe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load creates the ui elemets
|
// Load creates the ui elemets
|
||||||
func (h *HUD) Load() {
|
func (h *HUD) Load() {
|
||||||
|
h.loadSprites()
|
||||||
|
|
||||||
|
h.healthGlobe.load()
|
||||||
|
h.manaGlobe.load()
|
||||||
|
|
||||||
|
h.loadSkillResources()
|
||||||
|
h.loadCustomWidgets()
|
||||||
|
h.loadUIButtons()
|
||||||
|
h.loadTooltips()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HUD) loadCustomWidgets() {
|
||||||
|
// static background
|
||||||
|
_, height, err := h.mainPanel.GetFrameSize(0) // health globe is the frame with max height
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h.panelBackground = h.uiManager.NewCustomWidgetCached(h.renderPanelStatic, screenWidth, height)
|
||||||
|
h.panelBackground.SetPosition(0, screenHeight-height)
|
||||||
|
|
||||||
|
// stamina bar
|
||||||
|
h.widgetStamina = h.uiManager.NewCustomWidget(h.renderStaminaBar, staminaBarWidth, staminaBarHeight)
|
||||||
|
h.widgetStamina.SetPosition(staminaBarOffsetX, staminaBarOffsetY)
|
||||||
|
|
||||||
|
// experience bar
|
||||||
|
h.widgetExperience = h.uiManager.NewCustomWidget(h.renderExperienceBar, expBarWidth, expBarHeight)
|
||||||
|
|
||||||
|
// Left skill widget
|
||||||
|
leftRenderFunc := func(target d2interface.Surface) {
|
||||||
|
x, y := h.widgetLeftSkill.GetPosition()
|
||||||
|
h.renderLeftSkill(x, y, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.widgetLeftSkill = h.uiManager.NewCustomWidget(leftRenderFunc, skillIconWidth, skillIconHeight)
|
||||||
|
h.widgetLeftSkill.SetPosition(leftSkillX, screenHeight)
|
||||||
|
|
||||||
|
// Right skill widget
|
||||||
|
rightRenderFunc := func(target d2interface.Surface) {
|
||||||
|
x, y := h.widgetRightSkill.GetPosition()
|
||||||
|
h.renderRightSkill(x, y, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
h.widgetRightSkill = h.uiManager.NewCustomWidget(rightRenderFunc, skillIconWidth, skillIconHeight)
|
||||||
|
h.widgetRightSkill.SetPosition(rightSkillX, screenHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HUD) loadSkillResources() {
|
||||||
|
// https://github.com/OpenDiablo2/OpenDiablo2/issues/799
|
||||||
|
genericSkillsSprite, err := h.uiManager.NewSprite(d2resource.GenericSkills, d2resource.PaletteSky)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
attackIconID := 2
|
||||||
|
|
||||||
|
h.leftSkillResource = &SkillResource{
|
||||||
|
SkillIcon: genericSkillsSprite,
|
||||||
|
IconNumber: attackIconID,
|
||||||
|
SkillResourcePath: d2resource.GenericSkills,
|
||||||
|
}
|
||||||
|
|
||||||
|
h.rightSkillResource = &SkillResource{
|
||||||
|
SkillIcon: genericSkillsSprite,
|
||||||
|
IconNumber: attackIconID,
|
||||||
|
SkillResourcePath: d2resource.GenericSkills,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *HUD) loadSprites() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
h.globeSprite, err = h.uiManager.NewSprite(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
h.globeSprite, err = h.uiManager.NewSprite(d2resource.GameGlobeOverlap, d2resource.PaletteSky)
|
||||||
@ -183,29 +255,6 @@ func (h *HUD) Load() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/799
|
|
||||||
genericSkillsSprite, err := h.uiManager.NewSprite(d2resource.GenericSkills, d2resource.PaletteSky)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
attackIconID := 2
|
|
||||||
|
|
||||||
h.leftSkillResource = &SkillResource{
|
|
||||||
SkillIcon: genericSkillsSprite,
|
|
||||||
IconNumber: attackIconID,
|
|
||||||
SkillResourcePath: d2resource.GenericSkills,
|
|
||||||
}
|
|
||||||
|
|
||||||
h.rightSkillResource = &SkillResource{
|
|
||||||
SkillIcon: genericSkillsSprite,
|
|
||||||
IconNumber: attackIconID,
|
|
||||||
SkillResourcePath: d2resource.GenericSkills,
|
|
||||||
}
|
|
||||||
|
|
||||||
h.loadUIButtons()
|
|
||||||
h.loadTooltips()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) loadTooltips() {
|
func (h *HUD) loadTooltips() {
|
||||||
@ -292,35 +341,23 @@ func (h *HUD) onToggleRunButton(noButton bool) {
|
|||||||
// NOTE: the positioning of all of the panel elements is coupled to the rendering order :(
|
// NOTE: the positioning of all of the panel elements is coupled to the rendering order :(
|
||||||
// don't change the order in which the render methods are called, as there is an x,y offset
|
// don't change the order in which the render methods are called, as there is an x,y offset
|
||||||
// that is updated between render calls
|
// that is updated between render calls
|
||||||
func (h *HUD) renderGameControlPanelElements(target d2interface.Surface) error {
|
func (h *HUD) renderPanelStatic(target d2interface.Surface) {
|
||||||
_, height := target.GetSize()
|
_, height := target.GetSize()
|
||||||
offsetX, offsetY := 0, 0
|
offsetX, offsetY := 0, height
|
||||||
|
|
||||||
// Main panel background
|
// Main panel background
|
||||||
offsetY = height
|
|
||||||
if err := h.renderPanel(offsetX, offsetY, target); err != nil {
|
if err := h.renderPanel(offsetX, offsetY, target); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
}
|
return
|
||||||
|
|
||||||
// Health globe
|
|
||||||
w, _ := h.mainPanel.GetCurrentFrameSize()
|
|
||||||
|
|
||||||
if err := h.renderHealthGlobe(offsetX, offsetY, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Left Skill
|
|
||||||
offsetX += w
|
|
||||||
if err := h.renderLeftSkill(offsetX, offsetY, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New Stats Button
|
// New Stats Button
|
||||||
w, _ = h.leftSkillResource.SkillIcon.GetCurrentFrameSize()
|
w, _ := h.mainPanel.GetCurrentFrameSize()
|
||||||
offsetX += w
|
offsetX += w + skillIconWidth
|
||||||
|
|
||||||
if err := h.renderNewStatsButton(offsetX, offsetY, target); err != nil {
|
if err := h.renderNewStatsButton(offsetX, offsetY, target); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stamina
|
// Stamina
|
||||||
@ -328,30 +365,17 @@ func (h *HUD) renderGameControlPanelElements(target d2interface.Surface) error {
|
|||||||
offsetX += w
|
offsetX += w
|
||||||
|
|
||||||
if err := h.renderStamina(offsetX, offsetY, target); err != nil {
|
if err := h.renderStamina(offsetX, offsetY, target); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
}
|
return
|
||||||
|
|
||||||
// Stamina status bar
|
|
||||||
w, _ = h.mainPanel.GetCurrentFrameSize()
|
|
||||||
offsetX += w
|
|
||||||
|
|
||||||
if err := h.renderStaminaBar(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Experience status bar
|
|
||||||
if err := h.renderExperienceBar(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mini Panel and button
|
|
||||||
if err := h.renderMiniPanel(target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Potions
|
// Potions
|
||||||
|
w, _ = h.mainPanel.GetCurrentFrameSize()
|
||||||
|
offsetX += w
|
||||||
|
|
||||||
if err := h.renderPotions(offsetX, offsetY, target); err != nil {
|
if err := h.renderPotions(offsetX, offsetY, target); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// New Skills Button
|
// New Skills Button
|
||||||
@ -359,87 +383,21 @@ func (h *HUD) renderGameControlPanelElements(target d2interface.Surface) error {
|
|||||||
offsetX += w
|
offsetX += w
|
||||||
|
|
||||||
if err := h.renderNewSkillsButton(offsetX, offsetY, target); err != nil {
|
if err := h.renderNewSkillsButton(offsetX, offsetY, target); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right skill
|
// Empty Mana Globe
|
||||||
w, _ = h.mainPanel.GetCurrentFrameSize()
|
w, _ = h.mainPanel.GetCurrentFrameSize()
|
||||||
offsetX += w
|
offsetX += w + skillIconWidth
|
||||||
|
|
||||||
if err := h.renderRightSkill(offsetX, offsetY, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mana Globe
|
|
||||||
w, _ = h.rightSkillResource.SkillIcon.GetCurrentFrameSize()
|
|
||||||
offsetX += w
|
|
||||||
|
|
||||||
if err := h.renderManaGlobe(offsetX, offsetY, target); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HUD) renderManaGlobe(x, _ int, target d2interface.Surface) error {
|
|
||||||
_, height := target.GetSize()
|
|
||||||
|
|
||||||
if err := h.mainPanel.SetCurrentFrame(frameRightGlobeHolder); err != nil {
|
if err := h.mainPanel.SetCurrentFrame(frameRightGlobeHolder); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.mainPanel.SetPosition(x, height)
|
h.mainPanel.SetPosition(offsetX, height)
|
||||||
|
|
||||||
h.mainPanel.Render(target)
|
h.mainPanel.Render(target)
|
||||||
|
|
||||||
// Mana status bar
|
|
||||||
manaPercent := float64(h.hero.Stats.Mana) / float64(h.hero.Stats.MaxMana)
|
|
||||||
manaBarHeight := int(manaPercent * float64(globeHeight))
|
|
||||||
|
|
||||||
if err := h.hpManaStatusSprite.SetCurrentFrame(frameManaStatus); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.hpManaStatusSprite.SetPosition(x+manaStatusOffsetX, height+manaStatusOffsetY)
|
|
||||||
|
|
||||||
manaMaskRect := image.Rect(0, globeHeight-manaBarHeight, globeWidth, globeHeight)
|
|
||||||
h.hpManaStatusSprite.RenderSection(target, manaMaskRect)
|
|
||||||
|
|
||||||
// Right globe
|
|
||||||
if err := h.globeSprite.SetCurrentFrame(frameRightGlobe); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.globeSprite.SetPosition(x+rightGlobeOffsetX, height+rightGlobeOffsetY)
|
|
||||||
|
|
||||||
h.globeSprite.Render(target)
|
|
||||||
h.globeSprite.Render(target)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HUD) renderHealthGlobe(x, y int, target d2interface.Surface) error {
|
|
||||||
healthPercent := float64(h.hero.Stats.Health) / float64(h.hero.Stats.MaxHealth)
|
|
||||||
hpBarHeight := int(healthPercent * float64(globeHeight))
|
|
||||||
|
|
||||||
if err := h.hpManaStatusSprite.SetCurrentFrame(0); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.hpManaStatusSprite.SetPosition(x+healthStatusOffsetX, y+healthStatusOffsetY)
|
|
||||||
|
|
||||||
healthMaskRect := image.Rect(0, globeHeight-hpBarHeight, globeWidth, globeHeight)
|
|
||||||
h.hpManaStatusSprite.RenderSection(target, healthMaskRect)
|
|
||||||
|
|
||||||
// Left globe
|
|
||||||
if err := h.globeSprite.SetCurrentFrame(frameHealthStatus); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
h.globeSprite.SetPosition(x+globeSpriteOffsetX, y+globeSpriteOffsetY)
|
|
||||||
h.globeSprite.Render(target)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderPanel(x, y int, target d2interface.Surface) error {
|
func (h *HUD) renderPanel(x, y int, target d2interface.Surface) error {
|
||||||
@ -453,7 +411,7 @@ func (h *HUD) renderPanel(x, y int, target d2interface.Surface) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderLeftSkill(x, y int, target d2interface.Surface) error {
|
func (h *HUD) renderLeftSkill(x, y int, target d2interface.Surface) {
|
||||||
newSkillResourcePath := h.getSkillResourceByClass(h.hero.LeftSkill.Charclass)
|
newSkillResourcePath := h.getSkillResourceByClass(h.hero.LeftSkill.Charclass)
|
||||||
if newSkillResourcePath != h.leftSkillResource.SkillResourcePath {
|
if newSkillResourcePath != h.leftSkillResource.SkillResourcePath {
|
||||||
h.leftSkillResource.SkillResourcePath = newSkillResourcePath
|
h.leftSkillResource.SkillResourcePath = newSkillResourcePath
|
||||||
@ -461,16 +419,15 @@ func (h *HUD) renderLeftSkill(x, y int, target d2interface.Surface) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := h.leftSkillResource.SkillIcon.SetCurrentFrame(h.hero.LeftSkill.IconCel); err != nil {
|
if err := h.leftSkillResource.SkillIcon.SetCurrentFrame(h.hero.LeftSkill.IconCel); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.leftSkillResource.SkillIcon.SetPosition(x, y)
|
h.leftSkillResource.SkillIcon.SetPosition(x, y)
|
||||||
h.leftSkillResource.SkillIcon.Render(target)
|
h.leftSkillResource.SkillIcon.Render(target)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderRightSkill(x, _ int, target d2interface.Surface) error {
|
func (h *HUD) renderRightSkill(x, _ int, target d2interface.Surface) {
|
||||||
_, height := target.GetSize()
|
_, height := target.GetSize()
|
||||||
|
|
||||||
newSkillResourcePath := h.getSkillResourceByClass(h.hero.RightSkill.Charclass)
|
newSkillResourcePath := h.getSkillResourceByClass(h.hero.RightSkill.Charclass)
|
||||||
@ -480,13 +437,12 @@ func (h *HUD) renderRightSkill(x, _ int, target d2interface.Surface) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := h.rightSkillResource.SkillIcon.SetCurrentFrame(h.hero.RightSkill.IconCel); err != nil {
|
if err := h.rightSkillResource.SkillIcon.SetCurrentFrame(h.hero.RightSkill.IconCel); err != nil {
|
||||||
return err
|
log.Print(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h.rightSkillResource.SkillIcon.SetPosition(x, height)
|
h.rightSkillResource.SkillIcon.SetPosition(x, height)
|
||||||
h.rightSkillResource.SkillIcon.Render(target)
|
h.rightSkillResource.SkillIcon.Render(target)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderNewStatsButton(x, y int, target d2interface.Surface) error {
|
func (h *HUD) renderNewStatsButton(x, y int, target d2interface.Surface) error {
|
||||||
@ -511,7 +467,7 @@ func (h *HUD) renderStamina(x, y int, target d2interface.Surface) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderStaminaBar(target d2interface.Surface) error {
|
func (h *HUD) renderStaminaBar(target d2interface.Surface) {
|
||||||
target.PushTranslation(staminaBarOffsetX, staminaBarOffsetY)
|
target.PushTranslation(staminaBarOffsetX, staminaBarOffsetY)
|
||||||
defer target.Pop()
|
defer target.Pop()
|
||||||
|
|
||||||
@ -526,19 +482,15 @@ func (h *HUD) renderStaminaBar(target d2interface.Surface) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
target.DrawRect(int(staminaPercent*staminaBarWidth), staminaBarHeight, staminaBarColor)
|
target.DrawRect(int(staminaPercent*staminaBarWidth), staminaBarHeight, staminaBarColor)
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderExperienceBar(target d2interface.Surface) error {
|
func (h *HUD) renderExperienceBar(target d2interface.Surface) {
|
||||||
target.PushTranslation(experienceBarOffsetX, experienceBarOffsetY)
|
target.PushTranslation(experienceBarOffsetX, experienceBarOffsetY)
|
||||||
defer target.Pop()
|
defer target.Pop()
|
||||||
|
|
||||||
expPercent := float64(h.hero.Stats.Experience) / float64(h.hero.Stats.NextLevelExp)
|
expPercent := float64(h.hero.Stats.Experience) / float64(h.hero.Stats.NextLevelExp)
|
||||||
|
|
||||||
target.DrawRect(int(expPercent*expBarWidth), 2, d2util.Color(whiteAlpha100))
|
target.DrawRect(int(expPercent*expBarWidth), 2, d2util.Color(whiteAlpha100))
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HUD) renderMiniPanel(target d2interface.Surface) error {
|
func (h *HUD) renderMiniPanel(target d2interface.Surface) error {
|
||||||
@ -765,7 +717,17 @@ func (h *HUD) renderForSelectableEntitiesHovered(target d2interface.Surface) {
|
|||||||
func (h *HUD) Render(target d2interface.Surface) error {
|
func (h *HUD) Render(target d2interface.Surface) error {
|
||||||
h.renderForSelectableEntitiesHovered(target)
|
h.renderForSelectableEntitiesHovered(target)
|
||||||
|
|
||||||
if err := h.renderGameControlPanelElements(target); err != nil {
|
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)
|
||||||
|
|
||||||
|
// Mini Panel and button
|
||||||
|
if err := h.renderMiniPanel(target); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ func (s *skillTree) load() {
|
|||||||
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPrioritySkilltree)
|
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPrioritySkilltree)
|
||||||
s.iconGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPrioritySkilltreeIcon)
|
s.iconGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPrioritySkilltreeIcon)
|
||||||
|
|
||||||
s.panel = s.uiManager.NewCustomWidget(s.Render)
|
s.panel = s.uiManager.NewCustomWidget(s.Render, 400, 600)
|
||||||
s.panelGroup.AddWidget(s.panel)
|
s.panelGroup.AddWidget(s.panel)
|
||||||
|
|
||||||
s.frame = d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameRight)
|
s.frame = d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameRight)
|
||||||
@ -424,9 +424,6 @@ func (s *skillTree) renderTabCommon(target d2interface.Surface) {
|
|||||||
|
|
||||||
skillPanel.SetPosition(x+w, y)
|
skillPanel.SetPosition(x+w, y)
|
||||||
s.renderPanelSegment(target, frameCommonTabBottomRight)
|
s.renderPanelSegment(target, frameCommonTabBottomRight)
|
||||||
|
|
||||||
// available skill points label
|
|
||||||
s.availSPLabel.Render(target)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *skillTree) renderTab(target d2interface.Surface, tab int) {
|
func (s *skillTree) renderTab(target d2interface.Surface, tab int) {
|
||||||
|
Loading…
Reference in New Issue
Block a user