OpenDiablo2/d2common/d2fileformats/d2dcc/dcc_direction_frame.go

124 lines
3.4 KiB
Go

package d2dcc
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"log"
)
// DCCDirectionFrame represents a direction frame for a DCC.
type DCCDirectionFrame struct {
Box d2geom.Rectangle
Cells []DCCCell
PixelData []byte
Width int
Height int
XOffset int
YOffset int
NumberOfOptionalBytes int
NumberOfCodedBytes int
HorizontalCellCount int
VerticalCellCount int
FrameIsBottomUp bool
valid bool
}
// CreateDCCDirectionFrame Creates a DCCDirectionFrame for a DCC.
func CreateDCCDirectionFrame(bits *d2datautils.BitMuncher, direction *DCCDirection) *DCCDirectionFrame {
result := &DCCDirectionFrame{}
bits.GetBits(direction.Variable0Bits) // Variable0
result.Width = int(bits.GetBits(direction.WidthBits))
result.Height = int(bits.GetBits(direction.HeightBits))
result.XOffset = bits.GetSignedBits(direction.XOffsetBits)
result.YOffset = bits.GetSignedBits(direction.YOffsetBits)
result.NumberOfOptionalBytes = int(bits.GetBits(direction.OptionalDataBits))
result.NumberOfCodedBytes = int(bits.GetBits(direction.CodedBytesBits))
result.FrameIsBottomUp = bits.GetBit() == 1
if result.FrameIsBottomUp {
log.Panic("Bottom up frames are not implemented.")
} else {
result.Box = d2geom.Rectangle{
Left: result.XOffset,
Top: result.YOffset - result.Height + 1,
Width: result.Width,
Height: result.Height,
}
}
result.valid = true
return result
}
func (v *DCCDirectionFrame) recalculateCells(direction *DCCDirection) {
var w = 4 - ((v.Box.Left - direction.Box.Left) % 4) // Width of the first column (in pixels)
if (v.Width - w) <= 1 {
v.HorizontalCellCount = 1
} else {
tmp := v.Width - w - 1
v.HorizontalCellCount = 2 + (tmp / 4) //nolint:gomnd magic math
if (tmp % 4) == 0 {
v.HorizontalCellCount--
}
}
// Height of the first column (in pixels)
h := 4 - ((v.Box.Top - direction.Box.Top) % 4) //nolint:gomnd data decode
if (v.Height - h) <= 1 {
v.VerticalCellCount = 1
} else {
tmp := v.Height - h - 1
v.VerticalCellCount = 2 + (tmp / 4) //nolint:gomnd data decode
if (tmp % 4) == 0 {
v.VerticalCellCount--
}
}
// Calculate the cell widths and heights
cellWidths := make([]int, v.HorizontalCellCount)
if v.HorizontalCellCount == 1 {
cellWidths[0] = v.Width
} else {
cellWidths[0] = w
for i := 1; i < (v.HorizontalCellCount - 1); i++ {
cellWidths[i] = 4
}
cellWidths[v.HorizontalCellCount-1] = v.Width - w - (4 * (v.HorizontalCellCount - 2))
}
cellHeights := make([]int, v.VerticalCellCount)
if v.VerticalCellCount == 1 {
cellHeights[0] = v.Height
} else {
cellHeights[0] = h
for i := 1; i < (v.VerticalCellCount - 1); i++ {
cellHeights[i] = 4
}
cellHeights[v.VerticalCellCount-1] = v.Height - h - (4 * (v.VerticalCellCount - 2))
}
v.Cells = make([]DCCCell, v.HorizontalCellCount*v.VerticalCellCount)
offsetY := v.Box.Top - direction.Box.Top
for y := 0; y < v.VerticalCellCount; y++ {
offsetX := v.Box.Left - direction.Box.Left
for x := 0; x < v.HorizontalCellCount; x++ {
v.Cells[x+(y*v.HorizontalCellCount)] = DCCCell{
XOffset: offsetX,
YOffset: offsetY,
Width: cellWidths[x],
Height: cellHeights[y],
}
offsetX += cellWidths[x]
}
offsetY += cellHeights[y]
}
}