d2player/skilltree: Move every element to widgets

the uiManager now handles every element of the ui, so we don't need to
render elements manually in game_controls. Now we can also use
widget_groups to simplify handling the opening/closing of the panel.
This commit is contained in:
juander 2020-11-09 18:09:46 +01:00
parent 83acaefea2
commit 622bc832d3
4 changed files with 162 additions and 128 deletions

View File

@ -7,6 +7,10 @@ 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
)

View File

@ -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
}
@ -1015,7 +1010,7 @@ func (g *GameControls) bindLearnSkillsCommand(term d2interface.Terminal) error {
}
if skill, ok := g.hero.Skills[skillDetailRecord.ID]; ok {
skill.SkillPoints++;
skill.SkillPoints++
learnedSkillsCount++
} else {
skill, skillErr := g.heroState.CreateHeroSkill(1, skillDetailRecord.Skill)

View 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
}

View File

@ -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(
@ -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.RenderNoError(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.RenderNoError(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
}