mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-05 19:14:14 -04:00
Added support for all object layers. (#127)
This commit is contained in:
parent
09e713b1cb
commit
3555578c0e
@ -3,7 +3,6 @@ package common
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"math"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -12,18 +11,19 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten"
|
"github.com/hajimehoshi/ebiten"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var DccLayerNames = []string{"HD", "TR", "LG", "RA", "LA", "RH", "LH", "SH", "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8"}
|
||||||
|
|
||||||
// AnimatedEntity represents an entity on the map that can be animated
|
// AnimatedEntity represents an entity on the map that can be animated
|
||||||
type AnimatedEntity struct {
|
type AnimatedEntity struct {
|
||||||
// LocationX represents the tile X position of the entity
|
// LocationX represents the tile X position of the entity
|
||||||
LocationX float64
|
LocationX float64
|
||||||
// LocationY represents the tile Y position of the entity
|
// LocationY represents the tile Y position of the entity
|
||||||
LocationY float64
|
LocationY float64
|
||||||
dcc *DCC
|
dccLayers map[string]*DCC
|
||||||
cof *Cof
|
Cof *Cof
|
||||||
palette palettedefs.PaletteType
|
palette palettedefs.PaletteType
|
||||||
base string
|
base string
|
||||||
token string
|
token string
|
||||||
tr string
|
|
||||||
animationMode string
|
animationMode string
|
||||||
weaponClass string
|
weaponClass string
|
||||||
lastFrameTime time.Time
|
lastFrameTime time.Time
|
||||||
@ -31,8 +31,9 @@ type AnimatedEntity struct {
|
|||||||
animationSpeed int
|
animationSpeed int
|
||||||
direction int
|
direction int
|
||||||
currentFrame int
|
currentFrame int
|
||||||
frames []*ebiten.Image
|
frames map[string][]*ebiten.Image
|
||||||
frameLocations []Rectangle
|
frameLocations map[string][]Rectangle
|
||||||
|
object Object
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateAnimatedEntity creates an instance of AnimatedEntity
|
// CreateAnimatedEntity creates an instance of AnimatedEntity
|
||||||
@ -40,11 +41,12 @@ func CreateAnimatedEntity(object Object, fileProvider FileProvider, palette pale
|
|||||||
result := &AnimatedEntity{
|
result := &AnimatedEntity{
|
||||||
base: object.Lookup.Base,
|
base: object.Lookup.Base,
|
||||||
token: object.Lookup.Token,
|
token: object.Lookup.Token,
|
||||||
tr: object.Lookup.TR,
|
object: object,
|
||||||
palette: palette,
|
palette: palette,
|
||||||
}
|
}
|
||||||
result.LocationX = math.Floor(float64(object.X) / 5)
|
result.dccLayers = make(map[string]*DCC)
|
||||||
result.LocationY = math.Floor(float64(object.Y) / 5)
|
result.LocationX = float64(object.X) / 5
|
||||||
|
result.LocationY = float64(object.Y) / 5
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,14 +55,69 @@ var DirectionLookup = []int{3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14
|
|||||||
|
|
||||||
// SetMode changes the graphical mode of this animated entity
|
// SetMode changes the graphical mode of this animated entity
|
||||||
func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction int, provider FileProvider) {
|
func (v *AnimatedEntity) SetMode(animationMode, weaponClass string, direction int, provider FileProvider) {
|
||||||
dccPath := fmt.Sprintf("%s/%s/tr/%str%s%s%s.dcc", v.base, v.token, v.token, v.tr, animationMode, weaponClass)
|
cofPath := fmt.Sprintf("%s/%s/Cof/%s%s%s.Cof", v.base, v.token, v.token, animationMode, weaponClass)
|
||||||
v.dcc = LoadDCC(dccPath, provider)
|
v.Cof = LoadCof(cofPath, provider)
|
||||||
cofPath := fmt.Sprintf("%s/%s/cof/%s%s%s.cof", v.base, v.token, v.token, animationMode, weaponClass)
|
|
||||||
v.cof = LoadCof(cofPath, provider)
|
|
||||||
v.animationMode = animationMode
|
v.animationMode = animationMode
|
||||||
v.weaponClass = weaponClass
|
v.weaponClass = weaponClass
|
||||||
v.direction = direction
|
v.direction = direction
|
||||||
v.cacheFrames()
|
if v.direction >= v.Cof.NumberOfDirections {
|
||||||
|
v.direction = v.Cof.NumberOfDirections - 1
|
||||||
|
}
|
||||||
|
v.frames = make(map[string][]*ebiten.Image)
|
||||||
|
v.frameLocations = make(map[string][]Rectangle)
|
||||||
|
v.dccLayers = make(map[string]*DCC)
|
||||||
|
for _, cofLayer := range v.Cof.CofLayers {
|
||||||
|
layerName := DccLayerNames[cofLayer.Type]
|
||||||
|
v.dccLayers[layerName] = v.LoadLayer(layerName, provider)
|
||||||
|
if v.dccLayers[layerName] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.cacheFrames(layerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *AnimatedEntity) LoadLayer(layer string, fileProvider FileProvider) *DCC {
|
||||||
|
layerName := "tr"
|
||||||
|
switch strings.ToUpper(layer) {
|
||||||
|
case "HD": // Head
|
||||||
|
layerName = v.object.Lookup.HD
|
||||||
|
case "TR": // Torso
|
||||||
|
layerName = v.object.Lookup.TR
|
||||||
|
case "LG": // Legs
|
||||||
|
layerName = v.object.Lookup.LG
|
||||||
|
case "RA": // RightArm
|
||||||
|
layerName = v.object.Lookup.RA
|
||||||
|
case "LA": // LeftArm
|
||||||
|
layerName = v.object.Lookup.LA
|
||||||
|
case "RH": // RightHand
|
||||||
|
layerName = v.object.Lookup.RH
|
||||||
|
case "LH": // LeftHand
|
||||||
|
layerName = v.object.Lookup.LH
|
||||||
|
case "SH": // Shield
|
||||||
|
layerName = v.object.Lookup.SH
|
||||||
|
case "S1": // Special1
|
||||||
|
layerName = v.object.Lookup.S1
|
||||||
|
case "S2": // Special2
|
||||||
|
layerName = v.object.Lookup.S2
|
||||||
|
case "S3": // Special3
|
||||||
|
layerName = v.object.Lookup.S3
|
||||||
|
case "S4": // Special4
|
||||||
|
layerName = v.object.Lookup.S4
|
||||||
|
case "S5": // Special5
|
||||||
|
layerName = v.object.Lookup.S5
|
||||||
|
case "S6": // Special6
|
||||||
|
layerName = v.object.Lookup.S6
|
||||||
|
case "S7": // Special7
|
||||||
|
layerName = v.object.Lookup.S7
|
||||||
|
case "S8": // Special8
|
||||||
|
layerName = v.object.Lookup.S8
|
||||||
|
}
|
||||||
|
if len(layerName) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dccPath := fmt.Sprintf("%s/%s/%s/%s%s%s%s%s.dcc", v.base, v.token, layer, v.token, layer, layerName, v.animationMode, v.weaponClass)
|
||||||
|
return LoadDCC(dccPath, fileProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render draws this animated entity onto the target
|
// Render draws this animated entity onto the target
|
||||||
@ -72,23 +129,35 @@ func (v *AnimatedEntity) Render(target *ebiten.Image, offsetX, offsetY int) {
|
|||||||
v.currentFrame = 0
|
v.currentFrame = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for idx := 0; idx < v.Cof.NumberOfLayers; idx++ {
|
||||||
|
priority := v.Cof.Priority[v.direction][v.currentFrame][idx]
|
||||||
|
if int(priority) >= len(DccLayerNames) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
frameName := DccLayerNames[priority]
|
||||||
|
if v.frames[frameName] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// TODO: Transparency op maybe, but it'l murder batch calls
|
||||||
opts := &ebiten.DrawImageOptions{}
|
opts := &ebiten.DrawImageOptions{}
|
||||||
opts.GeoM.Translate(float64(v.frameLocations[v.currentFrame].Left+offsetX), float64(v.frameLocations[v.currentFrame].Top+offsetY+40))
|
opts.GeoM.Translate(float64(v.frameLocations[frameName][v.currentFrame].Left+offsetX),
|
||||||
target.DrawImage(v.frames[v.currentFrame], opts)
|
float64(v.frameLocations[frameName][v.currentFrame].Top+offsetY+40))
|
||||||
|
target.DrawImage(v.frames[frameName][v.currentFrame], opts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *AnimatedEntity) cacheFrames() {
|
func (v *AnimatedEntity) cacheFrames(layerName string) {
|
||||||
|
dcc := v.dccLayers[layerName]
|
||||||
v.currentFrame = 0
|
v.currentFrame = 0
|
||||||
animationData := AnimationData[strings.ToLower(v.token+v.animationMode+v.weaponClass)][0]
|
animationData := AnimationData[strings.ToLower(v.token+v.animationMode+v.weaponClass)][0]
|
||||||
v.animationSpeed = int(1000.0 / ((float64(animationData.AnimationSpeed) * 25.0) / 256.0))
|
v.animationSpeed = int(1000.0 / ((float64(animationData.AnimationSpeed) * 25.0) / 256.0))
|
||||||
v.framesToAnimate = animationData.FramesPerDirection
|
v.framesToAnimate = animationData.FramesPerDirection
|
||||||
v.lastFrameTime = time.Now()
|
v.lastFrameTime = time.Now()
|
||||||
minX := int32(2147483647)
|
minX := int32(10000)
|
||||||
minY := int32(2147483647)
|
minY := int32(10000)
|
||||||
maxX := int32(-2147483648)
|
maxX := int32(-10000)
|
||||||
maxY := int32(-2147483648)
|
maxY := int32(-10000)
|
||||||
for _, layer := range v.dcc.Directions {
|
for _, layer := range dcc.Directions {
|
||||||
minX = MinInt32(minX, int32(layer.Box.Left))
|
minX = MinInt32(minX, int32(layer.Box.Left))
|
||||||
minY = MinInt32(minY, int32(layer.Box.Top))
|
minY = MinInt32(minY, int32(layer.Box.Top))
|
||||||
maxX = MaxInt32(maxX, int32(layer.Box.Right()))
|
maxX = MaxInt32(maxX, int32(layer.Box.Right()))
|
||||||
@ -96,17 +165,17 @@ func (v *AnimatedEntity) cacheFrames() {
|
|||||||
}
|
}
|
||||||
frameW := maxX - minX
|
frameW := maxX - minX
|
||||||
frameH := maxY - minY
|
frameH := maxY - minY
|
||||||
v.frames = make([]*ebiten.Image, v.framesToAnimate)
|
v.frames[layerName] = make([]*ebiten.Image, v.framesToAnimate)
|
||||||
v.frameLocations = make([]Rectangle, v.framesToAnimate)
|
v.frameLocations[layerName] = make([]Rectangle, v.framesToAnimate)
|
||||||
for frameIndex := range v.frames {
|
for frameIndex := range v.frames[layerName] {
|
||||||
v.frames[frameIndex], _ = ebiten.NewImage(int(frameW), int(frameH), ebiten.FilterNearest)
|
v.frames[layerName][frameIndex], _ = ebiten.NewImage(int(frameW), int(frameH), ebiten.FilterNearest)
|
||||||
priorityBase := (v.direction * animationData.FramesPerDirection * v.cof.NumberOfLayers) + (frameIndex * v.cof.NumberOfLayers)
|
for layerIdx := 0; layerIdx < v.Cof.NumberOfLayers; layerIdx++ {
|
||||||
for layerIdx := 0; layerIdx < v.cof.NumberOfLayers; layerIdx++ {
|
transparency := byte(255)
|
||||||
comp := v.cof.Priority[priorityBase+layerIdx]
|
if v.Cof.CofLayers[layerIdx].Transparent {
|
||||||
if _, found := v.cof.CompositeLayers[comp]; !found {
|
transparency = byte(128)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
direction := v.dcc.Directions[v.direction]
|
|
||||||
|
direction := dcc.Directions[v.direction]
|
||||||
frame := direction.Frames[frameIndex]
|
frame := direction.Frames[frameIndex]
|
||||||
img := image.NewRGBA(image.Rect(0, 0, int(frameW), int(frameH)))
|
img := image.NewRGBA(image.Rect(0, 0, int(frameW), int(frameH)))
|
||||||
for y := 0; y < direction.Box.Height; y++ {
|
for y := 0; y < direction.Box.Height; y++ {
|
||||||
@ -122,13 +191,13 @@ func (v *AnimatedEntity) cacheFrames() {
|
|||||||
img.Pix[(actualX*4)+(actualY*int(frameW)*4)] = color.R
|
img.Pix[(actualX*4)+(actualY*int(frameW)*4)] = color.R
|
||||||
img.Pix[(actualX*4)+(actualY*int(frameW)*4)+1] = color.G
|
img.Pix[(actualX*4)+(actualY*int(frameW)*4)+1] = color.G
|
||||||
img.Pix[(actualX*4)+(actualY*int(frameW)*4)+2] = color.B
|
img.Pix[(actualX*4)+(actualY*int(frameW)*4)+2] = color.B
|
||||||
img.Pix[(actualX*4)+(actualY*int(frameW)*4)+3] = 255
|
img.Pix[(actualX*4)+(actualY*int(frameW)*4)+3] = transparency
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newImage, _ := ebiten.NewImageFromImage(img, ebiten.FilterNearest)
|
newImage, _ := ebiten.NewImageFromImage(img, ebiten.FilterNearest)
|
||||||
img = nil
|
img = nil
|
||||||
v.frames[frameIndex] = newImage
|
v.frames[layerName][frameIndex] = newImage
|
||||||
v.frameLocations[frameIndex] = Rectangle{
|
v.frameLocations[layerName][frameIndex] = Rectangle{
|
||||||
Left: int(minX),
|
Left: int(minX),
|
||||||
Top: int(minY),
|
Top: int(minY),
|
||||||
Width: int(frameW),
|
Width: int(frameW),
|
||||||
|
@ -31,6 +31,7 @@ func (v *BitMuncher) GetBit() uint32 {
|
|||||||
|
|
||||||
func (v *BitMuncher) SkipBits(bits int) {
|
func (v *BitMuncher) SkipBits(bits int) {
|
||||||
v.Offset += bits
|
v.Offset += bits
|
||||||
|
v.BitsRead += bits
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *BitMuncher) GetByte() byte {
|
func (v *BitMuncher) GetByte() byte {
|
||||||
|
@ -204,7 +204,7 @@ type Cof struct {
|
|||||||
CofLayers []*CofLayer
|
CofLayers []*CofLayer
|
||||||
CompositeLayers map[CompositeType]int
|
CompositeLayers map[CompositeType]int
|
||||||
AnimationFrames []AnimationFrame
|
AnimationFrames []AnimationFrame
|
||||||
Priority []CompositeType
|
Priority [][][]CompositeType
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadCof(fileName string, fileProvider FileProvider) *Cof {
|
func LoadCof(fileName string, fileProvider FileProvider) *Cof {
|
||||||
@ -235,10 +235,16 @@ func LoadCof(fileName string, fileProvider FileProvider) *Cof {
|
|||||||
result.AnimationFrames[i] = AnimationFrame(animationFrameBytes[i])
|
result.AnimationFrames[i] = AnimationFrame(animationFrameBytes[i])
|
||||||
}
|
}
|
||||||
priorityLen := result.FramesPerDirection * result.NumberOfDirections * result.NumberOfLayers
|
priorityLen := result.FramesPerDirection * result.NumberOfDirections * result.NumberOfLayers
|
||||||
result.Priority = make([]CompositeType, priorityLen)
|
result.Priority = make([][][]CompositeType, result.NumberOfDirections)
|
||||||
priorityBytes, _ := streamReader.ReadBytes(priorityLen)
|
priorityBytes, _ := streamReader.ReadBytes(priorityLen)
|
||||||
for i := range priorityBytes {
|
for direction := 0; direction < result.NumberOfDirections; direction++ {
|
||||||
result.Priority[i] = CompositeType(priorityBytes[i])
|
result.Priority[direction] = make([][]CompositeType, result.FramesPerDirection)
|
||||||
|
for frame := 0; frame < result.FramesPerDirection; frame++ {
|
||||||
|
result.Priority[direction][frame] = make([]CompositeType, result.NumberOfLayers)
|
||||||
|
for i := 0; i < result.NumberOfLayers; i++ {
|
||||||
|
result.Priority[direction][frame][i] = CompositeType(priorityBytes[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package common
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DCCPixelBufferEntry struct {
|
type DCCPixelBufferEntry struct {
|
||||||
@ -52,7 +51,7 @@ type DCCDirection struct {
|
|||||||
EncodingTypeBitsreamSize int
|
EncodingTypeBitsreamSize int
|
||||||
RawPixelCodesBitstreamSize int
|
RawPixelCodesBitstreamSize int
|
||||||
Frames []*DCCDirectionFrame
|
Frames []*DCCDirectionFrame
|
||||||
PaletteEntries []byte
|
PaletteEntries [256]byte
|
||||||
Box Rectangle
|
Box Rectangle
|
||||||
Cells []*DCCCell
|
Cells []*DCCCell
|
||||||
PixelData []byte
|
PixelData []byte
|
||||||
@ -71,6 +70,11 @@ type DCC struct {
|
|||||||
|
|
||||||
var crazyBitTable = []byte{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32}
|
var crazyBitTable = []byte{0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 26, 28, 30, 32}
|
||||||
var pixelMaskLookup = []int{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}
|
var pixelMaskLookup = []int{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4}
|
||||||
|
var dccDir4 = []byte{0, 1, 2, 3}
|
||||||
|
var dccDir8 = []byte{4, 0, 5, 1, 6, 2, 7, 3}
|
||||||
|
var dccDir16 = []byte{4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14, 3, 15}
|
||||||
|
var dccDir32 = []byte{4, 16, 8, 17, 0, 18, 9, 19, 5, 20, 10, 21, 1, 22, 11, 23,
|
||||||
|
6, 24, 12, 25, 2, 26, 13, 27, 7, 28, 14, 29, 3, 30, 15, 31}
|
||||||
|
|
||||||
func CreateDCCDirectionFrame(bits *BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
|
func CreateDCCDirectionFrame(bits *BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
|
||||||
result := &DCCDirectionFrame{}
|
result := &DCCDirectionFrame{}
|
||||||
@ -82,12 +86,16 @@ func CreateDCCDirectionFrame(bits *BitMuncher, direction *DCCDirection) *DCCDire
|
|||||||
result.NumberOfOptionalBytes = int(bits.GetBits(direction.OptionalDataBits))
|
result.NumberOfOptionalBytes = int(bits.GetBits(direction.OptionalDataBits))
|
||||||
result.NumberOfCodedBytes = int(bits.GetBits(direction.CodedBytesBits))
|
result.NumberOfCodedBytes = int(bits.GetBits(direction.CodedBytesBits))
|
||||||
result.FrameIsBottomUp = bits.GetBit() == 1
|
result.FrameIsBottomUp = bits.GetBit() == 1
|
||||||
|
if result.FrameIsBottomUp {
|
||||||
|
log.Panic("Bottom up frames are not implemented.")
|
||||||
|
} else {
|
||||||
result.Box = Rectangle{
|
result.Box = Rectangle{
|
||||||
result.XOffset,
|
result.XOffset,
|
||||||
result.YOffset - result.Height - 1,
|
result.YOffset - result.Height + 1,
|
||||||
result.Width,
|
result.Width,
|
||||||
result.Height,
|
result.Height,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,10 +172,10 @@ func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
|||||||
result.OptionalDataBits = int(crazyBitTable[bm.GetBits(4)])
|
result.OptionalDataBits = int(crazyBitTable[bm.GetBits(4)])
|
||||||
result.CodedBytesBits = int(crazyBitTable[bm.GetBits(4)])
|
result.CodedBytesBits = int(crazyBitTable[bm.GetBits(4)])
|
||||||
result.Frames = make([]*DCCDirectionFrame, file.FramesPerDirection)
|
result.Frames = make([]*DCCDirectionFrame, file.FramesPerDirection)
|
||||||
minx := 9223372036854775807
|
minx := 100000
|
||||||
miny := 9223372036854775807
|
miny := 100000
|
||||||
maxx := -9223372036854775808
|
maxx := -100000
|
||||||
maxy := -9223372036854775808
|
maxy := -100000
|
||||||
// Load the frame headers
|
// Load the frame headers
|
||||||
for frameIdx := 0; frameIdx < file.FramesPerDirection; frameIdx++ {
|
for frameIdx := 0; frameIdx < file.FramesPerDirection; frameIdx++ {
|
||||||
result.Frames[frameIdx] = CreateDCCDirectionFrame(bm, result)
|
result.Frames[frameIdx] = CreateDCCDirectionFrame(bm, result)
|
||||||
@ -176,7 +184,7 @@ func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
|||||||
maxx = int(MaxInt32(int32(result.Frames[frameIdx].Box.Right()), int32(maxx)))
|
maxx = int(MaxInt32(int32(result.Frames[frameIdx].Box.Right()), int32(maxx)))
|
||||||
maxy = int(MaxInt32(int32(result.Frames[frameIdx].Box.Bottom()), int32(maxy)))
|
maxy = int(MaxInt32(int32(result.Frames[frameIdx].Box.Bottom()), int32(maxy)))
|
||||||
}
|
}
|
||||||
result.Box = Rectangle{minx, miny, maxx - minx, maxy - miny}
|
result.Box = Rectangle{minx, miny, (maxx - minx), (maxy - miny)}
|
||||||
if result.OptionalDataBits > 0 {
|
if result.OptionalDataBits > 0 {
|
||||||
log.Panic("Optional bits in DCC data is not currently supported.")
|
log.Panic("Optional bits in DCC data is not currently supported.")
|
||||||
}
|
}
|
||||||
@ -189,24 +197,14 @@ func CreateDCCDirection(bm *BitMuncher, file *DCC) *DCCDirection {
|
|||||||
result.RawPixelCodesBitstreamSize = int(bm.GetBits(20))
|
result.RawPixelCodesBitstreamSize = int(bm.GetBits(20))
|
||||||
}
|
}
|
||||||
// PixelValuesKey
|
// PixelValuesKey
|
||||||
paletteEntries := make([]bool, 0)
|
|
||||||
paletteEntryCount := 0
|
paletteEntryCount := 0
|
||||||
for i := 0; i < 256; i++ {
|
for i := 0; i < 256; i++ {
|
||||||
valid := bm.GetBit() != 0
|
valid := bm.GetBit() != 0
|
||||||
paletteEntries = append(paletteEntries, valid)
|
|
||||||
if valid {
|
if valid {
|
||||||
|
result.PaletteEntries[paletteEntryCount] = byte(i)
|
||||||
paletteEntryCount++
|
paletteEntryCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.PaletteEntries = make([]byte, paletteEntryCount)
|
|
||||||
paletteOffset := 0
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
if !paletteEntries[i] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
result.PaletteEntries[paletteOffset] = byte(i)
|
|
||||||
paletteOffset++
|
|
||||||
}
|
|
||||||
// HERE BE GIANTS:
|
// HERE BE GIANTS:
|
||||||
// Because of the way this thing mashes bits together, BIT offset matters
|
// Because of the way this thing mashes bits together, BIT offset matters
|
||||||
// here. For example, if you are on byte offset 3, bit offset 6, and
|
// here. For example, if you are on byte offset 3, bit offset 6, and
|
||||||
@ -343,10 +341,12 @@ func (v *DCCDirection) GenerateFrames(pcd *BitMuncher) {
|
|||||||
|
|
||||||
func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *BitMuncher) {
|
func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *BitMuncher) {
|
||||||
lastPixel := uint32(0)
|
lastPixel := uint32(0)
|
||||||
pixelStack := make([]uint32, 4)
|
|
||||||
maxCellX := 0
|
maxCellX := 0
|
||||||
maxCellY := 0
|
maxCellY := 0
|
||||||
for _, frame := range v.Frames {
|
for _, frame := range v.Frames {
|
||||||
|
if frame == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
maxCellX += frame.HorizontalCellCount
|
maxCellX += frame.HorizontalCellCount
|
||||||
maxCellY += frame.VerticalCellCount
|
maxCellY += frame.VerticalCellCount
|
||||||
}
|
}
|
||||||
@ -366,11 +366,9 @@ func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *BitMuncher) {
|
|||||||
frameIndex++
|
frameIndex++
|
||||||
originCellX := (frame.Box.Left - v.Box.Left) / 4
|
originCellX := (frame.Box.Left - v.Box.Left) / 4
|
||||||
originCellY := (frame.Box.Top - v.Box.Top) / 4
|
originCellY := (frame.Box.Top - v.Box.Top) / 4
|
||||||
frameCellIndex := 0
|
|
||||||
for cellY := 0; cellY < frame.VerticalCellCount; cellY++ {
|
for cellY := 0; cellY < frame.VerticalCellCount; cellY++ {
|
||||||
currentCellY := cellY + originCellY
|
currentCellY := cellY + originCellY
|
||||||
for cellX := 0; cellX < frame.HorizontalCellCount; cellX++ {
|
for cellX := 0; cellX < frame.HorizontalCellCount; cellX++ {
|
||||||
frameCellIndex++
|
|
||||||
currentCell := originCellX + cellX + (currentCellY * v.HorizontalCellCount)
|
currentCell := originCellX + cellX + (currentCellY * v.HorizontalCellCount)
|
||||||
nextCell := false
|
nextCell := false
|
||||||
tmp := 0
|
tmp := 0
|
||||||
@ -392,6 +390,7 @@ func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *BitMuncher) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Decode the pixels
|
// Decode the pixels
|
||||||
|
var pixelStack [4]uint32
|
||||||
lastPixel = 0
|
lastPixel = 0
|
||||||
numberOfPixelBits := pixelMaskLookup[pixelMask]
|
numberOfPixelBits := pixelMaskLookup[pixelMask]
|
||||||
encodingType := 0
|
encodingType := 0
|
||||||
@ -415,7 +414,7 @@ func (v *DCCDirection) FillPixelBuffer(pcd, ec, pm, et, rp *BitMuncher) {
|
|||||||
}
|
}
|
||||||
if pixelStack[i] == lastPixel {
|
if pixelStack[i] == lastPixel {
|
||||||
pixelStack[i] = 0
|
pixelStack[i] = 0
|
||||||
i = numberOfPixelBits // Just break here....
|
break
|
||||||
} else {
|
} else {
|
||||||
lastPixel = pixelStack[i]
|
lastPixel = pixelStack[i]
|
||||||
decodedPixel++
|
decodedPixel++
|
||||||
@ -514,15 +513,22 @@ func LoadDCC(path string, fileProvider FileProvider) *DCC {
|
|||||||
directionOffsets[i] = int(bm.GetInt32())
|
directionOffsets[i] = int(bm.GetInt32())
|
||||||
}
|
}
|
||||||
result.Directions = make([]*DCCDirection, result.NumberOfDirections)
|
result.Directions = make([]*DCCDirection, result.NumberOfDirections)
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(result.NumberOfDirections)
|
|
||||||
for i := 0; i < result.NumberOfDirections; i++ {
|
for i := 0; i < result.NumberOfDirections; i++ {
|
||||||
go func(i int) {
|
dir := byte(0)
|
||||||
defer wg.Done()
|
switch result.NumberOfDirections {
|
||||||
result.Directions[i] = CreateDCCDirection(CreateBitMuncher(fileData, directionOffsets[i]*8), result)
|
case 1:
|
||||||
}(i)
|
dir = 0
|
||||||
|
case 4:
|
||||||
|
dir = dccDir4[i]
|
||||||
|
case 8:
|
||||||
|
dir = dccDir8[i]
|
||||||
|
case 16:
|
||||||
|
dir = dccDir16[i]
|
||||||
|
case 32:
|
||||||
|
dir = dccDir32[i]
|
||||||
|
}
|
||||||
|
result.Directions[dir] = CreateDCCDirection(CreateBitMuncher(fileData, directionOffsets[i]*8), result)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,7 @@ func CreateNPC(object Object, fileProvider FileProvider) *NPC {
|
|||||||
AnimatedEntity: CreateAnimatedEntity(object, fileProvider, palettedefs.Units),
|
AnimatedEntity: CreateAnimatedEntity(object, fileProvider, palettedefs.Units),
|
||||||
Paths: object.Paths,
|
Paths: object.Paths,
|
||||||
}
|
}
|
||||||
result.AnimatedEntity.SetMode(object.Lookup.Mode, object.Lookup.Class, 0, fileProvider)
|
result.AnimatedEntity.SetMode(object.Lookup.Mode, object.Lookup.Class, 1, fileProvider)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ func (v *Region) loadObjects(fileProvider common.FileProvider) {
|
|||||||
npc := common.CreateNPC(object, fileProvider)
|
npc := common.CreateNPC(object, fileProvider)
|
||||||
v.NPCs = append(v.NPCs, npc)
|
v.NPCs = append(v.NPCs, npc)
|
||||||
case common.ObjectTypeItem:
|
case common.ObjectTypeItem:
|
||||||
if object.ObjectInfo == nil || !object.ObjectInfo.Draw || object.Lookup.Base == "" || object.Lookup.Token == "" || object.Lookup.TR == "" {
|
if object.ObjectInfo == nil || !object.ObjectInfo.Draw || object.Lookup.Base == "" || object.Lookup.Token == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
entity := common.CreateAnimatedEntity(object, fileProvider, palettedefs.Units)
|
entity := common.CreateAnimatedEntity(object, fileProvider, palettedefs.Units)
|
||||||
|
Loading…
Reference in New Issue
Block a user