mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-09 01:56:47 -05:00
Merge pull request #911 from juander-ux/ui_refactor
d2ui refactor I *almost* squashed it!
This commit is contained in:
commit
5e5d8415ba
@ -242,32 +242,28 @@ var _ Widget = &Button{} // static check to ensure button implements widget
|
||||
|
||||
// Button defines a standard wide UI button
|
||||
type Button struct {
|
||||
manager *UIManager
|
||||
*BaseWidget
|
||||
buttonLayout ButtonLayout
|
||||
normalSurface d2interface.Surface
|
||||
pressedSurface d2interface.Surface
|
||||
toggledSurface d2interface.Surface
|
||||
pressedToggledSurface d2interface.Surface
|
||||
disabledSurface d2interface.Surface
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
height int
|
||||
onClick func()
|
||||
enabled bool
|
||||
visible bool
|
||||
pressed bool
|
||||
toggled bool
|
||||
}
|
||||
|
||||
// NewButton creates an instance of Button
|
||||
func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
|
||||
base := NewBaseWidget(ui)
|
||||
base.SetVisible(true)
|
||||
|
||||
btn := &Button{
|
||||
width: 0,
|
||||
height: 0,
|
||||
visible: true,
|
||||
enabled: true,
|
||||
pressed: false,
|
||||
BaseWidget: base,
|
||||
enabled: true,
|
||||
pressed: false,
|
||||
}
|
||||
|
||||
buttonLayout := getButtonLayouts()[buttonType]
|
||||
@ -348,7 +344,7 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
|
||||
xOffset := half(v.width)
|
||||
|
||||
label.SetPosition(xOffset, textY)
|
||||
label.Render(v.normalSurface)
|
||||
label.RenderNoError(v.normalSurface)
|
||||
|
||||
if !btnLayout.HasImage || !btnLayout.AllowFrameChange {
|
||||
return
|
||||
@ -422,15 +418,10 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
|
||||
}
|
||||
|
||||
label.SetPosition(state.offsetX, state.offsetY)
|
||||
label.Render(*state.prerenderdestination)
|
||||
label.RenderNoError(*state.prerenderdestination)
|
||||
}
|
||||
}
|
||||
|
||||
// bindManager binds the button to the UI manager
|
||||
func (v *Button) bindManager(manager *UIManager) {
|
||||
v.manager = manager
|
||||
}
|
||||
|
||||
// OnActivated defines the callback handler for the activate event
|
||||
func (v *Button) OnActivated(callback func()) {
|
||||
v.onClick = callback
|
||||
@ -495,32 +486,6 @@ func (v *Button) SetEnabled(enabled bool) {
|
||||
v.enabled = enabled
|
||||
}
|
||||
|
||||
// GetSize returns the size of the button
|
||||
func (v *Button) GetSize() (width, height int) {
|
||||
return v.width, v.height
|
||||
}
|
||||
|
||||
// SetPosition moves the button
|
||||
func (v *Button) SetPosition(x, y int) {
|
||||
v.x = x
|
||||
v.y = y
|
||||
}
|
||||
|
||||
// GetPosition returns the location of the button
|
||||
func (v *Button) GetPosition() (x, y int) {
|
||||
return v.x, v.y
|
||||
}
|
||||
|
||||
// GetVisible returns the visibility of the button
|
||||
func (v *Button) GetVisible() bool {
|
||||
return v.visible
|
||||
}
|
||||
|
||||
// SetVisible sets the visibility of the button
|
||||
func (v *Button) SetVisible(visible bool) {
|
||||
v.visible = visible
|
||||
}
|
||||
|
||||
// GetPressed returns the pressed state of the button
|
||||
func (v *Button) GetPressed() bool {
|
||||
return v.pressed
|
||||
|
@ -8,18 +8,16 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
)
|
||||
|
||||
// static check that Checkbox implements Widget
|
||||
var _ Widget = &Checkbox{}
|
||||
|
||||
// Checkbox represents a checkbox UI element
|
||||
type Checkbox struct {
|
||||
manager *UIManager
|
||||
*BaseWidget
|
||||
Image d2interface.Surface
|
||||
checkedImage d2interface.Surface
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
height int
|
||||
onClick func()
|
||||
checkState bool
|
||||
visible bool
|
||||
enabled bool
|
||||
}
|
||||
|
||||
@ -27,11 +25,11 @@ type Checkbox struct {
|
||||
func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox {
|
||||
var err error
|
||||
|
||||
base := NewBaseWidget(ui)
|
||||
|
||||
result := &Checkbox{
|
||||
BaseWidget: base,
|
||||
checkState: checkState,
|
||||
visible: true,
|
||||
width: 0,
|
||||
height: 0,
|
||||
enabled: true,
|
||||
}
|
||||
|
||||
@ -70,11 +68,6 @@ func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox {
|
||||
return result
|
||||
}
|
||||
|
||||
// bindManager binds the checkbox to the UI manager
|
||||
func (v *Checkbox) bindManager(manager *UIManager) {
|
||||
v.manager = manager
|
||||
}
|
||||
|
||||
// Render renders the checkbox
|
||||
func (v *Checkbox) Render(target d2interface.Surface) error {
|
||||
target.PushTranslation(v.x, v.y)
|
||||
@ -140,29 +133,3 @@ func (v *Checkbox) Activate() {
|
||||
|
||||
v.onClick()
|
||||
}
|
||||
|
||||
// GetPosition returns the position of the checkbox
|
||||
func (v *Checkbox) GetPosition() (x, y int) {
|
||||
return v.x, v.y
|
||||
}
|
||||
|
||||
// GetSize returns the size of the checkbox
|
||||
func (v *Checkbox) GetSize() (width, height int) {
|
||||
return v.width, v.height
|
||||
}
|
||||
|
||||
// GetVisible returns the visibility state of the checkbox
|
||||
func (v *Checkbox) GetVisible() bool {
|
||||
return v.visible
|
||||
}
|
||||
|
||||
// SetPosition sets the position of the checkbox
|
||||
func (v *Checkbox) SetPosition(x, y int) {
|
||||
v.x = x
|
||||
v.y = y
|
||||
}
|
||||
|
||||
// SetVisible sets the visibility of the checkbox
|
||||
func (v *Checkbox) SetVisible(visible bool) {
|
||||
v.visible = visible
|
||||
}
|
||||
|
32
d2core/d2ui/custom_widget.go
Normal file
32
d2core/d2ui/custom_widget.go
Normal file
@ -0,0 +1,32 @@
|
||||
package d2ui
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
// static check that CustomWidget implements widget
|
||||
var _ Widget = &CustomWidget{}
|
||||
|
||||
// CustomWidget is a widget with a fully custom render function
|
||||
type CustomWidget struct {
|
||||
*BaseWidget
|
||||
renderFunc func(target d2interface.Surface) error
|
||||
}
|
||||
|
||||
// NewCustomWidget creates a new widget with custom render function
|
||||
func (ui *UIManager) NewCustomWidget(renderFunc func(target d2interface.Surface) error) *CustomWidget {
|
||||
base := NewBaseWidget(ui)
|
||||
|
||||
return &CustomWidget{
|
||||
BaseWidget: base,
|
||||
renderFunc: renderFunc,
|
||||
}
|
||||
}
|
||||
|
||||
// Render draws the custom widget
|
||||
func (c *CustomWidget) Render(target d2interface.Surface) error {
|
||||
return c.renderFunc(target)
|
||||
}
|
||||
|
||||
// Advance is a no-op
|
||||
func (c *CustomWidget) Advance(elapsed float64) error {
|
||||
return nil
|
||||
}
|
@ -11,6 +11,9 @@ type Drawable interface {
|
||||
GetSize() (width, height int)
|
||||
SetPosition(x, y int)
|
||||
GetPosition() (x, y int)
|
||||
OffsetPosition(xo, yo int)
|
||||
GetVisible() bool
|
||||
SetVisible(visible bool)
|
||||
SetRenderPriority(priority RenderPriority)
|
||||
GetRenderPriority() (priority RenderPriority)
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// static check that UIFrame implements Widget
|
||||
var _ Widget = &UIFrame{}
|
||||
|
||||
type frameOrientation = int
|
||||
|
||||
// Frame orientations
|
||||
@ -19,11 +22,9 @@ const (
|
||||
// UIFrame is a representation of a ui panel that occupies the left or right half of the screen
|
||||
// when it is visible.
|
||||
type UIFrame struct {
|
||||
*BaseWidget
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *UIManager
|
||||
frame *Sprite
|
||||
originX int
|
||||
originY int
|
||||
frameOrientation frameOrientation
|
||||
}
|
||||
|
||||
@ -58,12 +59,13 @@ func NewUIFrame(
|
||||
originY = 0
|
||||
}
|
||||
|
||||
base := NewBaseWidget(uiManager)
|
||||
base.SetPosition(originX, originY)
|
||||
|
||||
frame := &UIFrame{
|
||||
BaseWidget: base,
|
||||
asset: asset,
|
||||
uiManager: uiManager,
|
||||
frameOrientation: frameOrientation,
|
||||
originX: originX,
|
||||
originY: originY,
|
||||
}
|
||||
frame.Load()
|
||||
|
||||
@ -72,7 +74,7 @@ func NewUIFrame(
|
||||
|
||||
// Load the necessary frame resources
|
||||
func (u *UIFrame) Load() {
|
||||
sprite, err := u.uiManager.NewSprite(d2resource.Frame, d2resource.PaletteSky)
|
||||
sprite, err := u.manager.NewSprite(d2resource.Frame, d2resource.PaletteSky)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
@ -105,7 +107,7 @@ func (u *UIFrame) renderLeft(target d2interface.Surface) error {
|
||||
// the frame coordinates
|
||||
coord := make(map[int]*struct{ x, y int })
|
||||
|
||||
startX, startY := u.originX, u.originY
|
||||
startX, startY := u.GetPosition()
|
||||
currentX, currentY := startX, startY
|
||||
|
||||
// first determine the coordinates for each frame
|
||||
@ -162,7 +164,7 @@ func (u *UIFrame) renderRight(target d2interface.Surface) error {
|
||||
// the frame coordinates
|
||||
coord := make(map[int]*struct{ x, y int })
|
||||
|
||||
startX, startY := u.originX, u.originY
|
||||
startX, startY := u.GetPosition()
|
||||
currentX, currentY := startX, startY
|
||||
|
||||
// first determine the coordinates for each frame
|
||||
@ -225,7 +227,12 @@ func (u *UIFrame) renderFramePiece(sfc d2interface.Surface, x, y, idx int) error
|
||||
|
||||
u.frame.SetPosition(x, y)
|
||||
|
||||
u.frame.Render(sfc)
|
||||
u.frame.RenderNoError(sfc)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Advance is a no-op
|
||||
func (u *UIFrame) Advance(elapsed float64) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -13,12 +13,13 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
|
||||
)
|
||||
|
||||
// static check that UIFrame implements Widget
|
||||
var _ Widget = &Label{}
|
||||
|
||||
// Label represents a user interface label
|
||||
type Label struct {
|
||||
manager *UIManager
|
||||
*BaseWidget
|
||||
text string
|
||||
X int
|
||||
Y int
|
||||
Alignment d2gui.HorizontalAlign
|
||||
font *d2asset.Font
|
||||
Color map[int]color.Color
|
||||
@ -33,10 +34,13 @@ func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label {
|
||||
return nil
|
||||
}
|
||||
|
||||
base := NewBaseWidget(ui)
|
||||
|
||||
result := &Label{
|
||||
Alignment: d2gui.HorizontalAlignLeft,
|
||||
Color: map[int]color.Color{0: color.White},
|
||||
font: font,
|
||||
BaseWidget: base,
|
||||
Alignment: d2gui.HorizontalAlignLeft,
|
||||
Color: map[int]color.Color{0: color.White},
|
||||
font: font,
|
||||
}
|
||||
|
||||
result.bindManager(ui)
|
||||
@ -44,9 +48,15 @@ func (ui *UIManager) NewLabel(fontPath, palettePath string) *Label {
|
||||
return result
|
||||
}
|
||||
|
||||
// Render draws the label on the screen, respliting the lines to allow for other alignments.
|
||||
func (v *Label) Render(target d2interface.Surface) {
|
||||
target.PushTranslation(v.X, v.Y)
|
||||
// Render draws the label on the screen
|
||||
func (v *Label) Render(target d2interface.Surface) error {
|
||||
v.RenderNoError(target)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenderNoError draws the label on the screen, respliting the lines to allow for other alignments.
|
||||
func (v *Label) RenderNoError(target d2interface.Surface) {
|
||||
target.PushTranslation(v.GetPosition())
|
||||
|
||||
lines := strings.Split(v.text, "\n")
|
||||
yOffset := 0
|
||||
@ -91,17 +101,6 @@ func (v *Label) Render(target d2interface.Surface) {
|
||||
target.Pop()
|
||||
}
|
||||
|
||||
// bindManager binds the label to the UI manager
|
||||
func (v *Label) bindManager(manager *UIManager) {
|
||||
v.manager = manager
|
||||
}
|
||||
|
||||
// SetPosition moves the label to the specified location
|
||||
func (v *Label) SetPosition(x, y int) {
|
||||
v.X = x
|
||||
v.Y = y
|
||||
}
|
||||
|
||||
// GetSize returns the size of the label
|
||||
func (v *Label) GetSize() (width, height int) {
|
||||
return v.font.GetTextMetrics(v.text)
|
||||
@ -172,6 +171,11 @@ func (v *Label) getAlignOffset(textWidth int) int {
|
||||
}
|
||||
}
|
||||
|
||||
// Advance is a no-op
|
||||
func (v *Label) Advance(elapsed float64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func getColor(token ColorToken) color.Color {
|
||||
// https://github.com/OpenDiablo2/OpenDiablo2/issues/823
|
||||
colors := map[ColorToken]color.Color{
|
||||
|
@ -15,11 +15,12 @@ const (
|
||||
scrollbarWidth = 10
|
||||
)
|
||||
|
||||
// static check that Scrollbar implements widget
|
||||
var _ Widget = &Scrollbar{}
|
||||
|
||||
// Scrollbar is a vertical slider ui element
|
||||
type Scrollbar struct {
|
||||
manager *UIManager
|
||||
x, y, height int
|
||||
visible bool
|
||||
*BaseWidget
|
||||
enabled bool
|
||||
currentOffset int
|
||||
maxOffset int
|
||||
@ -36,12 +37,13 @@ func (ui *UIManager) NewScrollbar(x, y, height int) *Scrollbar {
|
||||
return nil
|
||||
}
|
||||
|
||||
base := NewBaseWidget(ui)
|
||||
base.SetPosition(x, y)
|
||||
base.height = height
|
||||
|
||||
result := &Scrollbar{
|
||||
visible: true,
|
||||
BaseWidget: base,
|
||||
enabled: true,
|
||||
x: x,
|
||||
y: y,
|
||||
height: height,
|
||||
scrollbarSprite: scrollbarSprite,
|
||||
}
|
||||
|
||||
@ -146,11 +148,6 @@ func (v *Scrollbar) Render(target d2interface.Surface) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindManager binds the scrollbar to the UI manager
|
||||
func (v *Scrollbar) bindManager(manager *UIManager) {
|
||||
v.manager = manager
|
||||
}
|
||||
|
||||
// Advance advances the scrollbar sprite
|
||||
func (v *Scrollbar) Advance(elapsed float64) error {
|
||||
return v.scrollbarSprite.Advance(elapsed)
|
||||
@ -161,27 +158,6 @@ func (v *Scrollbar) GetSize() (width, height int) {
|
||||
return scrollbarWidth, v.height
|
||||
}
|
||||
|
||||
// SetPosition sets the scrollbar x,y position
|
||||
func (v *Scrollbar) SetPosition(x, y int) {
|
||||
v.x = x
|
||||
v.y = y
|
||||
}
|
||||
|
||||
// GetPosition returns the scrollbar x,y position
|
||||
func (v *Scrollbar) GetPosition() (x, y int) {
|
||||
return v.x, v.y
|
||||
}
|
||||
|
||||
// GetVisible returns whether or not the scrollbar is visible
|
||||
func (v *Scrollbar) GetVisible() bool {
|
||||
return v.visible
|
||||
}
|
||||
|
||||
// SetVisible sets the scrollbar visibility state
|
||||
func (v *Scrollbar) SetVisible(visible bool) {
|
||||
v.visible = visible
|
||||
}
|
||||
|
||||
// SetMaxOffset sets the maximum offset of the scrollbar
|
||||
func (v *Scrollbar) SetMaxOffset(maxOffset int) {
|
||||
v.maxOffset = maxOffset
|
||||
|
@ -11,10 +11,12 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
|
||||
)
|
||||
|
||||
// static check that Sprite implements Widget
|
||||
var _ Widget = &Sprite{}
|
||||
|
||||
// Sprite is a positioned visual object.
|
||||
type Sprite struct {
|
||||
x int
|
||||
y int
|
||||
*BaseWidget
|
||||
animation d2interface.Animation
|
||||
}
|
||||
|
||||
@ -31,11 +33,21 @@ func (ui *UIManager) NewSprite(animationPath, palettePath string) (*Sprite, erro
|
||||
|
||||
animation.BindRenderer(ui.renderer)
|
||||
|
||||
return &Sprite{animation: animation}, nil
|
||||
base := NewBaseWidget(ui)
|
||||
|
||||
return &Sprite{
|
||||
BaseWidget: base,
|
||||
animation: animation}, nil
|
||||
}
|
||||
|
||||
// Render renders the sprite on the given surface
|
||||
func (s *Sprite) Render(target d2interface.Surface) {
|
||||
func (s *Sprite) Render(target d2interface.Surface) error {
|
||||
s.RenderNoError(target)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenderNoError renders the sprite on the given surface
|
||||
func (s *Sprite) RenderNoError(target d2interface.Surface) {
|
||||
_, frameHeight := s.animation.GetCurrentFrameSize()
|
||||
|
||||
target.PushTranslation(s.x, s.y-frameHeight)
|
||||
@ -80,15 +92,9 @@ func (s *Sprite) RenderSegmented(target d2interface.Surface, segmentsX, segments
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPosition places the sprite in 2D
|
||||
func (s *Sprite) SetPosition(x, y int) {
|
||||
s.x = x
|
||||
s.y = y
|
||||
}
|
||||
|
||||
// GetPosition retrieves the 2D position of the sprite
|
||||
func (s *Sprite) GetPosition() (x, y int) {
|
||||
return s.x, s.y
|
||||
// GetSize returns the size of the current frame
|
||||
func (s *Sprite) GetSize() (width, height int) {
|
||||
return s.GetCurrentFrameSize()
|
||||
}
|
||||
|
||||
// GetFrameSize gets the Size(width, height) of a indexed frame.
|
||||
|
@ -10,17 +10,17 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
)
|
||||
|
||||
// static check that TextBox implements widget
|
||||
var _ Widget = &TextBox{}
|
||||
|
||||
// TextBox represents a text input box
|
||||
type TextBox struct {
|
||||
manager *UIManager
|
||||
*BaseWidget
|
||||
textLabel *Label
|
||||
lineBar *Label
|
||||
text string
|
||||
filter string
|
||||
x int
|
||||
y int
|
||||
bgSprite *Sprite
|
||||
visible bool
|
||||
enabled bool
|
||||
isFocused bool
|
||||
}
|
||||
@ -33,13 +33,15 @@ func (ui *UIManager) NewTextbox() *TextBox {
|
||||
return nil
|
||||
}
|
||||
|
||||
base := NewBaseWidget(ui)
|
||||
|
||||
tb := &TextBox{
|
||||
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
bgSprite: bgSprite,
|
||||
textLabel: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
|
||||
lineBar: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
|
||||
enabled: true,
|
||||
visible: true,
|
||||
BaseWidget: base,
|
||||
filter: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
bgSprite: bgSprite,
|
||||
textLabel: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
|
||||
lineBar: ui.NewLabel(d2resource.FontFormal11, d2resource.PaletteUnits),
|
||||
enabled: true,
|
||||
}
|
||||
tb.lineBar.SetText("_")
|
||||
|
||||
@ -59,21 +61,16 @@ func (v *TextBox) Render(target d2interface.Surface) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
v.bgSprite.Render(target)
|
||||
v.textLabel.Render(target)
|
||||
v.bgSprite.RenderNoError(target)
|
||||
v.textLabel.RenderNoError(target)
|
||||
|
||||
if (time.Now().UnixNano()/1e6)&(1<<8) > 0 {
|
||||
v.lineBar.Render(target)
|
||||
v.lineBar.RenderNoError(target)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// bindManager binds the textbox to the UI manager
|
||||
func (v *TextBox) bindManager(manager *UIManager) {
|
||||
v.manager = manager
|
||||
}
|
||||
|
||||
// OnKeyChars handles key character events
|
||||
func (v *TextBox) OnKeyChars(event d2interface.KeyCharsEvent) bool {
|
||||
if !v.isFocused || !v.visible || !v.enabled {
|
||||
@ -189,21 +186,6 @@ func (v *TextBox) SetPosition(x, y int) {
|
||||
v.bgSprite.SetPosition(v.x, v.y+26)
|
||||
}
|
||||
|
||||
// GetPosition returns the position of the text box
|
||||
func (v *TextBox) GetPosition() (x, y int) {
|
||||
return v.x, v.y
|
||||
}
|
||||
|
||||
// GetVisible returns the visibility of the text box
|
||||
func (v *TextBox) GetVisible() bool {
|
||||
return v.visible
|
||||
}
|
||||
|
||||
// SetVisible sets the visibility of the text box
|
||||
func (v *TextBox) SetVisible(visible bool) {
|
||||
v.visible = visible
|
||||
}
|
||||
|
||||
// GetEnabled returns the enabled state of the text box
|
||||
func (v *TextBox) GetEnabled() bool {
|
||||
return v.enabled
|
||||
|
@ -14,13 +14,15 @@ const (
|
||||
screenHeight = 600
|
||||
)
|
||||
|
||||
// static check that Tooltip implements widget
|
||||
var _ Widget = &Tooltip{}
|
||||
|
||||
// Tooltip contains a label containing text with a transparent, black background
|
||||
type Tooltip struct {
|
||||
manager *UIManager
|
||||
*BaseWidget
|
||||
lines []string
|
||||
label *Label
|
||||
backgroundColor int
|
||||
x, y int
|
||||
originX tooltipXOrigin
|
||||
originY tooltipYOrigin
|
||||
boxEnabled bool
|
||||
@ -56,11 +58,12 @@ func (ui *UIManager) NewTooltip(font,
|
||||
label := ui.NewLabel(font, palette)
|
||||
label.Alignment = d2gui.HorizontalAlignCenter
|
||||
|
||||
base := NewBaseWidget(ui)
|
||||
|
||||
res := &Tooltip{
|
||||
BaseWidget: base,
|
||||
backgroundColor: blackAlpha70,
|
||||
label: label,
|
||||
x: 0,
|
||||
y: 0,
|
||||
originX: originX,
|
||||
originY: originY,
|
||||
boxEnabled: true,
|
||||
@ -70,12 +73,6 @@ func (ui *UIManager) NewTooltip(font,
|
||||
return res
|
||||
}
|
||||
|
||||
// SetPosition sets the position of the origin point of the tooltip
|
||||
func (t *Tooltip) SetPosition(x, y int) {
|
||||
t.x = x
|
||||
t.y = y
|
||||
}
|
||||
|
||||
// SetTextLines sets the tooltip text in the form of an array of strings
|
||||
func (t *Tooltip) SetTextLines(lines []string) {
|
||||
t.lines = lines
|
||||
@ -143,7 +140,7 @@ func (t *Tooltip) GetSize() (sx, sy int) {
|
||||
}
|
||||
|
||||
// Render draws the tooltip
|
||||
func (t *Tooltip) Render(target d2interface.Surface) {
|
||||
func (t *Tooltip) Render(target d2interface.Surface) error {
|
||||
maxW, maxH := t.GetSize()
|
||||
|
||||
// nolint:gomnd // no magic numbers, their meaning is obvious
|
||||
@ -190,9 +187,16 @@ func (t *Tooltip) Render(target d2interface.Surface) {
|
||||
for i := range t.lines {
|
||||
t.label.SetText(t.lines[i])
|
||||
_, h := t.label.GetTextMetrics(t.lines[i])
|
||||
t.label.Render(target)
|
||||
t.label.RenderNoError(target)
|
||||
target.PushTranslation(0, h)
|
||||
}
|
||||
|
||||
target.PopN(len(t.lines))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Advance is a no-op
|
||||
func (t *Tooltip) Advance(elapsed float64) error {
|
||||
return nil
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package d2ui
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
|
||||
@ -12,16 +13,18 @@ import (
|
||||
|
||||
// UIManager manages a collection of UI elements (buttons, textboxes, labels)
|
||||
type UIManager struct {
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer
|
||||
inputManager d2interface.InputManager
|
||||
audio d2interface.AudioProvider
|
||||
widgets []Widget
|
||||
cursorButtons CursorButton
|
||||
CursorX int
|
||||
CursorY int
|
||||
pressedWidget Widget
|
||||
clickSfx d2interface.SoundEffect
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer
|
||||
inputManager d2interface.InputManager
|
||||
audio d2interface.AudioProvider
|
||||
widgets []Widget
|
||||
widgetsGroups []*WidgetGroup
|
||||
clickableWidgets []ClickableWidget
|
||||
cursorButtons CursorButton
|
||||
CursorX int
|
||||
CursorY int
|
||||
pressedWidget ClickableWidget
|
||||
clickSfx d2interface.SoundEffect
|
||||
}
|
||||
|
||||
// Note: methods for creating buttons and stuff are in their respective files
|
||||
@ -44,9 +47,18 @@ func (ui *UIManager) Initialize() {
|
||||
// Reset resets the state of the UI manager. Typically called for new screens
|
||||
func (ui *UIManager) Reset() {
|
||||
ui.widgets = nil
|
||||
ui.clickableWidgets = nil
|
||||
ui.pressedWidget = nil
|
||||
}
|
||||
|
||||
// addWidgetGroup adds a widgetGroup to the UI manager and sorts by priority
|
||||
func (ui *UIManager) addWidgetGroup(group *WidgetGroup) {
|
||||
ui.widgetsGroups = append(ui.widgetsGroups, group)
|
||||
sort.SliceStable(ui.widgetsGroups, func(i, j int) bool {
|
||||
return ui.widgetsGroups[i].priority < ui.widgetsGroups[j].priority
|
||||
})
|
||||
}
|
||||
|
||||
// addWidget adds a widget to the UI manager
|
||||
func (ui *UIManager) addWidget(widget Widget) {
|
||||
err := ui.inputManager.BindHandler(widget)
|
||||
@ -54,8 +66,12 @@ func (ui *UIManager) addWidget(widget Widget) {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
ui.widgets = append(ui.widgets, widget)
|
||||
clickable, ok := widget.(ClickableWidget)
|
||||
if ok {
|
||||
ui.clickableWidgets = append(ui.clickableWidgets, clickable)
|
||||
}
|
||||
|
||||
ui.widgets = append(ui.widgets, widget)
|
||||
widget.bindManager(ui)
|
||||
}
|
||||
|
||||
@ -67,13 +83,12 @@ func (ui *UIManager) OnMouseButtonUp(event d2interface.MouseEvent) bool {
|
||||
// activate previously pressed widget if cursor is still hovering
|
||||
w := ui.pressedWidget
|
||||
|
||||
if w != nil && ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.
|
||||
GetEnabled() {
|
||||
if w != nil && ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
||||
w.Activate()
|
||||
}
|
||||
|
||||
// unpress all widgets that are pressed
|
||||
for _, w := range ui.widgets {
|
||||
for _, w := range ui.clickableWidgets {
|
||||
w.SetPressed(false)
|
||||
}
|
||||
}
|
||||
@ -87,7 +102,7 @@ func (ui *UIManager) OnMouseButtonDown(event d2interface.MouseEvent) bool {
|
||||
if event.Button() == d2enum.MouseButtonLeft {
|
||||
// find and press a widget on screen
|
||||
ui.pressedWidget = nil
|
||||
for _, w := range ui.widgets {
|
||||
for _, w := range ui.clickableWidgets {
|
||||
if ui.contains(w, ui.CursorX, ui.CursorY) && w.GetVisible() && w.GetEnabled() {
|
||||
w.SetPressed(true)
|
||||
ui.pressedWidget = w
|
||||
@ -115,6 +130,15 @@ func (ui *UIManager) Render(target d2interface.Surface) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, widgetGroup := range ui.widgetsGroups {
|
||||
if widgetGroup.GetVisible() {
|
||||
err := widgetGroup.Render(target)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// contains determines whether a given x,y coordinate lands within a Widget
|
||||
|
@ -1,13 +1,102 @@
|
||||
package d2ui
|
||||
|
||||
// RenderPriority determines in which order ui elements are drawn.
|
||||
// The higher the number the later an element is drawn.
|
||||
type RenderPriority int
|
||||
|
||||
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
|
||||
// RenderPriorityForeground is the last element drawn
|
||||
RenderPriorityForeground
|
||||
)
|
||||
|
||||
// Widget defines an object that is a UI widget
|
||||
type Widget interface {
|
||||
Drawable
|
||||
bindManager(ui *UIManager)
|
||||
GetEnabled() bool
|
||||
}
|
||||
|
||||
// ClickableWidget defines an object that can be clicked
|
||||
type ClickableWidget interface {
|
||||
Widget
|
||||
SetEnabled(enabled bool)
|
||||
SetPressed(pressed bool)
|
||||
GetEnabled() bool
|
||||
GetPressed() bool
|
||||
OnActivated(callback func())
|
||||
Activate()
|
||||
}
|
||||
|
||||
// BaseWidget contains default functionality that all widgets share
|
||||
type BaseWidget struct {
|
||||
manager *UIManager
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
height int
|
||||
renderPriority RenderPriority
|
||||
visible bool
|
||||
}
|
||||
|
||||
// NewBaseWidget creates a new BaseWidget with defaults
|
||||
func NewBaseWidget(manager *UIManager) *BaseWidget {
|
||||
return &BaseWidget{
|
||||
manager: manager,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
visible: true,
|
||||
renderPriority: RenderPriorityBackground,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BaseWidget) bindManager(manager *UIManager) {
|
||||
b.manager = manager
|
||||
}
|
||||
|
||||
// GetSize returns the size of the widget
|
||||
func (b *BaseWidget) GetSize() (width, height int) {
|
||||
return b.width, b.height
|
||||
}
|
||||
|
||||
// SetPosition sets the position of the widget
|
||||
func (b *BaseWidget) SetPosition(x, y int) {
|
||||
b.x, b.y = x, y
|
||||
}
|
||||
|
||||
// OffsetPosition moves the widget by x and y
|
||||
func (b *BaseWidget) OffsetPosition(x, y int) {
|
||||
b.x += x
|
||||
b.y += y
|
||||
}
|
||||
|
||||
// GetPosition returns the position of the widget
|
||||
func (b *BaseWidget) GetPosition() (x, y int) {
|
||||
return b.x, b.y
|
||||
}
|
||||
|
||||
// GetVisible returns whether the widget is visible
|
||||
func (b *BaseWidget) GetVisible() (visible bool) {
|
||||
return b.visible
|
||||
}
|
||||
|
||||
// SetVisible make the widget visible, not visible
|
||||
func (b *BaseWidget) SetVisible(visible bool) {
|
||||
b.visible = visible
|
||||
}
|
||||
|
||||
// GetRenderPriority returns the order in which this widget is rendered
|
||||
func (b *BaseWidget) GetRenderPriority() (prio RenderPriority) {
|
||||
return b.renderPriority
|
||||
}
|
||||
|
||||
// SetRenderPriority sets the order in which this widget is rendered
|
||||
func (b *BaseWidget) SetRenderPriority(prio RenderPriority) {
|
||||
b.renderPriority = prio
|
||||
}
|
||||
|
92
d2core/d2ui/widget_group.go
Normal file
92
d2core/d2ui/widget_group.go
Normal file
@ -0,0 +1,92 @@
|
||||
package d2ui
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
// static check that WidgetGroup implements widget
|
||||
var _ Widget = &WidgetGroup{}
|
||||
|
||||
// WidgetGroup allows the grouping of widgets to apply actions to all
|
||||
// widgets at once.
|
||||
type WidgetGroup struct {
|
||||
*BaseWidget
|
||||
entries []Widget
|
||||
priority RenderPriority
|
||||
}
|
||||
|
||||
// NewWidgetGroup creates a new widget group
|
||||
func (ui *UIManager) NewWidgetGroup(priority RenderPriority) *WidgetGroup {
|
||||
base := NewBaseWidget(ui)
|
||||
base.SetRenderPriority(priority)
|
||||
|
||||
group := &WidgetGroup{
|
||||
BaseWidget: base,
|
||||
}
|
||||
|
||||
ui.addWidgetGroup(group)
|
||||
|
||||
return group
|
||||
}
|
||||
|
||||
// AddWidget adds a widget to the group
|
||||
func (wg *WidgetGroup) AddWidget(w Widget) {
|
||||
wg.adjustSize(w)
|
||||
wg.entries = append(wg.entries, w)
|
||||
sort.SliceStable(wg.entries, func(i, j int) bool {
|
||||
return wg.entries[i].GetRenderPriority() < wg.entries[j].GetRenderPriority()
|
||||
})
|
||||
}
|
||||
|
||||
// adjustSize recalculates the bounding box if a new widget is added
|
||||
func (wg *WidgetGroup) adjustSize(w Widget) {
|
||||
x, y := w.GetPosition()
|
||||
width, height := w.GetSize()
|
||||
|
||||
if x+width > wg.width {
|
||||
wg.width = x + width
|
||||
}
|
||||
|
||||
if wg.x > x {
|
||||
wg.width += wg.x - x
|
||||
wg.x = x
|
||||
}
|
||||
|
||||
if y+height > wg.height {
|
||||
wg.height = x + height
|
||||
}
|
||||
|
||||
if wg.y > y {
|
||||
wg.height += wg.y - y
|
||||
wg.y = y
|
||||
}
|
||||
}
|
||||
|
||||
// Advance is a no-op here
|
||||
func (wg *WidgetGroup) Advance(elapsed float64) error {
|
||||
// No-op
|
||||
return nil
|
||||
}
|
||||
|
||||
// Render draw the widgets to the screen
|
||||
func (wg *WidgetGroup) Render(target d2interface.Surface) error {
|
||||
for _, entry := range wg.entries {
|
||||
if entry.GetVisible() {
|
||||
err := entry.Render(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetVisible sets the visibility of all widgets in the group
|
||||
func (wg *WidgetGroup) SetVisible(visible bool) {
|
||||
for _, entry := range wg.entries {
|
||||
entry.SetVisible(visible)
|
||||
}
|
||||
}
|
@ -373,7 +373,7 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) {
|
||||
return
|
||||
}
|
||||
|
||||
v.d2HeroTitle.Render(screen)
|
||||
v.d2HeroTitle.RenderNoError(screen)
|
||||
actualSelectionIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
|
||||
|
||||
if v.selectedCharacter > -1 && actualSelectionIndex >= 0 && actualSelectionIndex < 8 {
|
||||
@ -388,12 +388,13 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) {
|
||||
continue
|
||||
}
|
||||
|
||||
v.characterNameLabel[i].Render(screen)
|
||||
v.characterStatsLabel[i].Render(screen)
|
||||
v.characterExpLabel[i].Render(screen)
|
||||
v.characterNameLabel[i].RenderNoError(screen)
|
||||
v.characterStatsLabel[i].RenderNoError(screen)
|
||||
v.characterExpLabel[i].RenderNoError(screen)
|
||||
|
||||
charImgX := v.characterNameLabel[i].X - selectionBoxImageOffsetX
|
||||
charImgY := v.characterNameLabel[i].Y + selectionBoxImageOffsetY
|
||||
x, y := v.characterNameLabel[i].GetPosition()
|
||||
charImgX := x - selectionBoxImageOffsetX
|
||||
charImgY := y + selectionBoxImageOffsetY
|
||||
screen.PushTranslation(charImgX, charImgY)
|
||||
v.characterImage[i].Render(screen)
|
||||
screen.Pop()
|
||||
@ -406,7 +407,7 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) {
|
||||
return
|
||||
}
|
||||
|
||||
v.deleteCharConfirmLabel.Render(screen)
|
||||
v.deleteCharConfirmLabel.RenderNoError(screen)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ func (v *Credits) Render(screen d2interface.Surface) {
|
||||
continue
|
||||
}
|
||||
|
||||
label.Label.Render(screen)
|
||||
label.Label.RenderNoError(screen)
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,11 +159,14 @@ func (v *Credits) Advance(tickTime float64) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if label.Label.Y-1 < -15 {
|
||||
_, y := label.Label.GetPosition()
|
||||
|
||||
if y-1 < -15 {
|
||||
label.Available = true
|
||||
continue
|
||||
}
|
||||
label.Label.Y--
|
||||
|
||||
label.Label.OffsetPosition(0, -1)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,31 +452,31 @@ func (v *MainMenu) renderBackgrounds(screen d2interface.Surface) {
|
||||
func (v *MainMenu) renderLogos(screen d2interface.Surface) {
|
||||
switch v.screenMode {
|
||||
case ScreenModeTrademark, ScreenModeMainMenu, ScreenModeMultiplayer:
|
||||
v.diabloLogoLeftBack.Render(screen)
|
||||
v.diabloLogoRightBack.Render(screen)
|
||||
v.diabloLogoLeft.Render(screen)
|
||||
v.diabloLogoRight.Render(screen)
|
||||
v.diabloLogoLeftBack.RenderNoError(screen)
|
||||
v.diabloLogoRightBack.RenderNoError(screen)
|
||||
v.diabloLogoLeft.RenderNoError(screen)
|
||||
v.diabloLogoRight.RenderNoError(screen)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *MainMenu) renderLabels(screen d2interface.Surface) {
|
||||
switch v.screenMode {
|
||||
case ScreenModeServerIP:
|
||||
v.tcpIPOptionsLabel.Render(screen)
|
||||
v.tcpJoinGameLabel.Render(screen)
|
||||
v.tcpIPOptionsLabel.RenderNoError(screen)
|
||||
v.tcpJoinGameLabel.RenderNoError(screen)
|
||||
case ScreenModeTCPIP:
|
||||
v.tcpIPOptionsLabel.Render(screen)
|
||||
v.tcpIPOptionsLabel.RenderNoError(screen)
|
||||
case ScreenModeTrademark:
|
||||
v.copyrightLabel.Render(screen)
|
||||
v.copyrightLabel2.Render(screen)
|
||||
v.copyrightLabel.RenderNoError(screen)
|
||||
v.copyrightLabel2.RenderNoError(screen)
|
||||
|
||||
if v.errorLabel != nil {
|
||||
v.errorLabel.Render(screen)
|
||||
v.errorLabel.RenderNoError(screen)
|
||||
}
|
||||
case ScreenModeMainMenu:
|
||||
v.openDiabloLabel.Render(screen)
|
||||
v.versionLabel.Render(screen)
|
||||
v.commitLabel.Render(screen)
|
||||
v.openDiabloLabel.RenderNoError(screen)
|
||||
v.versionLabel.RenderNoError(screen)
|
||||
v.commitLabel.RenderNoError(screen)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -515,13 +515,13 @@ func (v *SelectHeroClass) Render(screen d2interface.Surface) {
|
||||
return
|
||||
}
|
||||
|
||||
v.headingLabel.Render(screen)
|
||||
v.headingLabel.RenderNoError(screen)
|
||||
|
||||
if v.selectedHero != d2enum.HeroNone {
|
||||
v.heroClassLabel.Render(screen)
|
||||
v.heroDesc1Label.Render(screen)
|
||||
v.heroDesc2Label.Render(screen)
|
||||
v.heroDesc3Label.Render(screen)
|
||||
v.heroClassLabel.RenderNoError(screen)
|
||||
v.heroDesc1Label.RenderNoError(screen)
|
||||
v.heroDesc2Label.RenderNoError(screen)
|
||||
v.heroDesc3Label.RenderNoError(screen)
|
||||
}
|
||||
|
||||
for heroClass, heroInfo := range v.heroRenderInfo {
|
||||
@ -536,12 +536,12 @@ func (v *SelectHeroClass) Render(screen d2interface.Surface) {
|
||||
}
|
||||
}
|
||||
|
||||
v.campfire.Render(screen)
|
||||
v.campfire.RenderNoError(screen)
|
||||
|
||||
if v.heroNameTextbox.GetVisible() {
|
||||
v.heroNameLabel.Render(screen)
|
||||
v.expansionCharLabel.Render(screen)
|
||||
v.hardcoreCharLabel.Render(screen)
|
||||
v.heroNameLabel.RenderNoError(screen)
|
||||
v.expansionCharLabel.RenderNoError(screen)
|
||||
v.hardcoreCharLabel.RenderNoError(screen)
|
||||
}
|
||||
}
|
||||
|
||||
@ -739,7 +739,7 @@ func setSpriteToFirstFrame(sprite *d2ui.Sprite) {
|
||||
|
||||
func drawSprite(sprite *d2ui.Sprite, target d2interface.Surface) {
|
||||
if sprite != nil {
|
||||
sprite.Render(target)
|
||||
sprite.RenderNoError(target)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,7 +370,7 @@ func NewGameControls(
|
||||
inputListener: inputListener,
|
||||
mapRenderer: mapRenderer,
|
||||
inventory: NewInventory(asset, ui, inventoryRecord),
|
||||
skilltree: newSkillTree(hero.Skills, hero.Class, asset, renderer, ui, guiManager),
|
||||
skilltree: newSkillTree(hero.Skills, hero.Class, asset, ui),
|
||||
heroStatsPanel: NewHeroStatsPanel(asset, ui, hero.Name(), hero.Class, hero.Stats),
|
||||
HelpOverlay: helpOverlay,
|
||||
hud: hud,
|
||||
@ -773,11 +773,6 @@ func (g *GameControls) renderPanels(target d2interface.Surface) error {
|
||||
g.heroStatsPanel.Render(target)
|
||||
g.inventory.Render(target)
|
||||
|
||||
err := g.skilltree.Render(target)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -1014,18 +1009,23 @@ func (g *GameControls) bindLearnSkillsCommand(term d2interface.Terminal) error {
|
||||
continue
|
||||
}
|
||||
|
||||
skill, skillErr := g.heroState.CreateHeroSkill(1, skillDetailRecord.Skill)
|
||||
if skill == nil {
|
||||
continue
|
||||
}
|
||||
if skill, ok := g.hero.Skills[skillDetailRecord.ID]; ok {
|
||||
skill.SkillPoints++
|
||||
learnedSkillsCount++
|
||||
} else {
|
||||
skill, skillErr := g.heroState.CreateHeroSkill(1, skillDetailRecord.Skill)
|
||||
if skill == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
learnedSkillsCount++
|
||||
learnedSkillsCount++
|
||||
|
||||
g.hero.Skills[skill.ID] = skill
|
||||
g.hero.Skills[skill.ID] = skill
|
||||
|
||||
if skillErr != nil {
|
||||
err = skillErr
|
||||
break
|
||||
if skillErr != nil {
|
||||
err = skillErr
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,11 +620,11 @@ func (h *HelpOverlay) Render(target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
for _, f := range h.frames {
|
||||
f.Render(target)
|
||||
f.RenderNoError(target)
|
||||
}
|
||||
|
||||
for _, t := range h.text {
|
||||
t.Render(target)
|
||||
t.RenderNoError(target)
|
||||
}
|
||||
|
||||
for _, l := range h.lines {
|
||||
|
@ -242,7 +242,7 @@ func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) err
|
||||
s.panel.SetPosition(currentX-w, currentY+h)
|
||||
}
|
||||
|
||||
s.panel.Render(target)
|
||||
s.panel.RenderNoError(target)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -295,7 +295,7 @@ func (s *HeroStatsPanel) renderStaticLabels(target d2interface.Surface) {
|
||||
cfg.centerAlign,
|
||||
})
|
||||
|
||||
label.Render(target)
|
||||
label.RenderNoError(target)
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@ func (s *HeroStatsPanel) renderStatValues(target d2interface.Surface) {
|
||||
func (s *HeroStatsPanel) renderStatValueNum(label *d2ui.Label, value int,
|
||||
target d2interface.Surface) {
|
||||
label.SetText(strconv.Itoa(value))
|
||||
label.Render(target)
|
||||
label.RenderNoError(target)
|
||||
}
|
||||
|
||||
func (s *HeroStatsPanel) createStatValueLabel(stat, x, y int) *d2ui.Label {
|
||||
|
@ -391,7 +391,7 @@ func (h *HUD) renderManaGlobe(x, _ int, target d2interface.Surface) error {
|
||||
|
||||
h.mainPanel.SetPosition(x, height)
|
||||
|
||||
h.mainPanel.Render(target)
|
||||
h.mainPanel.RenderNoError(target)
|
||||
|
||||
// Mana status bar
|
||||
manaPercent := float64(h.hero.Stats.Mana) / float64(h.hero.Stats.MaxMana)
|
||||
@ -413,8 +413,8 @@ func (h *HUD) renderManaGlobe(x, _ int, target d2interface.Surface) error {
|
||||
|
||||
h.globeSprite.SetPosition(x+rightGlobeOffsetX, height+rightGlobeOffsetY)
|
||||
|
||||
h.globeSprite.Render(target)
|
||||
h.globeSprite.Render(target)
|
||||
h.globeSprite.RenderNoError(target)
|
||||
h.globeSprite.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -438,7 +438,7 @@ func (h *HUD) renderHealthGlobe(x, y int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.globeSprite.SetPosition(x+globeSpriteOffsetX, y+globeSpriteOffsetY)
|
||||
h.globeSprite.Render(target)
|
||||
h.globeSprite.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -449,7 +449,7 @@ func (h *HUD) renderPanel(x, y int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.mainPanel.SetPosition(x, y)
|
||||
h.mainPanel.Render(target)
|
||||
h.mainPanel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -466,7 +466,7 @@ func (h *HUD) renderLeftSkill(x, y int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.leftSkillResource.SkillIcon.SetPosition(x, y)
|
||||
h.leftSkillResource.SkillIcon.Render(target)
|
||||
h.leftSkillResource.SkillIcon.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -485,7 +485,7 @@ func (h *HUD) renderRightSkill(x, _ int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.rightSkillResource.SkillIcon.SetPosition(x, height)
|
||||
h.rightSkillResource.SkillIcon.Render(target)
|
||||
h.rightSkillResource.SkillIcon.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -496,7 +496,7 @@ func (h *HUD) renderNewStatsButton(x, y int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.mainPanel.SetPosition(x, y)
|
||||
h.mainPanel.Render(target)
|
||||
h.mainPanel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -507,7 +507,7 @@ func (h *HUD) renderStamina(x, y int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.mainPanel.SetPosition(x, y)
|
||||
h.mainPanel.Render(target)
|
||||
h.mainPanel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -558,7 +558,7 @@ func (h *HUD) renderMiniPanel(target d2interface.Surface) error {
|
||||
buttonX, buttonY := (width>>1)+miniPanelButtonOffsetX, height+miniPanelButtonOffsetY
|
||||
|
||||
h.menuButton.SetPosition(buttonX, buttonY)
|
||||
h.menuButton.Render(target)
|
||||
h.menuButton.RenderNoError(target)
|
||||
h.miniPanel.Render(target)
|
||||
|
||||
miniPanelButtons := map[actionableType]string{
|
||||
@ -595,7 +595,10 @@ func (h *HUD) renderMiniPanel(target d2interface.Surface) error {
|
||||
labelY := centerY - halfButtonHeight - labelHeight
|
||||
|
||||
h.miniPanelTooltip.SetPosition(labelX, labelY)
|
||||
h.miniPanelTooltip.Render(target)
|
||||
|
||||
if err := h.miniPanelTooltip.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -609,7 +612,7 @@ func (h *HUD) renderPotions(x, _ int, target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
h.mainPanel.SetPosition(x, height)
|
||||
h.mainPanel.Render(target)
|
||||
h.mainPanel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -622,11 +625,12 @@ func (h *HUD) renderNewSkillsButton(x, _ int, target d2interface.Surface) error
|
||||
}
|
||||
|
||||
h.mainPanel.SetPosition(x, height)
|
||||
h.mainPanel.Render(target)
|
||||
h.mainPanel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint:golint,dupl // we clean this up later
|
||||
func (h *HUD) renderHealthTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
@ -641,9 +645,13 @@ func (h *HUD) renderHealthTooltip(target d2interface.Surface) {
|
||||
}
|
||||
|
||||
h.healthTooltip.SetText(strPanelHealth)
|
||||
h.healthTooltip.Render(target)
|
||||
|
||||
if err := h.healthTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:golint,dupl // we clean this up later
|
||||
func (h *HUD) renderManaTooltip(target d2interface.Surface) {
|
||||
mx, my := h.lastMouseX, h.lastMouseY
|
||||
|
||||
@ -657,7 +665,10 @@ func (h *HUD) renderManaTooltip(target d2interface.Surface) {
|
||||
}
|
||||
|
||||
h.manaTooltip.SetText(strPanelMana)
|
||||
h.manaTooltip.Render(target)
|
||||
|
||||
if err := h.manaTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HUD) renderRunWalkTooltip(target d2interface.Surface) {
|
||||
@ -679,7 +690,9 @@ func (h *HUD) renderRunWalkTooltip(target d2interface.Surface) {
|
||||
|
||||
h.runWalkTooltip.SetText(h.asset.TranslateString(stringTableKey))
|
||||
|
||||
h.runWalkTooltip.Render(target)
|
||||
if err := h.runWalkTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HUD) renderStaminaTooltip(target d2interface.Surface) {
|
||||
@ -696,7 +709,10 @@ func (h *HUD) renderStaminaTooltip(target d2interface.Surface) {
|
||||
strPanelStamina := fmt.Sprintf(fmtStamina, staminaCurr, staminaMax)
|
||||
|
||||
h.staminaTooltip.SetText(strPanelStamina)
|
||||
h.staminaTooltip.Render(target)
|
||||
|
||||
if err := h.staminaTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HUD) renderExperienceTooltip(target d2interface.Surface) {
|
||||
@ -720,7 +736,10 @@ func (h *HUD) renderExperienceTooltip(target d2interface.Surface) {
|
||||
strPanelExp := fmt.Sprintf(fmtExp, expCurr, expMax)
|
||||
|
||||
h.experienceTooltip.SetText(strPanelExp)
|
||||
h.experienceTooltip.Render(target)
|
||||
|
||||
if err := h.experienceTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HUD) renderForSelectableEntitiesHovered(target d2interface.Surface) {
|
||||
@ -753,7 +772,7 @@ func (h *HUD) renderForSelectableEntitiesHovered(target d2interface.Surface) {
|
||||
xLabel, yLabel := entScreenX-xOff, entScreenY-yOff-entityHeight-hoverLabelOuterPad
|
||||
h.nameLabel.SetPosition(xLabel, yLabel)
|
||||
|
||||
h.nameLabel.Render(target)
|
||||
h.nameLabel.RenderNoError(target)
|
||||
entity.Highlight()
|
||||
|
||||
break
|
||||
@ -775,7 +794,7 @@ func (h *HUD) Render(target d2interface.Surface) error {
|
||||
|
||||
if h.isZoneTextShown {
|
||||
h.zoneChangeText.SetPosition(zoneChangeTextX, zoneChangeTextY)
|
||||
h.zoneChangeText.Render(target)
|
||||
h.zoneChangeText.RenderNoError(target)
|
||||
}
|
||||
|
||||
h.renderHealthTooltip(target)
|
||||
|
@ -196,7 +196,7 @@ func (g *Inventory) renderFrame(target d2interface.Surface) error {
|
||||
w, h := g.panel.GetCurrentFrameSize()
|
||||
|
||||
g.panel.SetPosition(x, y+h)
|
||||
g.panel.Render(target)
|
||||
g.panel.RenderNoError(target)
|
||||
|
||||
switch frame {
|
||||
case frameInventoryTopLeft:
|
||||
@ -242,5 +242,8 @@ func (g *Inventory) renderItemDescription(target d2interface.Surface, i Inventor
|
||||
g.itemTooltip.SetTextLines(lines)
|
||||
_, y := g.grid.SlotToScreen(i.InventoryGridSlot())
|
||||
g.itemTooltip.SetPosition(g.hoverX, y)
|
||||
g.itemTooltip.Render(target)
|
||||
|
||||
if err := g.itemTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
@ -234,7 +234,7 @@ func (g *ItemGrid) renderItem(item InventoryItem, target d2interface.Surface, x,
|
||||
if itemSprite != nil {
|
||||
itemSprite.SetPosition(x, y)
|
||||
itemSprite.GetCurrentFrameSize()
|
||||
itemSprite.Render(target)
|
||||
itemSprite.RenderNoError(target)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ func (m *miniPanel) Render(target d2interface.Surface) {
|
||||
|
||||
m.container.SetPosition(x, y)
|
||||
|
||||
m.container.Render(target)
|
||||
m.container.RenderNoError(target)
|
||||
|
||||
buttonWidth, _ := m.button.GetCurrentFrameSize()
|
||||
buttonWidth++
|
||||
@ -122,7 +122,7 @@ func (m *miniPanel) Render(target d2interface.Surface) {
|
||||
x, y := halfW+offsetX, height+buttonOffsetY
|
||||
|
||||
m.button.SetPosition(x, y)
|
||||
m.button.Render(target)
|
||||
m.button.RenderNoError(target)
|
||||
|
||||
j += 2
|
||||
}
|
||||
|
@ -129,7 +129,9 @@ func (s *SkillPanel) Render(target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
if s.hoveredSkill != nil {
|
||||
s.hoverTooltip.Render(target)
|
||||
if err := s.hoverTooltip.Render(target); err != nil {
|
||||
log.Printf("Cannot render tooltip, %e", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -240,7 +242,7 @@ func (s *SkillPanel) createSkillListImage(skillsListRow *SkillListRow) (d2interf
|
||||
}
|
||||
|
||||
surface.PushTranslation(idx*skillIconWidth, 50)
|
||||
skillSprite.Render(surface)
|
||||
skillSprite.RenderNoError(surface)
|
||||
surface.Pop()
|
||||
}
|
||||
|
||||
|
99
d2game/d2player/skillicon.go
Normal file
99
d2game/d2player/skillicon.go
Normal file
@ -0,0 +1,99 @@
|
||||
package d2player
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2hero"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||
)
|
||||
|
||||
const (
|
||||
skillLabelXOffset = 49
|
||||
skillLabelYOffset = -4
|
||||
|
||||
skillIconXOff = 346
|
||||
skillIconYOff = 59
|
||||
skillIconDistX = 69
|
||||
skillIconDistY = 68
|
||||
)
|
||||
|
||||
type skillIcon struct {
|
||||
*d2ui.BaseWidget
|
||||
lvlLabel *d2ui.Label
|
||||
sprite *d2ui.Sprite
|
||||
skill *d2hero.HeroSkill
|
||||
}
|
||||
|
||||
func newSkillIcon(ui *d2ui.UIManager, baseSprite *d2ui.Sprite, skill *d2hero.HeroSkill) *skillIcon {
|
||||
base := d2ui.NewBaseWidget(ui)
|
||||
label := ui.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
||||
|
||||
x := skillIconXOff + skill.SkillColumn*skillIconDistX
|
||||
y := skillIconYOff + skill.SkillRow*skillIconDistY
|
||||
|
||||
res := &skillIcon{
|
||||
BaseWidget: base,
|
||||
sprite: baseSprite,
|
||||
skill: skill,
|
||||
lvlLabel: label,
|
||||
}
|
||||
|
||||
res.SetPosition(x, y)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (si *skillIcon) SetVisible(visible bool) {
|
||||
si.BaseWidget.SetVisible(visible)
|
||||
si.lvlLabel.SetVisible(visible)
|
||||
}
|
||||
|
||||
func (si *skillIcon) renderSprite(target d2interface.Surface) error {
|
||||
x, y := si.GetPosition()
|
||||
|
||||
if err := si.sprite.SetCurrentFrame(si.skill.IconCel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if si.skill.SkillPoints == 0 {
|
||||
target.PushSaturation(skillIconGreySat)
|
||||
defer target.Pop()
|
||||
|
||||
target.PushBrightness(skillIconGreyBright)
|
||||
defer target.Pop()
|
||||
}
|
||||
|
||||
si.sprite.SetPosition(x, y)
|
||||
|
||||
if err := si.sprite.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (si *skillIcon) renderSpriteLabel(target d2interface.Surface) error {
|
||||
if si.skill.SkillPoints == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
x, y := si.GetPosition()
|
||||
si.lvlLabel.SetText(strconv.Itoa(si.skill.SkillPoints))
|
||||
si.lvlLabel.SetPosition(x+skillLabelXOffset, y+skillLabelYOffset)
|
||||
|
||||
return si.lvlLabel.Render(target)
|
||||
}
|
||||
|
||||
func (si *skillIcon) Render(target d2interface.Surface) error {
|
||||
if err := si.renderSprite(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return si.renderSpriteLabel(target)
|
||||
}
|
||||
|
||||
func (si *skillIcon) Advance(elapsed float64) error {
|
||||
return nil
|
||||
}
|
@ -3,7 +3,6 @@ package d2player
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
@ -23,14 +22,6 @@ const (
|
||||
availSPLabelX = 677
|
||||
availSPLabelY = 72
|
||||
|
||||
skillIconXOff = 346
|
||||
skillIconYOff = 59
|
||||
skillIconDistX = 69
|
||||
skillIconDistY = 68
|
||||
|
||||
skillLabelXOffset = 49
|
||||
skillLabelYOffset = -4
|
||||
|
||||
skillCloseButtonXLeft = 416
|
||||
skillCloseButtonXMiddle = 501
|
||||
skillCloseButtonXRight = 572
|
||||
@ -83,55 +74,50 @@ type skillTreeTab struct {
|
||||
|
||||
func (st *skillTreeTab) createButton(uiManager *d2ui.UIManager, x, y int) {
|
||||
st.button = uiManager.NewButton(d2ui.ButtonTypeSkillTreeTab, st.buttonText)
|
||||
st.button.SetVisible(false)
|
||||
st.button.SetPosition(x, y)
|
||||
}
|
||||
|
||||
type skillTreeHeroTypeResources struct {
|
||||
skillIcon *d2ui.Sprite
|
||||
skillSprite *d2ui.Sprite
|
||||
skillIconPath string
|
||||
skillPanel *d2ui.Sprite
|
||||
skillPanelPath string
|
||||
}
|
||||
|
||||
type skillTree struct {
|
||||
resources *skillTreeHeroTypeResources
|
||||
asset *d2asset.AssetManager
|
||||
renderer d2interface.Renderer
|
||||
guiManager *d2gui.GuiManager
|
||||
uiManager *d2ui.UIManager
|
||||
layout *d2gui.Layout
|
||||
skills map[int]*d2hero.HeroSkill
|
||||
heroClass d2enum.Hero
|
||||
frame *d2ui.UIFrame
|
||||
availSPLabel *d2ui.Label
|
||||
skillLvlLabel *d2ui.Label
|
||||
closeButton *d2ui.Button
|
||||
tab [numTabs]*skillTreeTab
|
||||
isOpen bool
|
||||
originX int
|
||||
originY int
|
||||
selectedTab int
|
||||
onCloseCb func()
|
||||
resources *skillTreeHeroTypeResources
|
||||
asset *d2asset.AssetManager
|
||||
uiManager *d2ui.UIManager
|
||||
skills map[int]*d2hero.HeroSkill
|
||||
skillIcons []*skillIcon
|
||||
heroClass d2enum.Hero
|
||||
frame *d2ui.UIFrame
|
||||
availSPLabel *d2ui.Label
|
||||
closeButton *d2ui.Button
|
||||
tab [numTabs]*skillTreeTab
|
||||
isOpen bool
|
||||
originX int
|
||||
originY int
|
||||
selectedTab int
|
||||
onCloseCb func()
|
||||
panelGroup *d2ui.WidgetGroup
|
||||
iconGroup *d2ui.WidgetGroup
|
||||
panel *d2ui.CustomWidget
|
||||
}
|
||||
|
||||
func newSkillTree(
|
||||
skills map[int]*d2hero.HeroSkill,
|
||||
heroClass d2enum.Hero,
|
||||
asset *d2asset.AssetManager,
|
||||
renderer d2interface.Renderer,
|
||||
ui *d2ui.UIManager,
|
||||
guiManager *d2gui.GuiManager,
|
||||
) *skillTree {
|
||||
st := &skillTree{
|
||||
skills: skills,
|
||||
heroClass: heroClass,
|
||||
asset: asset,
|
||||
renderer: renderer,
|
||||
uiManager: ui,
|
||||
guiManager: guiManager,
|
||||
originX: skillTreePanelX,
|
||||
originY: skillTreePanelY,
|
||||
skills: skills,
|
||||
heroClass: heroClass,
|
||||
asset: asset,
|
||||
uiManager: ui,
|
||||
originX: skillTreePanelX,
|
||||
originY: skillTreePanelY,
|
||||
tab: [numTabs]*skillTreeTab{
|
||||
{},
|
||||
{},
|
||||
@ -143,16 +129,32 @@ func newSkillTree(
|
||||
}
|
||||
|
||||
func (s *skillTree) load() {
|
||||
s.panelGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPrioritySkilltree)
|
||||
s.iconGroup = s.uiManager.NewWidgetGroup(d2ui.RenderPrioritySkilltreeIcon)
|
||||
|
||||
s.panel = s.uiManager.NewCustomWidget(s.Render)
|
||||
s.panelGroup.AddWidget(s.panel)
|
||||
|
||||
s.frame = d2ui.NewUIFrame(s.asset, s.uiManager, d2ui.FrameRight)
|
||||
s.panelGroup.AddWidget(s.frame)
|
||||
|
||||
s.closeButton = s.uiManager.NewButton(d2ui.ButtonTypeSquareClose, "")
|
||||
s.closeButton.SetVisible(false)
|
||||
s.closeButton.OnActivated(func() { s.Close() })
|
||||
|
||||
s.skillLvlLabel = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
||||
s.panelGroup.AddWidget(s.closeButton)
|
||||
|
||||
s.setHeroTypeResourcePath()
|
||||
s.loadForHeroType()
|
||||
|
||||
for _, skill := range s.skills {
|
||||
si := newSkillIcon(s.uiManager, s.resources.skillSprite, skill)
|
||||
s.skillIcons = append(s.skillIcons, si)
|
||||
s.iconGroup.AddWidget(si)
|
||||
}
|
||||
|
||||
s.panelGroup.SetVisible(false)
|
||||
s.setTab(0)
|
||||
s.iconGroup.SetVisible(false)
|
||||
}
|
||||
|
||||
func (s *skillTree) loadForHeroType() {
|
||||
@ -168,21 +170,25 @@ func (s *skillTree) loadForHeroType() {
|
||||
log.Print(err)
|
||||
}
|
||||
|
||||
s.resources.skillIcon = si
|
||||
s.resources.skillSprite = si
|
||||
|
||||
s.tab[firstTab].createButton(s.uiManager, tabButtonX, tabButton0Y)
|
||||
s.tab[firstTab].button.OnActivated(func() { s.setTab(firstTab) })
|
||||
s.panelGroup.AddWidget(s.tab[firstTab].button)
|
||||
|
||||
s.tab[secondTab].createButton(s.uiManager, tabButtonX, tabButton1Y)
|
||||
s.tab[secondTab].button.OnActivated(func() { s.setTab(secondTab) })
|
||||
s.panelGroup.AddWidget(s.tab[secondTab].button)
|
||||
|
||||
s.tab[thirdTab].createButton(s.uiManager, tabButtonX, tabButton2Y)
|
||||
s.tab[thirdTab].button.OnActivated(func() { s.setTab(thirdTab) })
|
||||
s.panelGroup.AddWidget(s.tab[thirdTab].button)
|
||||
|
||||
s.availSPLabel = s.uiManager.NewLabel(d2resource.Font16, d2resource.PaletteSky)
|
||||
s.availSPLabel.SetPosition(availSPLabelX, availSPLabelY)
|
||||
s.availSPLabel.Alignment = d2gui.HorizontalAlignCenter
|
||||
s.availSPLabel.SetText(s.makeTabString("StrSklTree1", "StrSklTree2", "StrSklTree3"))
|
||||
s.panelGroup.AddWidget(s.availSPLabel)
|
||||
}
|
||||
|
||||
type heroTabData struct {
|
||||
@ -340,12 +346,9 @@ func (s *skillTree) Toggle() {
|
||||
// Close the skill tree
|
||||
func (s *skillTree) Close() {
|
||||
s.isOpen = false
|
||||
s.guiManager.SetLayout(nil)
|
||||
s.closeButton.SetVisible(false)
|
||||
|
||||
for i := 0; i < numTabs; i++ {
|
||||
s.tab[i].button.SetVisible(false)
|
||||
}
|
||||
s.panelGroup.SetVisible(false)
|
||||
s.iconGroup.SetVisible(false)
|
||||
|
||||
s.onCloseCb()
|
||||
}
|
||||
@ -353,17 +356,11 @@ func (s *skillTree) Close() {
|
||||
// Open the skill tree
|
||||
func (s *skillTree) Open() {
|
||||
s.isOpen = true
|
||||
if s.layout == nil {
|
||||
s.layout = d2gui.CreateLayout(s.renderer, d2gui.PositionTypeHorizontal, s.asset)
|
||||
}
|
||||
|
||||
s.closeButton.SetVisible(true)
|
||||
s.panelGroup.SetVisible(true)
|
||||
|
||||
for i := 0; i < numTabs; i++ {
|
||||
s.tab[i].button.SetVisible(true)
|
||||
}
|
||||
|
||||
s.guiManager.SetLayout(s.layout)
|
||||
// we only want to enable the icons of our current tab again
|
||||
s.setTab(s.selectedTab)
|
||||
}
|
||||
|
||||
func (s *skillTree) IsOpen() bool {
|
||||
@ -378,6 +375,10 @@ func (s *skillTree) SetOnCloseCb(cb func()) {
|
||||
func (s *skillTree) setTab(tab int) {
|
||||
s.selectedTab = tab
|
||||
s.closeButton.SetPosition(s.tab[tab].closeButtonPosX, skillCloseButtonY)
|
||||
|
||||
for _, si := range s.skillIcons {
|
||||
si.SetVisible(si.skill.SkillPage == tab+1)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *skillTree) renderPanelSegment(
|
||||
@ -387,7 +388,7 @@ func (s *skillTree) renderPanelSegment(
|
||||
return err
|
||||
}
|
||||
|
||||
s.resources.skillPanel.Render(target)
|
||||
s.resources.skillPanel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -441,7 +442,7 @@ func (s *skillTree) renderTabCommon(target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
// available skill points label
|
||||
s.availSPLabel.Render(target)
|
||||
s.availSPLabel.RenderNoError(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -512,69 +513,8 @@ func (s *skillTree) renderTab(target d2interface.Surface, tab int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *skillTree) renderSkillIcon(target d2interface.Surface, skill *d2hero.HeroSkill) error {
|
||||
skillIcon := s.resources.skillIcon
|
||||
if err := skillIcon.SetCurrentFrame(skill.IconCel); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
x := skillIconXOff + skill.SkillColumn*skillIconDistX
|
||||
y := skillIconYOff + skill.SkillRow*skillIconDistY
|
||||
|
||||
skillIcon.SetPosition(x, y)
|
||||
|
||||
if skill.SkillPoints == 0 {
|
||||
target.PushSaturation(skillIconGreySat)
|
||||
defer target.Pop()
|
||||
|
||||
target.PushBrightness(skillIconGreyBright)
|
||||
defer target.Pop()
|
||||
}
|
||||
|
||||
skillIcon.Render(target)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *skillTree) renderSkillIconLabel(target d2interface.Surface, skill *d2hero.HeroSkill) {
|
||||
if skill.SkillPoints == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
s.skillLvlLabel.SetText(strconv.Itoa(skill.SkillPoints))
|
||||
x := skillIconXOff + skill.SkillColumn*skillIconDistX + skillLabelXOffset
|
||||
y := skillIconYOff + skill.SkillRow*skillIconDistY + skillLabelYOffset
|
||||
s.skillLvlLabel.SetPosition(x, y)
|
||||
s.skillLvlLabel.Render(target)
|
||||
}
|
||||
|
||||
func (s *skillTree) renderSkillIcons(target d2interface.Surface, tab int) error {
|
||||
for idx := range s.skills {
|
||||
skill := s.skills[idx]
|
||||
if skill.SkillPage != tab+1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := s.renderSkillIcon(target, skill); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.renderSkillIconLabel(target, skill)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Render the skill tree panel
|
||||
func (s *skillTree) Render(target d2interface.Surface) error {
|
||||
if !s.isOpen {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := s.frame.Render(target); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.renderTabCommon(target); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -583,9 +523,5 @@ func (s *skillTree) Render(target d2interface.Surface) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.renderSkillIcons(target, s.selectedTab); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user