1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-11-18 10:26:02 -05:00
OpenDiablo2/d2core/d2gui/layout.go

519 lines
13 KiB
Go
Raw Normal View History

package d2gui
import (
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 16:51:30 -04:00
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
)
const layoutDebug = false // turns on debug rendering stuff for layouts
const (
white = 0xffffff_ff
magenta = 0xff00ff_ff
grey2 = 0x808080_ff
green = 0x0000ff_ff
yellow = 0xffff00_ff
)
// VerticalAlign type, determines alignment along y-axis within a layout
type VerticalAlign int
// VerticalAlign types
const (
VerticalAlignTop VerticalAlign = iota
VerticalAlignMiddle
VerticalAlignBottom
)
// HorizontalAlign type, determines alignment along x-axis within a layout
type HorizontalAlign int
// Horizontal alignment types
const (
HorizontalAlignLeft HorizontalAlign = iota
HorizontalAlignCenter
HorizontalAlignRight
)
// PositionType determines layout positioning
type PositionType int
// Positioning types
const (
PositionTypeAbsolute PositionType = iota
PositionTypeVertical
PositionTypeHorizontal
)
// Layout is a gui element container which will automatically position/align gui elements.
// Layouts are gui elements as well, so they can be nested in other layouts.
type Layout struct {
widgetBase
renderer d2interface.Renderer
assetManager *d2asset.AssetManager
width int
height int
verticalAlign VerticalAlign
horizontalAlign HorizontalAlign
positionType PositionType
entries []*layoutEntry
}
// CreateLayout creates a new GUI layout
func CreateLayout(renderer d2interface.Renderer, positionType PositionType, assetManager *d2asset.AssetManager) *Layout {
layout := &Layout{
renderer: renderer,
positionType: positionType,
assetManager: assetManager,
}
layout.SetVisible(true)
return layout
}
// SetSize sets the size of the layout
func (l *Layout) SetSize(width, height int) {
l.width = width
l.height = height
}
// SetVerticalAlign sets the vertical alignment type of the layout
func (l *Layout) SetVerticalAlign(verticalAlign VerticalAlign) {
l.verticalAlign = verticalAlign
}
// SetHorizontalAlign sets the horizontal alignment type of the layout
func (l *Layout) SetHorizontalAlign(horizontalAlign HorizontalAlign) {
l.horizontalAlign = horizontalAlign
}
// AddLayout adds a nested layout to this layout, given a position type.
// Returns a pointer to the nested layout
func (l *Layout) AddLayout(positionType PositionType) *Layout {
layout := CreateLayout(l.renderer, positionType, l.assetManager)
l.entries = append(l.entries, &layoutEntry{widget: layout})
return layout
}
// AddSpacerStatic adds a spacer with explicitly defined height and width
func (l *Layout) AddSpacerStatic(width, height int) *SpacerStatic {
spacer := createSpacerStatic(width, height)
l.entries = append(l.entries, &layoutEntry{widget: spacer})
return spacer
}
// AddSpacerDynamic adds a spacer which has dynamic width and height. The width
// and height are computed based off of the position/alignment type of the layout
// and the dimensions/positions of the layout entries.
func (l *Layout) AddSpacerDynamic() *SpacerDynamic {
spacer := createSpacerDynamic()
l.entries = append(l.entries, &layoutEntry{widget: spacer})
return spacer
}
// AddSprite given a path and palette, adds a Sprite as a layout entry
func (l *Layout) AddSprite(imagePath, palettePath string) (*Sprite, error) {
sprite, err := createSprite(imagePath, palettePath, l.assetManager)
if err != nil {
return nil, err
}
l.entries = append(l.entries, &layoutEntry{widget: sprite})
return sprite, nil
}
// AddAnimatedSprite given a path, palette, and direction will add an animated
// sprite as a layout entry
Enhanced escape menu with options - d2gui bug remaining (#459) * First improvements Signed-off-by: William Claude <w.claude@thebeat.co> * Make the menu more generic Signed-off-by: William Claude <w.claude@thebeat.co> * Handle mouse events Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug statement Signed-off-by: William Claude <w.claude@thebeat.co> * Handle left clicks better Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Handle titles in screens Signed-off-by: William Claude <w.claude@thebeat.co> * Improve the menu using layouts Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for onOff labels Signed-off-by: William Claude <w.claude@thebeat.co> * Mutualise title creation Signed-off-by: William Claude <w.claude@thebeat.co> * Add gutter and mutualise things Signed-off-by: William Claude <w.claude@thebeat.co> * Improve menu, mutualise a lot of things and support animated sprites Signed-off-by: William Claude <w.claude@thebeat.co> * Use a cfg struct instead of independent handlers Signed-off-by: William Claude <w.claude@thebeat.co> * Fix hardcoded value Signed-off-by: William Claude <w.claude@thebeat.co> * Clean things a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused property Signed-off-by: William Claude <w.claude@thebeat.co> * First support for hoverable elements Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for label selection feedback Signed-off-by: William Claude <w.claude@thebeat.co> * Add support options Signed-off-by: William Claude <w.claude@thebeat.co> * Update print statement Signed-off-by: William Claude <w.claude@thebeat.co> * Update rendering and clean code Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug things Signed-off-by: William Claude <w.claude@thebeat.co> * Handle hovering Signed-off-by: William Claude <w.claude@thebeat.co> * Support enter key for labels Signed-off-by: William Claude <w.claude@thebeat.co> * Attach methods to layout Signed-off-by: William Claude <w.claude@thebeat.co> * Move things under EscapeMenu Signed-off-by: William Claude <w.claude@thebeat.co> * Some renaming Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Set hovered element ID when using the mouse Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Delete unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Wire save & exit with a nasty hack Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Remove dead code Signed-off-by: William Claude <w.claude@thebeat.co> * Reorder the code a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Rename hoverableElement into actionableElement Signed-off-by: William Claude <w.claude@thebeat.co> * Prevent regenerating the label if the text didn't change Signed-off-by: William Claude <w.claude@thebeat.co>
2020-06-25 16:27:16 -04:00
func (l *Layout) AddAnimatedSprite(imagePath, palettePath string, direction AnimationDirection) (*AnimatedSprite, error) {
sprite, err := createAnimatedSprite(imagePath, palettePath, direction, l.assetManager)
Enhanced escape menu with options - d2gui bug remaining (#459) * First improvements Signed-off-by: William Claude <w.claude@thebeat.co> * Make the menu more generic Signed-off-by: William Claude <w.claude@thebeat.co> * Handle mouse events Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug statement Signed-off-by: William Claude <w.claude@thebeat.co> * Handle left clicks better Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Handle titles in screens Signed-off-by: William Claude <w.claude@thebeat.co> * Improve the menu using layouts Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for onOff labels Signed-off-by: William Claude <w.claude@thebeat.co> * Mutualise title creation Signed-off-by: William Claude <w.claude@thebeat.co> * Add gutter and mutualise things Signed-off-by: William Claude <w.claude@thebeat.co> * Improve menu, mutualise a lot of things and support animated sprites Signed-off-by: William Claude <w.claude@thebeat.co> * Use a cfg struct instead of independent handlers Signed-off-by: William Claude <w.claude@thebeat.co> * Fix hardcoded value Signed-off-by: William Claude <w.claude@thebeat.co> * Clean things a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused property Signed-off-by: William Claude <w.claude@thebeat.co> * First support for hoverable elements Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for label selection feedback Signed-off-by: William Claude <w.claude@thebeat.co> * Add support options Signed-off-by: William Claude <w.claude@thebeat.co> * Update print statement Signed-off-by: William Claude <w.claude@thebeat.co> * Update rendering and clean code Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug things Signed-off-by: William Claude <w.claude@thebeat.co> * Handle hovering Signed-off-by: William Claude <w.claude@thebeat.co> * Support enter key for labels Signed-off-by: William Claude <w.claude@thebeat.co> * Attach methods to layout Signed-off-by: William Claude <w.claude@thebeat.co> * Move things under EscapeMenu Signed-off-by: William Claude <w.claude@thebeat.co> * Some renaming Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Set hovered element ID when using the mouse Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Delete unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Wire save & exit with a nasty hack Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Remove dead code Signed-off-by: William Claude <w.claude@thebeat.co> * Reorder the code a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Rename hoverableElement into actionableElement Signed-off-by: William Claude <w.claude@thebeat.co> * Prevent regenerating the label if the text didn't change Signed-off-by: William Claude <w.claude@thebeat.co>
2020-06-25 16:27:16 -04:00
if err != nil {
return nil, err
}
l.entries = append(l.entries, &layoutEntry{widget: sprite})
Enhanced escape menu with options - d2gui bug remaining (#459) * First improvements Signed-off-by: William Claude <w.claude@thebeat.co> * Make the menu more generic Signed-off-by: William Claude <w.claude@thebeat.co> * Handle mouse events Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug statement Signed-off-by: William Claude <w.claude@thebeat.co> * Handle left clicks better Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Handle titles in screens Signed-off-by: William Claude <w.claude@thebeat.co> * Improve the menu using layouts Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for onOff labels Signed-off-by: William Claude <w.claude@thebeat.co> * Mutualise title creation Signed-off-by: William Claude <w.claude@thebeat.co> * Add gutter and mutualise things Signed-off-by: William Claude <w.claude@thebeat.co> * Improve menu, mutualise a lot of things and support animated sprites Signed-off-by: William Claude <w.claude@thebeat.co> * Use a cfg struct instead of independent handlers Signed-off-by: William Claude <w.claude@thebeat.co> * Fix hardcoded value Signed-off-by: William Claude <w.claude@thebeat.co> * Clean things a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused property Signed-off-by: William Claude <w.claude@thebeat.co> * First support for hoverable elements Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for label selection feedback Signed-off-by: William Claude <w.claude@thebeat.co> * Add support options Signed-off-by: William Claude <w.claude@thebeat.co> * Update print statement Signed-off-by: William Claude <w.claude@thebeat.co> * Update rendering and clean code Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug things Signed-off-by: William Claude <w.claude@thebeat.co> * Handle hovering Signed-off-by: William Claude <w.claude@thebeat.co> * Support enter key for labels Signed-off-by: William Claude <w.claude@thebeat.co> * Attach methods to layout Signed-off-by: William Claude <w.claude@thebeat.co> * Move things under EscapeMenu Signed-off-by: William Claude <w.claude@thebeat.co> * Some renaming Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Set hovered element ID when using the mouse Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Delete unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Wire save & exit with a nasty hack Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Remove dead code Signed-off-by: William Claude <w.claude@thebeat.co> * Reorder the code a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Rename hoverableElement into actionableElement Signed-off-by: William Claude <w.claude@thebeat.co> * Prevent regenerating the label if the text didn't change Signed-off-by: William Claude <w.claude@thebeat.co>
2020-06-25 16:27:16 -04:00
return sprite, nil
}
// AddLabel given a string and a FontStyle, adds a text label as a layout entry
func (l *Layout) AddLabel(text string, fontStyle FontStyle) (*Label, error) {
font, err := l.loadFont(fontStyle)
if err != nil {
return nil, err
}
label := createLabel(l.renderer, text, font)
l.entries = append(l.entries, &layoutEntry{widget: label})
return label, nil
}
// AddButton given a string and ButtonStyle, adds a button as a layout entry
func (l *Layout) AddButton(text string, buttonStyle ButtonStyle) (*Button, error) {
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 16:51:30 -04:00
button, err := l.createButton(l.renderer, text, buttonStyle)
if err != nil {
return nil, err
}
l.entries = append(l.entries, &layoutEntry{widget: button})
return button, nil
}
// Clear removes all layout entries
func (l *Layout) Clear() {
l.entries = nil
}
func (l *Layout) render(target d2interface.Surface) error {
2020-06-25 17:28:48 -04:00
l.AdjustEntryPlacement()
for _, entry := range l.entries {
if !entry.widget.isVisible() {
continue
}
if err := l.renderEntry(entry, target); err != nil {
return err
}
if layoutDebug {
if err := l.renderEntryDebug(entry, target); err != nil {
return err
}
}
}
return nil
}
func (l *Layout) advance(elapsed float64) error {
for _, entry := range l.entries {
if err := entry.widget.advance(elapsed); err != nil {
return err
}
}
return nil
}
func (l *Layout) renderEntry(entry *layoutEntry, target d2interface.Surface) error {
target.PushTranslation(entry.x, entry.y)
defer target.Pop()
return entry.widget.render(target)
}
func (l *Layout) renderEntryDebug(entry *layoutEntry, target d2interface.Surface) error {
target.PushTranslation(entry.x, entry.y)
defer target.Pop()
drawColor := rgbaColor(white)
switch entry.widget.(type) {
case *Layout:
drawColor = rgbaColor(magenta)
case *SpacerStatic, *SpacerDynamic:
drawColor = rgbaColor(grey2)
case *Label:
drawColor = rgbaColor(green)
case *Button:
drawColor = rgbaColor(yellow)
}
target.DrawLine(entry.width, 0, drawColor)
target.DrawLine(0, entry.height, drawColor)
target.PushTranslation(entry.width, 0)
target.DrawLine(0, entry.height, drawColor)
target.Pop()
target.PushTranslation(0, entry.height)
target.DrawLine(entry.width, 0, drawColor)
target.Pop()
return nil
}
func (l *Layout) getContentSize() (width, height int) {
for _, entry := range l.entries {
x, y := entry.widget.getPosition()
w, h := entry.widget.getSize()
switch l.positionType {
case PositionTypeVertical:
width = d2math.MaxInt(width, w)
height += h
case PositionTypeHorizontal:
width += w
height = d2math.MaxInt(height, h)
case PositionTypeAbsolute:
width = d2math.MaxInt(width, x+w)
height = d2math.MaxInt(height, y+h)
}
}
return width, height
}
// GetSize returns the layout width and height
func (l *Layout) GetSize() (width, height int) {
return l.getSize()
}
func (l *Layout) getSize() (width, height int) {
width, height = l.getContentSize()
return d2math.MaxInt(width, l.width), d2math.MaxInt(height, l.height)
}
func (l *Layout) onMouseButtonDown(event d2interface.MouseEvent) bool {
for _, entry := range l.entries {
if entry.IsIn(event) {
entry.widget.onMouseButtonDown(event)
entry.mouseDown[event.Button()] = true
}
}
return false
}
func (l *Layout) onMouseButtonUp(event d2interface.MouseEvent) bool {
for _, entry := range l.entries {
if entry.IsIn(event) {
if entry.mouseDown[event.Button()] {
entry.widget.onMouseButtonClick(event)
entry.widget.onMouseButtonUp(event)
}
}
entry.mouseDown[event.Button()] = false
}
return false
}
func (l *Layout) onMouseMove(event d2interface.MouseMoveEvent) bool {
for _, entry := range l.entries {
if entry.IsIn(event) {
entry.widget.onMouseMove(event)
if entry.mouseOver {
entry.widget.onMouseOver(event)
} else {
entry.widget.onMouseEnter(event)
}
entry.mouseOver = true
} else if entry.mouseOver {
entry.widget.onMouseLeave(event)
entry.mouseOver = false
}
}
return false
}
// AdjustEntryPlacement calculates and sets the position for all layout entries.
// This is based on the position/horizontal/vertical alignment type set, as well as the
// expansion types of spacers.
2020-06-25 17:28:48 -04:00
func (l *Layout) AdjustEntryPlacement() {
width, height := l.getSize()
var expanderCount, expanderWidth, expanderHeight int
for _, entry := range l.entries {
if entry.widget.isVisible() && entry.widget.isExpanding() {
expanderCount++
}
}
if expanderCount > 0 {
contentWidth, contentHeight := l.getContentSize()
switch l.positionType {
case PositionTypeVertical:
expanderHeight = (height - contentHeight) / expanderCount
case PositionTypeHorizontal:
expanderWidth = (width - contentWidth) / expanderCount
}
expanderWidth = d2math.MaxInt(0, expanderWidth)
expanderHeight = d2math.MaxInt(0, expanderHeight)
}
var offsetX, offsetY int
for idx := range l.entries {
entry := l.entries[idx]
if !entry.widget.isVisible() {
continue
}
if entry.widget.isExpanding() {
entry.width, entry.height = expanderWidth, expanderHeight
} else {
entry.width, entry.height = entry.widget.getSize()
}
l.handleEntryPosition(offsetX, offsetY, entry)
switch l.positionType {
case PositionTypeVertical:
offsetY += entry.height
case PositionTypeHorizontal:
offsetX += entry.width
}
Enhanced escape menu with options - d2gui bug remaining (#459) * First improvements Signed-off-by: William Claude <w.claude@thebeat.co> * Make the menu more generic Signed-off-by: William Claude <w.claude@thebeat.co> * Handle mouse events Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug statement Signed-off-by: William Claude <w.claude@thebeat.co> * Handle left clicks better Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Handle titles in screens Signed-off-by: William Claude <w.claude@thebeat.co> * Improve the menu using layouts Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for onOff labels Signed-off-by: William Claude <w.claude@thebeat.co> * Mutualise title creation Signed-off-by: William Claude <w.claude@thebeat.co> * Add gutter and mutualise things Signed-off-by: William Claude <w.claude@thebeat.co> * Improve menu, mutualise a lot of things and support animated sprites Signed-off-by: William Claude <w.claude@thebeat.co> * Use a cfg struct instead of independent handlers Signed-off-by: William Claude <w.claude@thebeat.co> * Fix hardcoded value Signed-off-by: William Claude <w.claude@thebeat.co> * Clean things a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused property Signed-off-by: William Claude <w.claude@thebeat.co> * First support for hoverable elements Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for label selection feedback Signed-off-by: William Claude <w.claude@thebeat.co> * Add support options Signed-off-by: William Claude <w.claude@thebeat.co> * Update print statement Signed-off-by: William Claude <w.claude@thebeat.co> * Update rendering and clean code Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug things Signed-off-by: William Claude <w.claude@thebeat.co> * Handle hovering Signed-off-by: William Claude <w.claude@thebeat.co> * Support enter key for labels Signed-off-by: William Claude <w.claude@thebeat.co> * Attach methods to layout Signed-off-by: William Claude <w.claude@thebeat.co> * Move things under EscapeMenu Signed-off-by: William Claude <w.claude@thebeat.co> * Some renaming Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Set hovered element ID when using the mouse Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Delete unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Wire save & exit with a nasty hack Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Remove dead code Signed-off-by: William Claude <w.claude@thebeat.co> * Reorder the code a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Rename hoverableElement into actionableElement Signed-off-by: William Claude <w.claude@thebeat.co> * Prevent regenerating the label if the text didn't change Signed-off-by: William Claude <w.claude@thebeat.co>
2020-06-25 16:27:16 -04:00
sx, sy := l.ScreenPos()
entry.widget.SetScreenPos(entry.x+sx, entry.y+sy)
Enhanced escape menu with options - d2gui bug remaining (#459) * First improvements Signed-off-by: William Claude <w.claude@thebeat.co> * Make the menu more generic Signed-off-by: William Claude <w.claude@thebeat.co> * Handle mouse events Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug statement Signed-off-by: William Claude <w.claude@thebeat.co> * Handle left clicks better Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Handle titles in screens Signed-off-by: William Claude <w.claude@thebeat.co> * Improve the menu using layouts Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for onOff labels Signed-off-by: William Claude <w.claude@thebeat.co> * Mutualise title creation Signed-off-by: William Claude <w.claude@thebeat.co> * Add gutter and mutualise things Signed-off-by: William Claude <w.claude@thebeat.co> * Improve menu, mutualise a lot of things and support animated sprites Signed-off-by: William Claude <w.claude@thebeat.co> * Use a cfg struct instead of independent handlers Signed-off-by: William Claude <w.claude@thebeat.co> * Fix hardcoded value Signed-off-by: William Claude <w.claude@thebeat.co> * Clean things a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused property Signed-off-by: William Claude <w.claude@thebeat.co> * First support for hoverable elements Signed-off-by: William Claude <w.claude@thebeat.co> * Add support for label selection feedback Signed-off-by: William Claude <w.claude@thebeat.co> * Add support options Signed-off-by: William Claude <w.claude@thebeat.co> * Update print statement Signed-off-by: William Claude <w.claude@thebeat.co> * Update rendering and clean code Signed-off-by: William Claude <w.claude@thebeat.co> * Remove debug things Signed-off-by: William Claude <w.claude@thebeat.co> * Handle hovering Signed-off-by: William Claude <w.claude@thebeat.co> * Support enter key for labels Signed-off-by: William Claude <w.claude@thebeat.co> * Attach methods to layout Signed-off-by: William Claude <w.claude@thebeat.co> * Move things under EscapeMenu Signed-off-by: William Claude <w.claude@thebeat.co> * Some renaming Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Set hovered element ID when using the mouse Signed-off-by: William Claude <w.claude@thebeat.co> * Clean Signed-off-by: William Claude <w.claude@thebeat.co> * Delete unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Wire save & exit with a nasty hack Signed-off-by: William Claude <w.claude@thebeat.co> * Remove unused file Signed-off-by: William Claude <w.claude@thebeat.co> * Remove dead code Signed-off-by: William Claude <w.claude@thebeat.co> * Reorder the code a bit Signed-off-by: William Claude <w.claude@thebeat.co> * Rename hoverableElement into actionableElement Signed-off-by: William Claude <w.claude@thebeat.co> * Prevent regenerating the label if the text didn't change Signed-off-by: William Claude <w.claude@thebeat.co>
2020-06-25 16:27:16 -04:00
entry.widget.setOffset(offsetX, offsetY)
}
}
func (l *Layout) handleEntryPosition(offsetX, offsetY int, entry *layoutEntry) {
width, height := l.getSize()
switch l.positionType {
case PositionTypeVertical:
entry.y = offsetY
l.handleEntryVerticalAlign(width, entry)
case PositionTypeHorizontal:
entry.x = offsetX
l.handleEntryHorizontalAlign(height, entry)
case PositionTypeAbsolute:
entry.x, entry.y = entry.widget.getPosition()
}
}
func (l *Layout) handleEntryHorizontalAlign(height int, entry *layoutEntry) {
switch l.verticalAlign {
case VerticalAlignTop:
entry.y = 0
case VerticalAlignMiddle:
entry.y = half(height) - half(entry.height)
case VerticalAlignBottom:
entry.y = height - entry.height
}
}
func (l *Layout) handleEntryVerticalAlign(width int, entry *layoutEntry) {
switch l.horizontalAlign {
case HorizontalAlignLeft:
entry.x = 0
case HorizontalAlignCenter:
entry.x = half(width) - half(entry.width)
case HorizontalAlignRight:
entry.x = width - entry.width
}
}
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 16:51:30 -04:00
func (l *Layout) createButton(renderer d2interface.Renderer, text string,
buttonStyle ButtonStyle) (*Button,
error) {
config := getButtonStyleConfig(buttonStyle)
if config == nil {
return nil, errors.New("invalid button style")
}
animation, loadErr := l.assetManager.LoadAnimation(config.animationPath, config.palettePath)
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 16:51:30 -04:00
if loadErr != nil {
return nil, loadErr
}
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 16:51:30 -04:00
var buttonWidth int
for i := 0; i < config.segmentsX; i++ {
w, _, err := animation.GetFrameSize(i)
if err != nil {
return nil, err
}
buttonWidth += w
}
var buttonHeight int
for i := 0; i < config.segmentsY; i++ {
_, h, err := animation.GetFrameSize(i * config.segmentsY)
if err != nil {
return nil, err
}
buttonHeight += h
}
font, loadErr := l.loadFont(config.fontStyle)
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 16:51:30 -04:00
if loadErr != nil {
return nil, loadErr
}
textColor := rgbaColor(grey)
textWidth, textHeight := font.GetTextMetrics(text)
textX := half(buttonWidth) - half(textWidth)
textY := half(buttonHeight) - half(textHeight) + config.textOffset
surfaceCount := animation.GetFrameCount() / (config.segmentsX * config.segmentsY)
surfaces := make([]d2interface.Surface, surfaceCount)
for i := 0; i < surfaceCount; i++ {
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
if surfaceErr != nil {
return nil, surfaceErr
}
segX, segY, frame := config.segmentsX, config.segmentsY, i
if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil {
return nil, segErr
}
font.SetColor(textColor)
var textOffsetX, textOffsetY int
switch buttonState(i) {
case buttonStatePressed, buttonStatePressedToggled:
textOffsetX = -2
textOffsetY = 2
}
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
surfaceErr = font.RenderText(text, surface)
surface.Pop()
if surfaceErr != nil {
return nil, surfaceErr
}
surfaces[i] = surface
}
button := &Button{width: buttonWidth, height: buttonHeight, surfaces: surfaces}
button.SetVisible(true)
return button, nil
}
func (l *Layout) loadFont(fontStyle FontStyle) (*d2asset.Font, error) {
config := getFontStyleConfig(fontStyle)
if config == nil {
return nil, errors.New("invalid font style")
}
return l.assetManager.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
}