mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 15:46:51 -05:00
Animation manager abstraction (#544)
* abstracted palettes, colors, and palette manager * make asset manager use the palette manager interface * added BGRA setter/getter, fixed lint errors * abstraction for animation and animation manager
This commit is contained in:
parent
8809fb2c22
commit
c1a88c9cf7
@ -1,11 +1,22 @@
|
||||
package d2dat
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
const (
|
||||
// index offset helpers
|
||||
b = iota
|
||||
g
|
||||
r
|
||||
o
|
||||
)
|
||||
|
||||
// Load loads a DAT file.
|
||||
func Load(data []byte) (*DATPalette, error) {
|
||||
func Load(data []byte) (d2interface.Palette, error) {
|
||||
palette := &DATPalette{}
|
||||
|
||||
for i := 0; i < 256; i++ {
|
||||
palette.Colors[i] = DATColor{B: data[i*3], G: data[i*3+1], R: data[i*3+2]}
|
||||
// offsets look like i*3+n, where n is 0,1,2
|
||||
palette.colors[i] = &DATColor{b: data[i*o+b], g: data[i*o+g], r: data[i*o+r]}
|
||||
}
|
||||
|
||||
return palette, nil
|
||||
|
@ -2,7 +2,76 @@ package d2dat
|
||||
|
||||
// DATColor represents a single color in a DAT file.
|
||||
type DATColor struct {
|
||||
R uint8
|
||||
G uint8
|
||||
B uint8
|
||||
r uint8
|
||||
g uint8
|
||||
b uint8
|
||||
a uint8
|
||||
}
|
||||
|
||||
const (
|
||||
colorBits = 8
|
||||
mask = 0xff
|
||||
)
|
||||
|
||||
const (
|
||||
bitShift0 = iota*colorBits
|
||||
bitShift8
|
||||
bitShift16
|
||||
bitShift24
|
||||
)
|
||||
|
||||
// R gets the red component
|
||||
func (c *DATColor) R() uint8 {
|
||||
return c.r
|
||||
}
|
||||
|
||||
// G gets the green component
|
||||
func (c *DATColor) G() uint8 {
|
||||
return c.g
|
||||
}
|
||||
|
||||
// B gets the blue component
|
||||
func (c *DATColor) B() uint8 {
|
||||
return c.b
|
||||
}
|
||||
|
||||
// A gets the alpha component
|
||||
func (c *DATColor) A() uint8 {
|
||||
return mask
|
||||
}
|
||||
|
||||
// RGBA gets the combination of the color components (0xRRGGBBAA)
|
||||
func (c *DATColor) RGBA() uint32 {
|
||||
return toComposite(c.r, c.g, c.b, c.a)
|
||||
}
|
||||
|
||||
// SetRGBA sets the color components using the given RGBA form
|
||||
func (c *DATColor) SetRGBA(rgba uint32) {
|
||||
c.r, c.g, c.b, c.a = toComponent(rgba)
|
||||
}
|
||||
|
||||
func (c *DATColor) BGRA() uint32 {
|
||||
return toComposite(c.b, c.g, c.r, c.a)
|
||||
}
|
||||
|
||||
func (c *DATColor) SetBGRA(bgra uint32) {
|
||||
c.b, c.g, c.r, c.a = toComponent(bgra)
|
||||
}
|
||||
|
||||
func toComposite (w,x,y,z uint8) uint32 {
|
||||
composite := uint32(w)<<bitShift24
|
||||
composite += uint32(x)<<bitShift16
|
||||
composite += uint32(y)<<bitShift8
|
||||
composite += uint32(z)<<bitShift0
|
||||
|
||||
return composite
|
||||
}
|
||||
|
||||
func toComponent (wxyz uint32) (w,x,y,z uint8){
|
||||
w = uint8(wxyz>>bitShift24 & mask)
|
||||
x = uint8(wxyz>>bitShift16 & mask)
|
||||
y = uint8(wxyz>>bitShift8 & mask)
|
||||
z = uint8(wxyz>>bitShift0 & mask)
|
||||
return w, x, y, z
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,34 @@
|
||||
package d2dat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
const (
|
||||
numColors = 256
|
||||
)
|
||||
|
||||
// DATPalette represents a 256 color palette.
|
||||
type DATPalette struct {
|
||||
Colors [256]DATColor
|
||||
colors [numColors]d2interface.Color
|
||||
}
|
||||
|
||||
// NumColors returns the number of colors in the palette
|
||||
func (p *DATPalette) NumColors() int {
|
||||
return len(p.colors)
|
||||
}
|
||||
|
||||
// GetColors returns the slice of colors in the palette
|
||||
func (p *DATPalette) GetColors() [numColors]d2interface.Color {
|
||||
return p.colors
|
||||
}
|
||||
|
||||
// GetColor returns a color by index
|
||||
func (p *DATPalette) GetColor(idx int) (d2interface.Color, error) {
|
||||
if color := p.colors[idx]; color != nil {
|
||||
return color, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("cannot find color index '%d in palette'", idx)
|
||||
}
|
||||
|
39
d2common/d2interface/animation.go
Normal file
39
d2common/d2interface/animation.go
Normal file
@ -0,0 +1,39 @@
|
||||
package d2interface
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
// Animation is an animation
|
||||
type Animation interface {
|
||||
Clone() Animation
|
||||
SetSubLoop(startFrame, EndFrame int)
|
||||
Advance(elapsed float64) error
|
||||
Render(target Surface) error
|
||||
RenderFromOrigin(target Surface) error
|
||||
RenderSection(sfc Surface, bound image.Rectangle) error
|
||||
GetFrameSize(frameIndex int) (int, int, error)
|
||||
GetCurrentFrameSize() (int, int)
|
||||
GetFrameBounds() (int, int)
|
||||
GetCurrentFrame() int
|
||||
GetFrameCount() int
|
||||
IsOnFirstFrame() bool
|
||||
IsOnLastFrame() bool
|
||||
GetDirectionCount() int
|
||||
SetDirection(directionIndex int) error
|
||||
GetDirection() int
|
||||
SetCurrentFrame(frameIndex int) error
|
||||
Rewind()
|
||||
PlayForward()
|
||||
PlayBackward()
|
||||
Pause()
|
||||
SetPlayLoop(loop bool)
|
||||
SetPlaySpeed(playSpeed float64)
|
||||
SetPlayLength(playLength float64)
|
||||
SetPlayLengthMs(playLengthMs int)
|
||||
SetColorMod(colorMod color.Color)
|
||||
GetPlayedCount() int
|
||||
ResetPlayedCount()
|
||||
SetBlend(blend bool)
|
||||
}
|
6
d2common/d2interface/archived_animation_manager.go
Normal file
6
d2common/d2interface/archived_animation_manager.go
Normal file
@ -0,0 +1,6 @@
|
||||
package d2interface
|
||||
|
||||
type ArchivedAnimationManager interface {
|
||||
Cacher
|
||||
LoadAnimation(animationPath, palettePath string, transparency int) (Animation, error)
|
||||
}
|
5
d2common/d2interface/archived_palette_manager.go
Normal file
5
d2common/d2interface/archived_palette_manager.go
Normal file
@ -0,0 +1,5 @@
|
||||
package d2interface
|
||||
|
||||
type ArchivedPaletteManager interface {
|
||||
LoadPalette(palettePath string) (Palette, error)
|
||||
}
|
22
d2common/d2interface/palette.go
Normal file
22
d2common/d2interface/palette.go
Normal file
@ -0,0 +1,22 @@
|
||||
package d2interface
|
||||
|
||||
const numColors = 256
|
||||
|
||||
// Color represents a color
|
||||
type Color interface {
|
||||
R() uint8
|
||||
G() uint8
|
||||
B() uint8
|
||||
A() uint8
|
||||
RGBA() uint32
|
||||
SetRGBA(uint32)
|
||||
BGRA() uint32
|
||||
SetBGRA(uint32)
|
||||
}
|
||||
|
||||
// Palette is a color palette
|
||||
type Palette interface {
|
||||
NumColors() int
|
||||
GetColors() [256]Color
|
||||
GetColor(idx int) (Color, error)
|
||||
}
|
@ -8,10 +8,9 @@ import (
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||
)
|
||||
@ -32,7 +31,7 @@ type animationFrame struct {
|
||||
offsetX int
|
||||
offsetY int
|
||||
|
||||
image d2interface.Surface
|
||||
image d2iface.Surface
|
||||
}
|
||||
|
||||
type animationDirection struct {
|
||||
@ -41,27 +40,25 @@ type animationDirection struct {
|
||||
|
||||
// Animation has directionality, play modes, and frame counting
|
||||
type Animation struct {
|
||||
directions []*animationDirection
|
||||
frameIndex int
|
||||
directionIndex int
|
||||
lastFrameTime float64
|
||||
playedCount int
|
||||
|
||||
compositeMode d2enum.CompositeMode
|
||||
colorMod color.Color
|
||||
originAtBottom bool
|
||||
|
||||
directions []*animationDirection
|
||||
colorMod color.Color
|
||||
frameIndex int
|
||||
directionIndex int
|
||||
lastFrameTime float64
|
||||
playedCount int
|
||||
compositeMode d2enum.CompositeMode
|
||||
playMode playMode
|
||||
playLength float64
|
||||
playLoop bool
|
||||
hasSubLoop bool // runs after first animation ends
|
||||
subStartingFrame int
|
||||
subEndingFrame int
|
||||
originAtBottom bool
|
||||
playLoop bool
|
||||
hasSubLoop bool // runs after first animation ends
|
||||
}
|
||||
|
||||
// CreateAnimationFromDCC creates an animation from d2dcc.DCC and d2dat.DATPalette
|
||||
func CreateAnimationFromDCC(renderer d2interface.Renderer, dcc *d2dcc.DCC, palette *d2dat.DATPalette,
|
||||
transparency int) (*Animation, error) {
|
||||
func CreateAnimationFromDCC(renderer d2iface.Renderer, dcc *d2dcc.DCC, palette d2iface.Palette,
|
||||
transparency int) (d2iface.Animation, error) {
|
||||
animation := &Animation{
|
||||
playLength: defaultPlayLength,
|
||||
playLoop: true,
|
||||
@ -87,18 +84,22 @@ func CreateAnimationFromDCC(renderer d2interface.Renderer, dcc *d2dcc.DCC, palet
|
||||
|
||||
for y := 0; y < frameHeight; y++ {
|
||||
for x := 0; x < frameWidth; x++ {
|
||||
if paletteIndex := dccFrame.PixelData[y*frameWidth+x]; paletteIndex != 0 {
|
||||
palColor := palette.Colors[paletteIndex]
|
||||
offset := (x + y*frameWidth) * bytesPerPixel
|
||||
pixels[offset] = palColor.R
|
||||
pixels[offset+1] = palColor.G
|
||||
pixels[offset+2] = palColor.B
|
||||
pixels[offset+3] = byte(transparency)
|
||||
paletteIndex := dccFrame.PixelData[y*frameWidth+x]
|
||||
|
||||
if paletteIndex == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
palColor := palette.GetColors()[paletteIndex]
|
||||
offset := (x + y*frameWidth) * bytesPerPixel
|
||||
pixels[offset] = palColor.R()
|
||||
pixels[offset+1] = palColor.G()
|
||||
pixels[offset+2] = palColor.B()
|
||||
pixels[offset+3] = byte(transparency)
|
||||
}
|
||||
}
|
||||
|
||||
sfc, err := renderer.NewSurface(frameWidth, frameHeight, d2interface.FilterNearest)
|
||||
sfc, err := renderer.NewSurface(frameWidth, frameHeight, d2iface.FilterNearest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -126,7 +127,8 @@ func CreateAnimationFromDCC(renderer d2interface.Renderer, dcc *d2dcc.DCC, palet
|
||||
}
|
||||
|
||||
// CreateAnimationFromDC6 creates an Animation from d2dc6.DC6 and d2dat.DATPalette
|
||||
func CreateAnimationFromDC6(renderer d2interface.Renderer, dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animation, error) {
|
||||
func CreateAnimationFromDC6(renderer d2iface.Renderer, dc6 *d2dc6.DC6,
|
||||
palette d2iface.Palette) (d2iface.Animation, error) {
|
||||
animation := &Animation{
|
||||
playLength: defaultPlayLength,
|
||||
playLoop: true,
|
||||
@ -134,7 +136,8 @@ func CreateAnimationFromDC6(renderer d2interface.Renderer, dc6 *d2dc6.DC6, palet
|
||||
}
|
||||
|
||||
for frameIndex, dc6Frame := range dc6.Frames {
|
||||
sfc, err := renderer.NewSurface(int(dc6Frame.Width), int(dc6Frame.Height), d2interface.FilterNearest)
|
||||
sfc, err := renderer.NewSurface(int(dc6Frame.Width), int(dc6Frame.Height),
|
||||
d2iface.FilterNearest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -177,14 +180,16 @@ func CreateAnimationFromDC6(renderer d2interface.Renderer, dc6 *d2dc6.DC6, palet
|
||||
colorData := make([]byte, int(dc6Frame.Width)*int(dc6Frame.Height)*bytesPerPixel)
|
||||
|
||||
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
|
||||
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
|
||||
// TODO: Is this == -1 or < 1?
|
||||
if indexData[i] < 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
colorData[i*bytesPerPixel] = palette.Colors[indexData[i]].R
|
||||
colorData[i*bytesPerPixel+1] = palette.Colors[indexData[i]].G
|
||||
colorData[i*bytesPerPixel+2] = palette.Colors[indexData[i]].B
|
||||
colorData[i*bytesPerPixel+3] = 0xff
|
||||
c := palette.GetColors()[indexData[i]]
|
||||
colorData[i*bytesPerPixel] = c.R()
|
||||
colorData[i*bytesPerPixel+1] = c.G()
|
||||
colorData[i*bytesPerPixel+2] = c.B()
|
||||
colorData[i*bytesPerPixel+3] = c.A()
|
||||
}
|
||||
|
||||
if err := sfc.ReplacePixels(colorData); err != nil {
|
||||
@ -209,17 +214,20 @@ func CreateAnimationFromDC6(renderer d2interface.Renderer, dc6 *d2dc6.DC6, palet
|
||||
return animation, nil
|
||||
}
|
||||
|
||||
func (a *Animation) Clone() *Animation {
|
||||
// Clone creates a copy of the animation
|
||||
func (a *Animation) Clone() d2iface.Animation {
|
||||
animation := *a
|
||||
return &animation
|
||||
}
|
||||
|
||||
func (a *Animation) SetSubLoop(startFrame, EndFrame int) {
|
||||
// SetSubLoop sets a sub loop for the animation
|
||||
func (a *Animation) SetSubLoop(startFrame, endFrame int) {
|
||||
a.subStartingFrame = startFrame
|
||||
a.subEndingFrame = EndFrame
|
||||
a.subEndingFrame = endFrame
|
||||
a.hasSubLoop = true
|
||||
}
|
||||
|
||||
// Advance advances the animation state
|
||||
func (a *Animation) Advance(elapsed float64) error {
|
||||
if a.playMode == playModePause {
|
||||
return nil
|
||||
@ -234,6 +242,7 @@ func (a *Animation) Advance(elapsed float64) error {
|
||||
for i := 0; i < framesAdvanced; i++ {
|
||||
startIndex := 0
|
||||
endIndex := frameCount
|
||||
|
||||
if a.hasSubLoop && a.playedCount > 0 {
|
||||
startIndex = a.subStartingFrame
|
||||
endIndex = a.subEndingFrame
|
||||
@ -268,7 +277,8 @@ func (a *Animation) Advance(elapsed float64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Animation) Render(target d2interface.Surface) error {
|
||||
// Render renders the animation to the given surface
|
||||
func (a *Animation) Render(target d2iface.Surface) error {
|
||||
direction := a.directions[a.directionIndex]
|
||||
frame := direction.frames[a.frameIndex]
|
||||
|
||||
@ -284,11 +294,13 @@ func (a *Animation) Render(target d2interface.Surface) error {
|
||||
return target.Render(frame.image)
|
||||
}
|
||||
|
||||
func (a *Animation) RenderFromOrigin(target d2interface.Surface) error {
|
||||
// RenderFromOrigin renders the animation from the animation origin
|
||||
func (a *Animation) RenderFromOrigin(target d2iface.Surface) error {
|
||||
if a.originAtBottom {
|
||||
direction := a.directions[a.directionIndex]
|
||||
frame := direction.frames[a.frameIndex]
|
||||
target.PushTranslation(0, -frame.height)
|
||||
|
||||
defer target.Pop()
|
||||
}
|
||||
|
||||
@ -296,37 +308,40 @@ func (a *Animation) RenderFromOrigin(target d2interface.Surface) error {
|
||||
}
|
||||
|
||||
// RenderSection renders the section of the animation frame enclosed by bounds
|
||||
func (a *Animation) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
|
||||
func (a *Animation) RenderSection(sfc d2iface.Surface, bound image.Rectangle) error {
|
||||
direction := a.directions[a.directionIndex]
|
||||
frame := direction.frames[a.frameIndex]
|
||||
|
||||
sfc.PushTranslation(frame.offsetX, frame.offsetY)
|
||||
sfc.PushCompositeMode(a.compositeMode)
|
||||
sfc.PushColor(a.colorMod)
|
||||
|
||||
defer sfc.PopN(3)
|
||||
|
||||
return sfc.RenderSection(frame.image, bound)
|
||||
}
|
||||
|
||||
// GetFrameSize gets the Size(width, height) of a indexed frame.
|
||||
func (a *Animation) GetFrameSize(frameIndex int) (int, int, error) {
|
||||
func (a *Animation) GetFrameSize(frameIndex int) (width, height int, err error) {
|
||||
direction := a.directions[a.directionIndex]
|
||||
if frameIndex >= len(direction.frames) {
|
||||
return 0, 0, errors.New("invalid frame index")
|
||||
}
|
||||
|
||||
frame := direction.frames[frameIndex]
|
||||
|
||||
return frame.width, frame.height, nil
|
||||
}
|
||||
|
||||
// GetCurrentFrameSize gets the Size(width, height) of the current frame.
|
||||
func (a *Animation) GetCurrentFrameSize() (int, int) {
|
||||
width, height, _ := a.GetFrameSize(a.frameIndex)
|
||||
func (a *Animation) GetCurrentFrameSize() (width, height int) {
|
||||
width, height, _ = a.GetFrameSize(a.frameIndex)
|
||||
return width, height
|
||||
}
|
||||
|
||||
// GetFrameBounds gets maximum Size(width, height) of all frame.
|
||||
func (a *Animation) GetFrameBounds() (int, int) {
|
||||
maxWidth, maxHeight := 0, 0
|
||||
func (a *Animation) GetFrameBounds() (maxWidth, maxHeight int) {
|
||||
maxWidth, maxHeight = 0, 0
|
||||
|
||||
direction := a.directions[a.directionIndex]
|
||||
for _, frame := range direction.frames {
|
||||
@ -427,13 +442,15 @@ func (a *Animation) SetPlaySpeed(playSpeed 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
|
||||
func (a *Animation) SetPlayLength(playLength float64) {
|
||||
// TODO refactor to use time.Duration instead of float64
|
||||
a.playLength = playLength
|
||||
a.lastFrameTime = 0
|
||||
}
|
||||
|
||||
// SetPlayLengthMs sets the Animation's play length in milliseconds
|
||||
func (a *Animation) SetPlayLengthMs(playLengthMs int) { // TODO remove this method
|
||||
func (a *Animation) SetPlayLengthMs(playLengthMs int) {
|
||||
// TODO remove this method
|
||||
const millisecondsPerSecond = 1000.0
|
||||
a.SetPlayLength(float64(playLengthMs) / millisecondsPerSecond)
|
||||
}
|
||||
|
@ -19,6 +19,14 @@ type animationManager struct {
|
||||
renderer d2interface.Renderer
|
||||
}
|
||||
|
||||
func (am *animationManager) ClearCache() {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (am *animationManager) GetCache() d2interface.Cache {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func createAnimationManager(renderer d2interface.Renderer) *animationManager {
|
||||
return &animationManager{
|
||||
renderer: renderer,
|
||||
@ -26,13 +34,15 @@ func createAnimationManager(renderer d2interface.Renderer) *animationManager {
|
||||
}
|
||||
}
|
||||
|
||||
func (am *animationManager) loadAnimation(animationPath, palettePath string, transparency int) (*Animation, error) {
|
||||
func (am *animationManager) LoadAnimation(
|
||||
animationPath, palettePath string,
|
||||
transparency int ) (d2interface.Animation, error) {
|
||||
cachePath := fmt.Sprintf("%s;%s;%d", animationPath, palettePath, transparency)
|
||||
if animation, found := am.cache.Retrieve(cachePath); found {
|
||||
return animation.(*Animation).Clone(), nil
|
||||
}
|
||||
|
||||
var animation *Animation
|
||||
var animation d2interface.Animation
|
||||
|
||||
ext := strings.ToLower(filepath.Ext(animationPath))
|
||||
switch ext {
|
||||
|
@ -10,9 +10,9 @@ import (
|
||||
type assetManager struct {
|
||||
archiveManager d2interface.ArchiveManager
|
||||
archivedFileManager d2interface.ArchivedFileManager
|
||||
paletteManager *paletteManager
|
||||
paletteManager d2interface.ArchivedPaletteManager
|
||||
paletteTransformManager *paletteTransformManager
|
||||
animationManager *animationManager
|
||||
animationManager d2interface.ArchivedAnimationManager
|
||||
fontManager *fontManager
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ type compositeMode struct {
|
||||
weaponClass string
|
||||
playedCount int
|
||||
|
||||
layers []*Animation
|
||||
layers []d2interface.Animation
|
||||
|
||||
frameCount int
|
||||
frameIndex int
|
||||
@ -194,7 +194,7 @@ func (c *Composite) createMode(animationMode, weaponClass string) (*compositeMod
|
||||
cof: cof,
|
||||
animationMode: animationMode,
|
||||
weaponClass: weaponClass,
|
||||
layers: make([]*Animation, d2enum.CompositeTypeMax),
|
||||
layers: make([]d2interface.Animation, d2enum.CompositeTypeMax),
|
||||
frameCount: animationData[0].FramesPerDirection,
|
||||
animationSpeed: 1.0 / ((float64(animationData[0].AnimationSpeed) * 25.0) / 256.0),
|
||||
}
|
||||
@ -240,7 +240,7 @@ func (c *Composite) createMode(animationMode, weaponClass string) (*compositeMod
|
||||
}
|
||||
|
||||
func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weaponClass,
|
||||
palettePath string, transparency int) (*Animation, error) {
|
||||
palettePath string, transparency int) (d2interface.Animation, error) {
|
||||
animationPaths := []string{
|
||||
fmt.Sprintf("%s/%s/%s/%s%s%s%s%s.dcc", c.basePath, c.token, layerKey, c.token, layerKey, layerValue, animationMode, weaponClass),
|
||||
fmt.Sprintf("%s/%s/%s/%s%s%s%s%s.dc6", c.basePath, c.token, layerKey, c.token, layerKey, layerValue, animationMode, weaponClass),
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
)
|
||||
|
||||
@ -106,13 +105,14 @@ func FileExists(filePath string) (bool, error) {
|
||||
}
|
||||
|
||||
// LoadAnimation loads an animation by its resource path and its palette path
|
||||
func LoadAnimation(animationPath, palettePath string) (*Animation, error) {
|
||||
func LoadAnimation(animationPath, palettePath string) (d2interface.Animation, error) {
|
||||
return LoadAnimationWithTransparency(animationPath, palettePath, 255)
|
||||
}
|
||||
|
||||
// LoadAnimationWithTransparency loads an animation by its resource path and its palette path with a given transparency value
|
||||
func LoadAnimationWithTransparency(animationPath, palettePath string, transparency int) (*Animation, error) {
|
||||
return singleton.animationManager.loadAnimation(animationPath, palettePath, transparency)
|
||||
func LoadAnimationWithTransparency(animationPath, palettePath string,
|
||||
transparency int) (d2interface.Animation, error) {
|
||||
return singleton.animationManager.LoadAnimation(animationPath, palettePath, transparency)
|
||||
}
|
||||
|
||||
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||
@ -126,6 +126,6 @@ func LoadFont(tablePath, spritePath, palettePath string) (*Font, error) {
|
||||
}
|
||||
|
||||
// LoadPalette loads a palette from a given palette path
|
||||
func LoadPalette(palettePath string) (*d2dat.DATPalette, error) {
|
||||
return singleton.paletteManager.loadPalette(palettePath)
|
||||
func LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||
return singleton.paletteManager.LoadPalette(palettePath)
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ type fontGlyph struct {
|
||||
|
||||
// Font represents a displayable font
|
||||
type Font struct {
|
||||
sheet *Animation
|
||||
sheet d2interface.Animation
|
||||
glyphs map[rune]fontGlyph
|
||||
color color.Color
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ func createPaletteManager() *paletteManager {
|
||||
return &paletteManager{d2common.CreateCache(paletteBudget)}
|
||||
}
|
||||
|
||||
func (pm *paletteManager) loadPalette(palettePath string) (*d2dat.DATPalette, error) {
|
||||
func (pm *paletteManager) LoadPalette(palettePath string) (d2interface.Palette, error) {
|
||||
if palette, found := pm.cache.Retrieve(palettePath); found {
|
||||
return palette.(*d2dat.DATPalette), nil
|
||||
return palette.(d2interface.Palette), nil
|
||||
}
|
||||
|
||||
paletteData, err := LoadFile(palettePath)
|
||||
|
@ -18,7 +18,8 @@ func loadFont(fontStyle FontStyle) (*d2asset.Font, error) {
|
||||
return d2asset.LoadFont(config.fontBasePath+".tbl", config.fontBasePath+".dc6", config.palettePath)
|
||||
}
|
||||
|
||||
func renderSegmented(animation *d2asset.Animation, segmentsX, segmentsY, frameOffset int, target d2interface.Surface) error {
|
||||
func renderSegmented(animation d2interface.Animation, segmentsX, segmentsY, frameOffset int,
|
||||
target d2interface.Surface) error {
|
||||
var currentY int
|
||||
for y := 0; y < segmentsY; y++ {
|
||||
var currentX int
|
||||
|
@ -13,10 +13,10 @@ import (
|
||||
|
||||
type manager struct {
|
||||
layout *Layout
|
||||
cursorAnim *d2asset.Animation
|
||||
cursorAnim d2interface.Animation
|
||||
cursorX int
|
||||
cursorY int
|
||||
loadingAnim *d2asset.Animation
|
||||
loadingAnim d2interface.Animation
|
||||
cursorVisible bool
|
||||
loading bool
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ type Sprite struct {
|
||||
segmentsY int
|
||||
frameOffset int
|
||||
|
||||
animation *d2asset.Animation
|
||||
animation d2interface.Animation
|
||||
}
|
||||
|
||||
type AnimatedSprite struct {
|
||||
|
@ -2,7 +2,6 @@ package d2mapentity
|
||||
|
||||
import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// AnimatedEntity represents an animation that can be projected onto the map.
|
||||
@ -12,11 +11,11 @@ type AnimatedEntity struct {
|
||||
action int
|
||||
repetitions int
|
||||
|
||||
animation *d2asset.Animation
|
||||
animation d2interface.Animation
|
||||
}
|
||||
|
||||
// CreateAnimatedEntity creates an instance of AnimatedEntity
|
||||
func CreateAnimatedEntity(x, y int, animation *d2asset.Animation) *AnimatedEntity {
|
||||
func CreateAnimatedEntity(x, y int, animation d2interface.Animation) *AnimatedEntity {
|
||||
entity := &AnimatedEntity{
|
||||
mapEntity: createMapEntity(x, y),
|
||||
animation: animation,
|
||||
|
@ -21,11 +21,11 @@ func (mr *MapRenderer) decodeTileGfxData(blocks []d2dt1.Block, pixels *[]byte, t
|
||||
for n > 0 {
|
||||
colorIndex := block.EncodedData[idx]
|
||||
if colorIndex != 0 {
|
||||
pixelColor := mr.palette.Colors[colorIndex]
|
||||
pixelColor := mr.palette.GetColors()[colorIndex]
|
||||
offset := 4 * (((blockY + y + tileYOffset) * tileWidth) + (blockX + x))
|
||||
(*pixels)[offset] = pixelColor.R
|
||||
(*pixels)[offset+1] = pixelColor.G
|
||||
(*pixels)[offset+2] = pixelColor.B
|
||||
(*pixels)[offset] = pixelColor.R()
|
||||
(*pixels)[offset+1] = pixelColor.G()
|
||||
(*pixels)[offset+2] = pixelColor.B()
|
||||
(*pixels)[offset+3] = 255
|
||||
}
|
||||
x++
|
||||
@ -58,12 +58,12 @@ func (mr *MapRenderer) decodeTileGfxData(blocks []d2dt1.Block, pixels *[]byte, t
|
||||
for b2 > 0 {
|
||||
colorIndex := block.EncodedData[idx]
|
||||
if colorIndex != 0 {
|
||||
pixelColor := mr.palette.Colors[colorIndex]
|
||||
pixelColor := mr.palette.GetColors()[colorIndex]
|
||||
|
||||
offset := 4 * (((blockY + y + tileYOffset) * tileWidth) + (blockX + x))
|
||||
(*pixels)[offset] = pixelColor.R
|
||||
(*pixels)[offset+1] = pixelColor.G
|
||||
(*pixels)[offset+2] = pixelColor.B
|
||||
(*pixels)[offset] = pixelColor.R()
|
||||
(*pixels)[offset+1] = pixelColor.G()
|
||||
(*pixels)[offset+2] = pixelColor.B()
|
||||
(*pixels)[offset+3] = 255
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
|
||||
@ -19,7 +18,7 @@ import (
|
||||
type MapRenderer struct {
|
||||
renderer d2interface.Renderer // The renderer to use for drawing operations
|
||||
mapEngine *d2mapengine.MapEngine // The map engine that is being rendered
|
||||
palette *d2dat.DATPalette // The palette used for this map
|
||||
palette d2interface.Palette // The palette used for this map
|
||||
viewport *Viewport // The viewport for the map renderer (used for rendering offsets)
|
||||
camera Camera // The camera for this map renderer (used to determine where on the map we are rendering)
|
||||
debugVisLevel int // Debug visibility index (0=none, 1=tiles, 2=sub-tiles)
|
||||
@ -354,7 +353,7 @@ func (mr *MapRenderer) Advance(elapsed float64) {
|
||||
}
|
||||
}
|
||||
|
||||
func loadPaletteForAct(levelType d2enum.RegionIdType) (*d2dat.DATPalette, error) {
|
||||
func loadPaletteForAct(levelType d2enum.RegionIdType) (d2interface.Palette, error) {
|
||||
var palettePath string
|
||||
switch levelType {
|
||||
case d2enum.RegionAct1Town, d2enum.RegionAct1Wilderness, d2enum.RegionAct1Cave, d2enum.RegionAct1Crypt,
|
||||
|
@ -8,21 +8,20 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
// Sprite is a positioned visual object.
|
||||
type Sprite struct {
|
||||
x int
|
||||
y int
|
||||
animation *d2asset.Animation
|
||||
animation d2interface.Animation
|
||||
}
|
||||
|
||||
var (
|
||||
ErrNoAnimation = errors.New("no animation was specified")
|
||||
)
|
||||
|
||||
func LoadSprite(animation *d2asset.Animation) (*Sprite, error) {
|
||||
func LoadSprite(animation d2interface.Animation) (*Sprite, error) {
|
||||
if animation == nil {
|
||||
return nil, ErrNoAnimation
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user