mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-17 09:56:07 -05:00
ba5ea334cc
* d2player/hud: Make minipanel button a real ui/button * d2ui/button: Add implicit tooltips for now it is only for close buttons. * d2ui/frame: Add size caluclation now frame.GetSize() returns meaningful values. * d2ui/button: Add minipanel button types * d2ui/hero_stats_panel: Fix cached image being way to big * d2ui/widget_group: Fix widget groups size calculation * d2ui/widget_group: Add debug rendering * d2ui/widget_group: SetVisible() now sets the visibility of the group object * d2player: Refactor mini_panel we converted all elements to widgets. Thus rendering from game_controls is no longer neccessary. * d2ui/button: Add disabled color to layouts * d2player/gamecontrols: temp hide minipanel when in esc menu * d2ui/widget_group: Add OffsetPosition() method * d2player/mini_panel: Implement moving of minipanel this only occours when other panels are opened. * d2player/minipanel: Fix inv/skilltree/char closebuttons these would screw up the moving of the mini panel. * Fix linter * d2player/minipanel: Add tooltips to buttons * d2player/skilltree: Fix icon rendering
286 lines
6.0 KiB
Go
286 lines
6.0 KiB
Go
package d2ui
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
|
)
|
|
|
|
// static check that UIFrame implements Widget
|
|
var _ Widget = &UIFrame{}
|
|
|
|
type frameOrientation = int
|
|
|
|
// Frame orientations
|
|
const (
|
|
FrameLeft frameOrientation = iota
|
|
FrameRight
|
|
)
|
|
|
|
// 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
|
|
frame *Sprite
|
|
frameOrientation frameOrientation
|
|
}
|
|
|
|
// frame indices into dc6 images for panels
|
|
const (
|
|
leftFrameTopLeft = iota
|
|
leftFrameTopRight
|
|
leftFrameMiddleLeft
|
|
leftFrameBottomLeft
|
|
leftFrameBottomRight
|
|
rightFrameTopLeft
|
|
rightFrameTopRight
|
|
rightFrameMiddleRight
|
|
rightFrameBottomRight
|
|
rightFrameBottomLeft
|
|
)
|
|
|
|
// NewUIFrame creates a new Frame instance
|
|
func NewUIFrame(
|
|
asset *d2asset.AssetManager,
|
|
uiManager *UIManager,
|
|
frameOrientation frameOrientation,
|
|
) *UIFrame {
|
|
var originX, originY = 0, 0
|
|
|
|
switch frameOrientation {
|
|
case FrameLeft:
|
|
originX = 0
|
|
originY = 0
|
|
case FrameRight:
|
|
originX = 400
|
|
originY = 0
|
|
}
|
|
|
|
base := NewBaseWidget(uiManager)
|
|
base.SetPosition(originX, originY)
|
|
|
|
frame := &UIFrame{
|
|
BaseWidget: base,
|
|
asset: asset,
|
|
frameOrientation: frameOrientation,
|
|
}
|
|
frame.Load()
|
|
|
|
return frame
|
|
}
|
|
|
|
// Load the necessary frame resources
|
|
func (u *UIFrame) Load() {
|
|
sprite, err := u.manager.NewSprite(d2resource.Frame, d2resource.PaletteSky)
|
|
if err != nil {
|
|
log.Print(err)
|
|
}
|
|
|
|
u.frame = sprite
|
|
u.calculateSize()
|
|
}
|
|
|
|
func (u *UIFrame) calculateSize() {
|
|
var framesWidth, framesHeight []int
|
|
|
|
if u.frameOrientation == FrameLeft {
|
|
framesWidth = []int{
|
|
leftFrameTopLeft,
|
|
leftFrameTopRight,
|
|
}
|
|
framesHeight = []int{
|
|
leftFrameTopLeft,
|
|
leftFrameMiddleLeft,
|
|
leftFrameBottomLeft,
|
|
}
|
|
} else if u.frameOrientation == FrameRight {
|
|
framesWidth = []int{
|
|
rightFrameTopLeft,
|
|
rightFrameTopRight,
|
|
}
|
|
framesHeight = []int{
|
|
rightFrameTopRight,
|
|
rightFrameMiddleRight,
|
|
rightFrameBottomRight,
|
|
}
|
|
}
|
|
|
|
for i := range framesWidth {
|
|
w, _, err := u.frame.GetFrameSize(framesWidth[i])
|
|
if err != nil {
|
|
log.Print(err)
|
|
}
|
|
|
|
u.width += w
|
|
}
|
|
|
|
for i := range framesHeight {
|
|
_, h, err := u.frame.GetFrameSize(framesHeight[i])
|
|
if err != nil {
|
|
log.Print(err)
|
|
}
|
|
|
|
u.height += h
|
|
}
|
|
}
|
|
|
|
// Render the frame to the target surface
|
|
func (u *UIFrame) Render(target d2interface.Surface) {
|
|
switch u.frameOrientation {
|
|
case FrameLeft:
|
|
if err := u.renderLeft(target); err != nil {
|
|
log.Printf("Render error %e", err)
|
|
}
|
|
case FrameRight:
|
|
if err := u.renderRight(target); err != nil {
|
|
log.Printf("Render error %e", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (u *UIFrame) renderLeft(target d2interface.Surface) error {
|
|
// the frame pieces we are interested in.
|
|
framePieces := []int{
|
|
leftFrameTopLeft,
|
|
leftFrameTopRight,
|
|
leftFrameMiddleLeft,
|
|
leftFrameBottomLeft,
|
|
leftFrameBottomRight,
|
|
}
|
|
|
|
// the frame coordinates
|
|
coord := make(map[int]*struct{ x, y int })
|
|
|
|
startX, startY := u.GetPosition()
|
|
currentX, currentY := startX, startY
|
|
|
|
// first determine the coordinates for each frame
|
|
// the order that we check is important
|
|
for _, piece := range framePieces {
|
|
width, height, err := u.frame.GetFrameSize(piece)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c := &struct{ x, y int }{}
|
|
|
|
switch piece {
|
|
case leftFrameTopLeft:
|
|
c.x, c.y = currentX, currentY+height
|
|
currentX, currentY = currentX+width, currentY+height
|
|
case leftFrameTopRight:
|
|
c.x, c.y = currentX, startY+height
|
|
currentX = startX
|
|
case leftFrameMiddleLeft:
|
|
c.x, c.y = currentX, currentY+height
|
|
currentY += height
|
|
case leftFrameBottomLeft:
|
|
c.x, c.y = currentX, currentY+height
|
|
currentX += width
|
|
case leftFrameBottomRight:
|
|
c.x, c.y = currentX, currentY+height
|
|
}
|
|
|
|
coord[piece] = c
|
|
}
|
|
|
|
// now render the pieces with the coordinates
|
|
for idx, c := range coord {
|
|
err := u.renderFramePiece(target, c.x, c.y, idx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (u *UIFrame) renderRight(target d2interface.Surface) error {
|
|
// the frame pieces we are interested in.
|
|
framePieces := []int{
|
|
rightFrameTopLeft,
|
|
rightFrameTopRight,
|
|
rightFrameMiddleRight,
|
|
rightFrameBottomRight,
|
|
rightFrameBottomLeft,
|
|
}
|
|
|
|
// the frame coordinates
|
|
coord := make(map[int]*struct{ x, y int })
|
|
|
|
startX, startY := u.GetPosition()
|
|
currentX, currentY := startX, startY
|
|
|
|
// first determine the coordinates for each frame
|
|
// the order that we check is important
|
|
for _, piece := range framePieces {
|
|
width, height, err := u.frame.GetFrameSize(piece)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c := &struct{ x, y int }{}
|
|
|
|
switch piece {
|
|
case rightFrameTopLeft:
|
|
c.x, c.y = currentX, currentY+height
|
|
currentX += width
|
|
case rightFrameTopRight:
|
|
c.x, c.y = currentX, currentY+height
|
|
currentX += width
|
|
currentY += height
|
|
case rightFrameMiddleRight:
|
|
c.x, c.y = currentX-width, currentY+height
|
|
currentY += height
|
|
case rightFrameBottomRight:
|
|
c.x, c.y = currentX-width, currentY+height
|
|
currentX -= width
|
|
case rightFrameBottomLeft:
|
|
c.x, c.y = currentX-width, currentY+height
|
|
currentX += width
|
|
}
|
|
|
|
coord[piece] = c
|
|
}
|
|
|
|
// now render the pieces with the coordinates
|
|
for idx, c := range coord {
|
|
err := u.renderFramePiece(target, c.x, c.y, idx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetFrameBounds returns the maximum width and height of all frames in sprite.
|
|
func (u *UIFrame) GetFrameBounds() (width, height int) {
|
|
return u.frame.GetFrameBounds()
|
|
}
|
|
|
|
// GetFrameCount returns the number of frames in the sprite
|
|
func (u *UIFrame) GetFrameCount() int {
|
|
return u.frame.GetFrameCount()
|
|
}
|
|
|
|
func (u *UIFrame) renderFramePiece(sfc d2interface.Surface, x, y, idx int) error {
|
|
if err := u.frame.SetCurrentFrame(idx); err != nil {
|
|
return err
|
|
}
|
|
|
|
u.frame.SetPosition(x, y)
|
|
|
|
u.frame.Render(sfc)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Advance is a no-op
|
|
func (u *UIFrame) Advance(elapsed float64) error {
|
|
return nil
|
|
}
|