mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-06-12 18:50:42 +00:00
first pass at resolving linting issues in d2asset (#518)
This commit is contained in:
parent
973e969002
commit
c8ec4c018e
|
@ -26,6 +26,8 @@ const (
|
||||||
playModeBackward
|
playModeBackward
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultPlayLength = 1.0
|
||||||
|
|
||||||
type animationFrame struct {
|
type animationFrame struct {
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
|
@ -59,9 +61,10 @@ type Animation struct {
|
||||||
subEndingFrame int
|
subEndingFrame int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateAnimationFromDCC creates an animation from d2dcc.DCC and d2dat.DATPalette
|
||||||
func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transparency int) (*Animation, error) {
|
func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transparency int) (*Animation, error) {
|
||||||
animation := &Animation{
|
animation := &Animation{
|
||||||
playLength: 1.0,
|
playLength: defaultPlayLength,
|
||||||
playLoop: true,
|
playLoop: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,14 +83,14 @@ func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transpare
|
||||||
frameWidth := maxX - minX
|
frameWidth := maxX - minX
|
||||||
frameHeight := maxY - minY
|
frameHeight := maxY - minY
|
||||||
|
|
||||||
pixels := make([]byte, frameWidth*frameHeight*4)
|
const bytesPerPixel = 4
|
||||||
|
pixels := make([]byte, frameWidth*frameHeight*bytesPerPixel)
|
||||||
|
|
||||||
for y := 0; y < frameHeight; y++ {
|
for y := 0; y < frameHeight; y++ {
|
||||||
for x := 0; x < frameWidth; x++ {
|
for x := 0; x < frameWidth; x++ {
|
||||||
|
|
||||||
if paletteIndex := dccFrame.PixelData[y*frameWidth+x]; paletteIndex != 0 {
|
if paletteIndex := dccFrame.PixelData[y*frameWidth+x]; paletteIndex != 0 {
|
||||||
palColor := palette.Colors[paletteIndex]
|
palColor := palette.Colors[paletteIndex]
|
||||||
offset := (x + y*frameWidth) * 4
|
offset := (x + y*frameWidth) * bytesPerPixel
|
||||||
pixels[offset] = palColor.R
|
pixels[offset] = palColor.R
|
||||||
pixels[offset+1] = palColor.G
|
pixels[offset+1] = palColor.G
|
||||||
pixels[offset+2] = palColor.B
|
pixels[offset+2] = palColor.B
|
||||||
|
@ -123,9 +126,10 @@ func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transpare
|
||||||
return animation, nil
|
return animation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateAnimationFromDC6 creates an Animation from d2dc6.DC6 and d2dat.DATPalette
|
||||||
func CreateAnimationFromDC6(dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animation, error) {
|
func CreateAnimationFromDC6(dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animation, error) {
|
||||||
animation := &Animation{
|
animation := &Animation{
|
||||||
playLength: 1.0,
|
playLength: defaultPlayLength,
|
||||||
playLoop: true,
|
playLoop: true,
|
||||||
originAtBottom: true,
|
originAtBottom: true,
|
||||||
}
|
}
|
||||||
|
@ -170,17 +174,18 @@ func CreateAnimationFromDC6(dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animati
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
colorData := make([]byte, dc6Frame.Width*dc6Frame.Height*4)
|
bytesPerPixel := 4
|
||||||
|
colorData := make([]byte, int(dc6Frame.Width)*int(dc6Frame.Height)*bytesPerPixel)
|
||||||
|
|
||||||
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
|
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
|
||||||
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
|
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
colorData[i*4] = palette.Colors[indexData[i]].R
|
colorData[i*bytesPerPixel] = palette.Colors[indexData[i]].R
|
||||||
colorData[i*4+1] = palette.Colors[indexData[i]].G
|
colorData[i*bytesPerPixel+1] = palette.Colors[indexData[i]].G
|
||||||
colorData[i*4+2] = palette.Colors[indexData[i]].B
|
colorData[i*bytesPerPixel+2] = palette.Colors[indexData[i]].B
|
||||||
colorData[i*4+3] = 0xff
|
colorData[i*bytesPerPixel+3] = 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sfc.ReplacePixels(colorData); err != nil {
|
if err := sfc.ReplacePixels(colorData); err != nil {
|
||||||
|
@ -269,9 +274,14 @@ func (a *Animation) Render(target d2interface.Surface) error {
|
||||||
frame := direction.frames[a.frameIndex]
|
frame := direction.frames[a.frameIndex]
|
||||||
|
|
||||||
target.PushTranslation(frame.offsetX, frame.offsetY)
|
target.PushTranslation(frame.offsetX, frame.offsetY)
|
||||||
|
defer target.Pop()
|
||||||
|
|
||||||
target.PushCompositeMode(a.compositeMode)
|
target.PushCompositeMode(a.compositeMode)
|
||||||
|
defer target.Pop()
|
||||||
|
|
||||||
target.PushColor(a.colorMod)
|
target.PushColor(a.colorMod)
|
||||||
defer target.PopN(3)
|
defer target.Pop()
|
||||||
|
|
||||||
return target.Render(frame.image)
|
return target.Render(frame.image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,9 +366,11 @@ func (a *Animation) GetDirectionCount() int {
|
||||||
|
|
||||||
// SetDirection places the animation in the direction of an animation
|
// SetDirection places the animation in the direction of an animation
|
||||||
func (a *Animation) SetDirection(directionIndex int) error {
|
func (a *Animation) SetDirection(directionIndex int) error {
|
||||||
if directionIndex >= 64 {
|
const smallestInvalidDirectionIndex = 64
|
||||||
|
if directionIndex >= smallestInvalidDirectionIndex {
|
||||||
return errors.New("invalid direction index")
|
return errors.New("invalid direction index")
|
||||||
}
|
}
|
||||||
|
|
||||||
a.directionIndex = d2dcc.Dir64ToDcc(directionIndex, len(a.directions))
|
a.directionIndex = d2dcc.Dir64ToDcc(directionIndex, len(a.directions))
|
||||||
a.frameIndex = 0
|
a.frameIndex = 0
|
||||||
|
|
||||||
|
@ -378,6 +390,7 @@ func (a *Animation) SetCurrentFrame(frameIndex int) error {
|
||||||
|
|
||||||
a.frameIndex = frameIndex
|
a.frameIndex = frameIndex
|
||||||
a.lastFrameTime = 0
|
a.lastFrameTime = 0
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,17 +427,21 @@ func (a *Animation) SetPlaySpeed(playSpeed float64) {
|
||||||
a.SetPlayLength(playSpeed * float64(a.GetFrameCount()))
|
a.SetPlayLength(playSpeed * float64(a.GetFrameCount()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Animation) SetPlayLength(playLength float64) {
|
// SetPlayLength sets the Animation's play length in seconds
|
||||||
|
func (a *Animation) SetPlayLength(playLength float64) { // TODO refactor to use time.Duration instead of float64
|
||||||
a.playLength = playLength
|
a.playLength = playLength
|
||||||
a.lastFrameTime = 0
|
a.lastFrameTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Animation) SetPlayLengthMs(playLengthMs int) {
|
// SetPlayLengthMs sets the Animation's play length in milliseconds
|
||||||
a.SetPlayLength(float64(playLengthMs) / 1000.0)
|
func (a *Animation) SetPlayLengthMs(playLengthMs int) { // TODO remove this method
|
||||||
|
const millisecondsPerSecond = 1000.0
|
||||||
|
a.SetPlayLength(float64(playLengthMs) / millisecondsPerSecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Animation) SetColorMod(color color.Color) {
|
// SetColorMod sets the Animation's color mod
|
||||||
a.colorMod = color
|
func (a *Animation) SetColorMod(colorMod color.Color) {
|
||||||
|
a.colorMod = colorMod
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPlayedCount gets the number of times the application played
|
// GetPlayedCount gets the number of times the application played
|
||||||
|
@ -437,7 +454,7 @@ func (a *Animation) ResetPlayedCount() {
|
||||||
a.playedCount = 0
|
a.playedCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetBlend sets the animation alpha blending status
|
// SetBlend sets the Animation alpha blending status
|
||||||
func (a *Animation) SetBlend(blend bool) {
|
func (a *Animation) SetBlend(blend bool) {
|
||||||
if blend {
|
if blend {
|
||||||
a.compositeMode = d2enum.CompositeModeLighter
|
a.compositeMode = d2enum.CompositeModeLighter
|
||||||
|
|
|
@ -27,6 +27,7 @@ func (am *animationManager) loadAnimation(animationPath, palettePath string, tra
|
||||||
}
|
}
|
||||||
|
|
||||||
var animation *Animation
|
var animation *Animation
|
||||||
|
|
||||||
ext := strings.ToLower(filepath.Ext(animationPath))
|
ext := strings.ToLower(filepath.Ext(animationPath))
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".dc6":
|
case ".dc6":
|
||||||
|
|
|
@ -17,7 +17,7 @@ type archiveEntry struct {
|
||||||
|
|
||||||
type archiveManager struct {
|
type archiveManager struct {
|
||||||
cache *d2common.Cache
|
cache *d2common.Cache
|
||||||
config d2config.Configuration
|
config *d2config.Configuration
|
||||||
entries []archiveEntry
|
entries []archiveEntry
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ const (
|
||||||
archiveBudget = 1024 * 1024 * 512
|
archiveBudget = 1024 * 1024 * 512
|
||||||
)
|
)
|
||||||
|
|
||||||
func createArchiveManager(config d2config.Configuration) *archiveManager {
|
func createArchiveManager(config *d2config.Configuration) *archiveManager {
|
||||||
return &archiveManager{cache: d2common.CreateCache(archiveBudget), config: config}
|
return &archiveManager{cache: d2common.CreateCache(archiveBudget), config: config}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ func (am *archiveManager) cacheArchiveEntries() error {
|
||||||
|
|
||||||
for _, archiveName := range am.config.MpqLoadOrder {
|
for _, archiveName := range am.config.MpqLoadOrder {
|
||||||
archivePath := path.Join(am.config.MpqPath, archiveName)
|
archivePath := path.Join(am.config.MpqPath, archiveName)
|
||||||
|
|
||||||
archive, err := am.loadArchive(archivePath)
|
archive, err := am.loadArchive(archivePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrWasInit = errors.New("asset system is already initialized")
|
|
||||||
ErrNotInit = errors.New("asset system is not initialized")
|
|
||||||
)
|
|
||||||
|
|
||||||
type assetManager struct {
|
type assetManager struct {
|
||||||
archiveManager *archiveManager
|
archiveManager *archiveManager
|
||||||
fileManager *fileManager
|
fileManager *fileManager
|
||||||
|
|
|
@ -5,24 +5,26 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
|
||||||
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Composite is a composite entity animation
|
||||||
type Composite struct {
|
type Composite struct {
|
||||||
object *d2datadict.ObjectLookupRecord
|
object *d2datadict.ObjectLookupRecord
|
||||||
palettePath string
|
palettePath string
|
||||||
mode *compositeMode
|
mode *compositeMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateComposite creates a Composite from a given ObjectLookupRecord and palettePath.
|
||||||
func CreateComposite(object *d2datadict.ObjectLookupRecord, palettePath string) *Composite {
|
func CreateComposite(object *d2datadict.ObjectLookupRecord, palettePath string) *Composite {
|
||||||
return &Composite{object: object, palettePath: palettePath}
|
return &Composite{object: object, palettePath: palettePath}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Advance moves the composite animation forward for a given elapsed time in nanoseconds.
|
||||||
func (c *Composite) Advance(elapsed float64) error {
|
func (c *Composite) Advance(elapsed float64) error {
|
||||||
if c.mode == nil {
|
if c.mode == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -46,6 +48,7 @@ func (c *Composite) Advance(elapsed float64) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render performs drawing of the Composite on the rendered d2interface.Surface.
|
||||||
func (c *Composite) Render(target d2interface.Surface) error {
|
func (c *Composite) Render(target d2interface.Surface) error {
|
||||||
if c.mode == nil {
|
if c.mode == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -63,10 +66,12 @@ func (c *Composite) Render(target d2interface.Surface) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAnimationMode returns the animation mode the Composite should render with.
|
||||||
func (c Composite) GetAnimationMode() string {
|
func (c Composite) GetAnimationMode() string {
|
||||||
return c.mode.animationMode
|
return c.mode.animationMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetMode sets the Composite's animation mode weapon class and direction
|
||||||
func (c *Composite) SetMode(animationMode, weaponClass string, direction int) error {
|
func (c *Composite) SetMode(animationMode, weaponClass string, direction int) error {
|
||||||
if c.mode != nil && c.mode.animationMode == animationMode && c.mode.weaponClass == weaponClass && c.mode.cofDirection == direction {
|
if c.mode != nil && c.mode.animationMode == animationMode && c.mode.weaponClass == weaponClass && c.mode.cofDirection == direction {
|
||||||
return nil
|
return nil
|
||||||
|
@ -77,11 +82,13 @@ func (c *Composite) SetMode(animationMode, weaponClass string, direction int) er
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ResetPlayedCount()
|
c.resetPlayedCount()
|
||||||
c.mode = mode
|
c.mode = mode
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetSpeed sets the speed at which the Composite's animation should advance through its frames
|
||||||
func (c *Composite) SetSpeed(speed int) {
|
func (c *Composite) SetSpeed(speed int) {
|
||||||
c.mode.animationSpeed = 1.0 / ((float64(speed) * 25.0) / 256.0)
|
c.mode.animationSpeed = 1.0 / ((float64(speed) * 25.0) / 256.0)
|
||||||
for layerIdx := range c.mode.layers {
|
for layerIdx := range c.mode.layers {
|
||||||
|
@ -92,6 +99,7 @@ func (c *Composite) SetSpeed(speed int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDirectionCount returns the Composites number of available animated directions
|
||||||
func (c *Composite) GetDirectionCount() int {
|
func (c *Composite) GetDirectionCount() int {
|
||||||
if c.mode == nil {
|
if c.mode == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -100,6 +108,7 @@ func (c *Composite) GetDirectionCount() int {
|
||||||
return c.mode.directionCount
|
return c.mode.directionCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPlayedCount returns the number of times the current animation mode has completed all its distinct frames
|
||||||
func (c *Composite) GetPlayedCount() int {
|
func (c *Composite) GetPlayedCount() int {
|
||||||
if c.mode == nil {
|
if c.mode == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -108,7 +117,7 @@ func (c *Composite) GetPlayedCount() int {
|
||||||
return c.mode.playedCount
|
return c.mode.playedCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Composite) ResetPlayedCount() {
|
func (c *Composite) resetPlayedCount() {
|
||||||
if c.mode != nil {
|
if c.mode != nil {
|
||||||
c.mode.playedCount = 0
|
c.mode.playedCount = 0
|
||||||
}
|
}
|
||||||
|
@ -117,7 +126,7 @@ func (c *Composite) ResetPlayedCount() {
|
||||||
type compositeMode struct {
|
type compositeMode struct {
|
||||||
animationMode string
|
animationMode string
|
||||||
weaponClass string
|
weaponClass string
|
||||||
cofDirection int
|
cofDirection int
|
||||||
directionCount int
|
directionCount int
|
||||||
playedCount int
|
playedCount int
|
||||||
|
|
||||||
|
@ -142,6 +151,7 @@ func (c *Composite) createMode(animationMode, weaponClass string, direction int)
|
||||||
}
|
}
|
||||||
|
|
||||||
animationKey := strings.ToLower(c.object.Token + animationMode + weaponClass)
|
animationKey := strings.ToLower(c.object.Token + animationMode + weaponClass)
|
||||||
|
|
||||||
animationData := d2data.AnimationData[animationKey]
|
animationData := d2data.AnimationData[animationKey]
|
||||||
if len(animationData) == 0 {
|
if len(animationData) == 0 {
|
||||||
return nil, errors.New("could not find animation data")
|
return nil, errors.New("could not find animation data")
|
||||||
|
@ -222,7 +232,9 @@ func (c *Composite) createMode(animationMode, weaponClass string, direction int)
|
||||||
layer.SetPlaySpeed(mode.animationSpeed)
|
layer.SetPlaySpeed(mode.animationSpeed)
|
||||||
layer.PlayForward()
|
layer.PlayForward()
|
||||||
layer.SetBlend(blend)
|
layer.SetBlend(blend)
|
||||||
layer.SetDirection(direction)
|
if err := layer.SetDirection(direction); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
mode.layers[cofLayer.Type] = layer
|
mode.layers[cofLayer.Type] = layer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
/*
|
||||||
|
Package d2asset has behaviors to load and save assets from disk.
|
||||||
|
*/
|
||||||
package d2asset
|
package d2asset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -8,19 +11,17 @@ import (
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
|
||||||
)
|
)
|
||||||
|
|
||||||
var singleton *assetManager
|
var singleton *assetManager
|
||||||
|
|
||||||
|
// Initialize creates and assigns all necessary dependencies for the assetManager top-level functions to work correctly
|
||||||
func Initialize(term d2interface.Terminal) error {
|
func Initialize(term d2interface.Terminal) error {
|
||||||
verifyNotInit()
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
config = d2config.Get()
|
config = d2config.Get()
|
||||||
archiveManager = createArchiveManager(config)
|
archiveManager = createArchiveManager(&config)
|
||||||
fileManager = createFileManager(config, archiveManager)
|
fileManager = createFileManager(&config, archiveManager)
|
||||||
paletteManager = createPaletteManager()
|
paletteManager = createPaletteManager()
|
||||||
paletteTransformManager = createPaletteTransformManager()
|
paletteTransformManager = createPaletteTransformManager()
|
||||||
animationManager = createAnimationManager()
|
animationManager = createAnimationManager()
|
||||||
|
@ -36,7 +37,7 @@ func Initialize(term d2interface.Terminal) error {
|
||||||
fontManager,
|
fontManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
if err := term.BindAction("assetspam", "display verbose asset manager logs", func(verbose bool) {
|
||||||
if verbose {
|
if verbose {
|
||||||
term.OutputInfof("asset manager verbose logging enabled")
|
term.OutputInfof("asset manager verbose logging enabled")
|
||||||
} else {
|
} else {
|
||||||
|
@ -48,41 +49,47 @@ func Initialize(term d2interface.Terminal) error {
|
||||||
paletteManager.cache.SetVerbose(verbose)
|
paletteManager.cache.SetVerbose(verbose)
|
||||||
paletteTransformManager.cache.SetVerbose(verbose)
|
paletteTransformManager.cache.SetVerbose(verbose)
|
||||||
animationManager.cache.SetVerbose(verbose)
|
animationManager.cache.SetVerbose(verbose)
|
||||||
})
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
term.BindAction("assetstat", "display asset manager cache statistics", func() {
|
if err := term.BindAction("assetstat", "display asset manager cache statistics", func() {
|
||||||
term.OutputInfof("archive cache: %f", float64(archiveManager.cache.GetWeight())/float64(archiveManager.cache.GetBudget())*100.0)
|
type cache interface {
|
||||||
term.OutputInfof("file cache: %f", float64(fileManager.cache.GetWeight())/float64(fileManager.cache.GetBudget())*100.0)
|
GetWeight() int
|
||||||
term.OutputInfof("palette cache: %f", float64(paletteManager.cache.GetWeight())/float64(paletteManager.cache.GetBudget())*100.0)
|
GetBudget() int
|
||||||
term.OutputInfof("palette transform cache: %f", float64(paletteTransformManager.cache.GetWeight())/float64(paletteTransformManager.cache.GetBudget())*100.0)
|
}
|
||||||
term.OutputInfof("animation cache: %f", float64(animationManager.cache.GetWeight())/float64(animationManager.cache.GetBudget())*100.0)
|
|
||||||
term.OutputInfof("font cache: %f", float64(fontManager.cache.GetWeight())/float64(fontManager.cache.GetBudget())*100.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
term.BindAction("assetclear", "clear asset manager cache", func() {
|
var cacheStatistics = func(c cache) float64 {
|
||||||
|
const percent = 100.0
|
||||||
|
return float64(c.GetWeight()) / float64(c.GetBudget()) * percent
|
||||||
|
}
|
||||||
|
|
||||||
|
term.OutputInfof("archive cache: %f", cacheStatistics(archiveManager.cache))
|
||||||
|
term.OutputInfof("file cache: %f", cacheStatistics(fileManager.cache))
|
||||||
|
term.OutputInfof("palette cache: %f", cacheStatistics(paletteManager.cache))
|
||||||
|
term.OutputInfof("palette transform cache: %f", cacheStatistics(paletteTransformManager.cache))
|
||||||
|
term.OutputInfof("animation cache: %f", cacheStatistics(animationManager.cache))
|
||||||
|
term.OutputInfof("font cache: %f", cacheStatistics(fontManager.cache))
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := term.BindAction("assetclear", "clear asset manager cache", func() {
|
||||||
archiveManager.cache.Clear()
|
archiveManager.cache.Clear()
|
||||||
fileManager.cache.Clear()
|
fileManager.cache.Clear()
|
||||||
paletteManager.cache.Clear()
|
paletteManager.cache.Clear()
|
||||||
paletteTransformManager.cache.Clear()
|
paletteTransformManager.cache.Clear()
|
||||||
animationManager.cache.Clear()
|
animationManager.cache.Clear()
|
||||||
fontManager.cache.Clear()
|
fontManager.cache.Clear()
|
||||||
})
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Shutdown() {
|
// LoadFileStream streams an MPQ file from a source file path
|
||||||
singleton = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadArchive(archivePath string) (*d2mpq.MPQ, error) {
|
|
||||||
verifyWasInit()
|
|
||||||
return singleton.archiveManager.loadArchive(archivePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
|
func LoadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
|
||||||
verifyWasInit()
|
|
||||||
|
|
||||||
data, err := singleton.fileManager.loadFileStream(filePath)
|
data, err := singleton.fileManager.loadFileStream(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
|
log.Printf("error loading file stream %s (%v)", filePath, err.Error())
|
||||||
|
@ -91,9 +98,8 @@ func LoadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadFile loads an entire file from a source file path as a []byte
|
||||||
func LoadFile(filePath string) ([]byte, error) {
|
func LoadFile(filePath string) ([]byte, error) {
|
||||||
verifyWasInit()
|
|
||||||
|
|
||||||
data, err := singleton.fileManager.loadFile(filePath)
|
data, err := singleton.fileManager.loadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error loading file %s (%v)", filePath, err.Error())
|
log.Printf("error loading file %s (%v)", filePath, err.Error())
|
||||||
|
@ -102,49 +108,32 @@ func LoadFile(filePath string) ([]byte, error) {
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FileExists checks if a file exists on the underlying file system at the given file path.
|
||||||
func FileExists(filePath string) (bool, error) {
|
func FileExists(filePath string) (bool, error) {
|
||||||
verifyWasInit()
|
|
||||||
return singleton.fileManager.fileExists(filePath)
|
return singleton.fileManager.fileExists(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadAnimation loads an animation by its resource path and its palette path
|
||||||
func LoadAnimation(animationPath, palettePath string) (*Animation, error) {
|
func LoadAnimation(animationPath, palettePath string) (*Animation, error) {
|
||||||
verifyWasInit()
|
|
||||||
return LoadAnimationWithTransparency(animationPath, palettePath, 255)
|
return LoadAnimationWithTransparency(animationPath, palettePath, 255)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadPaletteTransform(pl2Path string) (*d2pl2.PL2, error) {
|
// LoadAnimationWithTransparency loads an animation by its resource path and its palette path with a given transparency value
|
||||||
verifyWasInit()
|
|
||||||
return singleton.paletteTransformManager.loadPaletteTransform(pl2Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadAnimationWithTransparency(animationPath, palettePath string, transparency int) (*Animation, error) {
|
func LoadAnimationWithTransparency(animationPath, palettePath string, transparency int) (*Animation, error) {
|
||||||
verifyWasInit()
|
|
||||||
return singleton.animationManager.loadAnimation(animationPath, palettePath, transparency)
|
return singleton.animationManager.loadAnimation(animationPath, palettePath, transparency)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||||
func LoadComposite(object *d2datadict.ObjectLookupRecord, palettePath string) (*Composite, error) {
|
func LoadComposite(object *d2datadict.ObjectLookupRecord, palettePath string) (*Composite, error) {
|
||||||
verifyWasInit()
|
|
||||||
return CreateComposite(object, palettePath), nil
|
return CreateComposite(object, palettePath), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadFont loads a font the resource files
|
||||||
func LoadFont(tablePath, spritePath, palettePath string) (*Font, error) {
|
func LoadFont(tablePath, spritePath, palettePath string) (*Font, error) {
|
||||||
verifyWasInit()
|
|
||||||
return singleton.fontManager.loadFont(tablePath, spritePath, palettePath)
|
return singleton.fontManager.loadFont(tablePath, spritePath, palettePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadPalette loads a palette from a given palette path
|
||||||
func LoadPalette(palettePath string) (*d2dat.DATPalette, error) {
|
func LoadPalette(palettePath string) (*d2dat.DATPalette, error) {
|
||||||
verifyWasInit()
|
|
||||||
return singleton.paletteManager.loadPalette(palettePath)
|
return singleton.paletteManager.loadPalette(palettePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyWasInit() {
|
|
||||||
if singleton == nil {
|
|
||||||
panic(ErrNotInit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func verifyNotInit() {
|
|
||||||
if singleton != nil {
|
|
||||||
panic(ErrWasInit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,14 +16,13 @@ const (
|
||||||
type fileManager struct {
|
type fileManager struct {
|
||||||
cache *d2common.Cache
|
cache *d2common.Cache
|
||||||
archiveManager *archiveManager
|
archiveManager *archiveManager
|
||||||
config d2config.Configuration
|
config *d2config.Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFileManager(config d2config.Configuration, archiveManager *archiveManager) *fileManager {
|
func createFileManager(config *d2config.Configuration, archiveManager *archiveManager) *fileManager {
|
||||||
return &fileManager{d2common.CreateCache(fileBudget), archiveManager, config}
|
return &fileManager{d2common.CreateCache(fileBudget), archiveManager, config}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (fm *fileManager) loadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
|
func (fm *fileManager) loadFileStream(filePath string) (*d2mpq.MpqDataStream, error) {
|
||||||
filePath = fm.fixupFilePath(filePath)
|
filePath = fm.fixupFilePath(filePath)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ type fontGlyph struct {
|
||||||
height int
|
height int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Font represents a displayable font
|
||||||
type Font struct {
|
type Font struct {
|
||||||
sheet *Animation
|
sheet *Animation
|
||||||
glyphs map[rune]fontGlyph
|
glyphs map[rune]fontGlyph
|
||||||
|
@ -47,7 +48,7 @@ func loadFont(tablePath, spritePath, palettePath string) (*Font, error) {
|
||||||
var glyph fontGlyph
|
var glyph fontGlyph
|
||||||
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
|
glyph.frame = int(binary.LittleEndian.Uint16(data[i+8 : i+10]))
|
||||||
glyph.width = int(data[i+3])
|
glyph.width = int(data[i+3])
|
||||||
glyph.height = maxCharHeight // int(data[i+4])
|
glyph.height = maxCharHeight
|
||||||
|
|
||||||
glyphs[code] = glyph
|
glyphs[code] = glyph
|
||||||
}
|
}
|
||||||
|
@ -61,11 +62,12 @@ func loadFont(tablePath, spritePath, palettePath string) (*Font, error) {
|
||||||
return font, nil
|
return font, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Font) SetColor(color color.Color) {
|
func (f *Font) SetColor(c color.Color) {
|
||||||
f.color = color
|
f.color = c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Font) GetTextMetrics(text string) (int, int) {
|
// GetTextMetrics returns the dimensions of the Font element in pixels
|
||||||
|
func (f *Font) GetTextMetrics(text string) (width, height int) {
|
||||||
var (
|
var (
|
||||||
lineWidth int
|
lineWidth int
|
||||||
lineHeight int
|
lineHeight int
|
||||||
|
@ -91,6 +93,7 @@ func (f *Font) GetTextMetrics(text string) (int, int) {
|
||||||
return totalWidth, totalHeight
|
return totalWidth, totalHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clone creates a shallow copy of the Font
|
||||||
func (f *Font) Clone() *Font {
|
func (f *Font) Clone() *Font {
|
||||||
return &Font{
|
return &Font{
|
||||||
sheet: f.sheet,
|
sheet: f.sheet,
|
||||||
|
@ -99,6 +102,7 @@ func (f *Font) Clone() *Font {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderText draws a string of text in a style described by Font onto the d2interface.Surface
|
||||||
func (f *Font) RenderText(text string, target d2interface.Surface) error {
|
func (f *Font) RenderText(text string, target d2interface.Surface) error {
|
||||||
f.sheet.SetColorMod(f.color)
|
f.sheet.SetColorMod(f.color)
|
||||||
f.sheet.SetBlend(false)
|
f.sheet.SetBlend(false)
|
||||||
|
@ -112,13 +116,23 @@ func (f *Font) RenderText(text string, target d2interface.Surface) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, c := range line {
|
for _, c := range line {
|
||||||
if glyph, ok := f.glyphs[c]; ok {
|
glyph, ok := f.glyphs[c]
|
||||||
f.sheet.SetCurrentFrame(glyph.frame)
|
if !ok {
|
||||||
f.sheet.Render(target)
|
continue
|
||||||
lineHeight = d2common.MaxInt(lineHeight, glyph.height)
|
|
||||||
target.PushTranslation(glyph.width, 0)
|
|
||||||
lineLength++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := f.sheet.SetCurrentFrame(glyph.frame); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := f.sheet.Render(target); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lineHeight = d2common.MaxInt(lineHeight, glyph.height)
|
||||||
|
lineLength++
|
||||||
|
|
||||||
|
target.PushTranslation(glyph.width, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
target.PopN(lineLength)
|
target.PopN(lineLength)
|
||||||
|
|
|
@ -32,6 +32,9 @@ func (pm *paletteManager) loadPalette(palettePath string) (*d2dat.DATPalette, er
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pm.cache.Insert(palettePath, palette, 1)
|
if err := pm.cache.Insert(palettePath, palette, 1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return palette, nil
|
return palette, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,9 @@ func (pm *paletteTransformManager) loadPaletteTransform(path string) (*d2pl2.PL2
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pm.cache.Insert(path, pl2, 1)
|
if err := pm.cache.Insert(path, pl2, 1); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return pl2, nil
|
return pl2, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user