mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-18 02:16:23 -05:00
Standardize indexed color to RGBA conversion to one function (#562)
* Common function for indexed color to rgba * Use ImgIndexToRGBA when decoding tiles * Pass DrawEffect down to animation
This commit is contained in:
parent
f18ede6e66
commit
1ad3c72211
@ -8,7 +8,7 @@ const (
|
||||
|
||||
// DrawEffectPctTransparency25 is a draw effect that implements the following function:
|
||||
// GL_MODULATE; GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA 25 % transparency (colormaps 49-304 in a .pl2)
|
||||
DrawEffectPctTransparency25 = iota
|
||||
DrawEffectPctTransparency25 DrawEffect = iota
|
||||
|
||||
// DrawEffectPctTransparency50 is a draw effect that implements the following function:
|
||||
// GL_MODULATE; GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA 50 % transparency (colormaps 305-560 in a .pl2)
|
||||
@ -37,4 +37,7 @@ const (
|
||||
// DrawEffectMod2X is a draw effect that implements the following function:
|
||||
// GL_COMBINE_ARB; GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA (colormaps 1457-1712 in a .pl2)
|
||||
DrawEffectMod2X
|
||||
|
||||
// no effect
|
||||
DrawEffectNone
|
||||
)
|
||||
|
@ -1,6 +1,8 @@
|
||||
package d2interface
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
type ArchivedAnimationManager interface {
|
||||
Cacher
|
||||
LoadAnimation(animationPath, palettePath string, transparency int) (Animation, error)
|
||||
LoadAnimation(animationPath, palettePath string, drawEffect d2enum.DrawEffect) (Animation, error)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
@ -36,8 +37,8 @@ func createAnimationManager(renderer d2interface.Renderer) *animationManager {
|
||||
|
||||
func (am *animationManager) LoadAnimation(
|
||||
animationPath, palettePath string,
|
||||
transparency int ) (d2interface.Animation, error) {
|
||||
cachePath := fmt.Sprintf("%s;%s;%d", animationPath, palettePath, transparency)
|
||||
effect d2enum.DrawEffect ) (d2interface.Animation, error) {
|
||||
cachePath := fmt.Sprintf("%s;%s;%d", animationPath, palettePath, effect)
|
||||
if animation, found := am.cache.Retrieve(cachePath); found {
|
||||
return animation.(d2interface.Animation).Clone(), nil
|
||||
}
|
||||
@ -62,7 +63,7 @@ func (am *animationManager) LoadAnimation(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
animation, err = CreateDCCAnimation(am.renderer, animationPath, palette, transparency)
|
||||
animation, err = CreateDCCAnimation(am.renderer, animationPath, palette, effect)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package d2asset
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
|
||||
@ -237,30 +236,17 @@ func (c *Composite) createMode(animationMode, weaponClass string) (*compositeMod
|
||||
layerValue = "lit"
|
||||
}
|
||||
|
||||
blend := false
|
||||
transparency := 255
|
||||
drawEffect := d2enum.DrawEffectNone
|
||||
|
||||
if cofLayer.Transparent {
|
||||
switch cofLayer.DrawEffect {
|
||||
case d2enum.DrawEffectPctTransparency25:
|
||||
transparency = 64
|
||||
case d2enum.DrawEffectPctTransparency50:
|
||||
transparency = 128
|
||||
case d2enum.DrawEffectPctTransparency75:
|
||||
transparency = 192
|
||||
case d2enum.DrawEffectModulate:
|
||||
blend = true
|
||||
default:
|
||||
log.Println("Unhandled DrawEffect ", cofLayer.DrawEffect, " requested for layer ", cofLayer.Type.String(), " of ", c.token)
|
||||
}
|
||||
drawEffect = cofLayer.DrawEffect
|
||||
}
|
||||
|
||||
layer, err := c.loadCompositeLayer(cofLayer.Type.String(), layerValue, animationMode,
|
||||
cofLayer.WeaponClass.String(), c.palettePath, transparency)
|
||||
cofLayer.WeaponClass.String(), c.palettePath, drawEffect)
|
||||
if err == nil {
|
||||
layer.SetPlaySpeed(mode.animationSpeed)
|
||||
layer.PlayForward()
|
||||
layer.SetBlend(blend)
|
||||
|
||||
if err := layer.SetDirection(c.direction); err != nil {
|
||||
return nil, err
|
||||
@ -274,7 +260,7 @@ func (c *Composite) createMode(animationMode, weaponClass string) (*compositeMod
|
||||
}
|
||||
|
||||
func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weaponClass,
|
||||
palettePath string, transparency int) (d2interface.Animation, error) {
|
||||
palettePath string, drawEffect d2enum.DrawEffect) (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),
|
||||
@ -282,7 +268,7 @@ func (c *Composite) loadCompositeLayer(layerKey, layerValue, animationMode, weap
|
||||
|
||||
for _, animationPath := range animationPaths {
|
||||
if exists, _ := FileExists(animationPath); exists {
|
||||
animation, err := LoadAnimationWithTransparency(animationPath, palettePath, transparency)
|
||||
animation, err := LoadAnimationWithEffect(animationPath, palettePath, drawEffect)
|
||||
if err == nil {
|
||||
return animation, nil
|
||||
}
|
||||
|
@ -104,13 +104,13 @@ func FileExists(filePath string) (bool, error) {
|
||||
|
||||
// LoadAnimation loads an animation by its resource path and its palette path
|
||||
func LoadAnimation(animationPath, palettePath string) (d2interface.Animation, error) {
|
||||
return LoadAnimationWithTransparency(animationPath, palettePath, 255)
|
||||
return LoadAnimationWithEffect(animationPath, palettePath, d2enum.DrawEffectNone)
|
||||
}
|
||||
|
||||
// LoadAnimationWithTransparency loads an animation by its resource path and its palette path with a given transparency value
|
||||
func LoadAnimationWithTransparency(animationPath, palettePath string,
|
||||
transparency int) (d2interface.Animation, error) {
|
||||
return singleton.animationManager.LoadAnimation(animationPath, palettePath, transparency)
|
||||
// LoadAnimationWithEffect loads an animation by its resource path and its palette path with a given transparency value
|
||||
func LoadAnimationWithEffect(animationPath, palettePath string,
|
||||
drawEffect d2enum.DrawEffect) (d2interface.Animation, error) {
|
||||
return singleton.animationManager.LoadAnimation(animationPath, palettePath, drawEffect)
|
||||
}
|
||||
|
||||
// LoadComposite creates a composite object from a ObjectLookupRecord and palettePath describing it
|
||||
|
@ -82,22 +82,7 @@ func (a *DC6Animation) decodeDirection(directionIndex int) error {
|
||||
}
|
||||
|
||||
indexData := dc6.DecodeFrame(startFrame + i)
|
||||
|
||||
bytesPerPixel := 4
|
||||
colorData := make([]byte, int(dc6Frame.Width)*int(dc6Frame.Height)*bytesPerPixel)
|
||||
|
||||
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
|
||||
// Index zero is hardcoded transparent regardless of palette
|
||||
if indexData[i] == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
c := a.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()
|
||||
}
|
||||
colorData := ImgIndexToRGBA(indexData, a.palette)
|
||||
|
||||
if err := sfc.ReplacePixels(colorData); err != nil {
|
||||
return err
|
||||
|
@ -2,9 +2,10 @@ package d2asset
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"math"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
|
||||
d2iface "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
@ -14,15 +15,14 @@ import (
|
||||
type DCCAnimation struct {
|
||||
animation
|
||||
dccPath string
|
||||
transparency int
|
||||
effect d2enum.DrawEffect
|
||||
palette d2iface.Palette
|
||||
renderer d2iface.Renderer
|
||||
}
|
||||
|
||||
// CreateAnimationFromDCC creates an animation from d2dcc.DCC and d2dat.DATPalette
|
||||
func CreateDCCAnimation(renderer d2iface.Renderer, dccPath string, palette d2iface.Palette,
|
||||
transparency int) (d2iface.Animation, error) {
|
||||
|
||||
effect d2enum.DrawEffect) (d2iface.Animation, error) {
|
||||
dcc, err := loadDCC(dccPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -39,9 +39,17 @@ func CreateDCCAnimation(renderer d2iface.Renderer, dccPath string, palette d2ifa
|
||||
dccPath: dccPath,
|
||||
palette: palette,
|
||||
renderer: renderer,
|
||||
transparency: transparency,
|
||||
effect: effect,
|
||||
}
|
||||
|
||||
// Really the renderer should take DrawEffects and do the right thing
|
||||
if effect == d2enum.DrawEffectModulate {
|
||||
DCC.SetBlend(true)
|
||||
}
|
||||
|
||||
// Transparency is now no longer handled, it should be done by using PL2 palette and
|
||||
// picking the appropriate transform for the transparency level
|
||||
|
||||
err = DCC.SetDirection(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -99,25 +107,7 @@ func (a *DCCAnimation) decodeDirection(directionIndex int) error {
|
||||
frameWidth := maxX - minX
|
||||
frameHeight := maxY - minY
|
||||
|
||||
const bytesPerPixel = 4
|
||||
pixels := make([]byte, frameWidth*frameHeight*bytesPerPixel)
|
||||
|
||||
for y := 0; y < frameHeight; y++ {
|
||||
for x := 0; x < frameWidth; x++ {
|
||||
paletteIndex := dccFrame.PixelData[y*frameWidth+x]
|
||||
|
||||
if paletteIndex == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
palColor := a.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(a.transparency)
|
||||
}
|
||||
}
|
||||
pixels := ImgIndexToRGBA(dccFrame.PixelData, a.palette)
|
||||
|
||||
sfc, err := a.renderer.NewSurface(frameWidth, frameHeight, d2enum.FilterNearest)
|
||||
if err != nil {
|
||||
|
23
d2core/d2asset/palette.go
Normal file
23
d2core/d2asset/palette.go
Normal file
@ -0,0 +1,23 @@
|
||||
package d2asset
|
||||
|
||||
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||
|
||||
func ImgIndexToRGBA(indexData []byte, palette d2interface.Palette) []byte {
|
||||
bytesPerPixel := 4
|
||||
colorData := make([]byte, len(indexData)*bytesPerPixel)
|
||||
|
||||
for i := 0; i < len(indexData); i++ {
|
||||
// Index zero is hardcoded transparent regardless of palette
|
||||
if indexData[i] == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
return colorData
|
||||
}
|
@ -19,15 +19,8 @@ func (mr *MapRenderer) decodeTileGfxData(blocks []d2dt1.Block, pixels *[]byte, t
|
||||
n := nbpix[y]
|
||||
length -= n
|
||||
for n > 0 {
|
||||
colorIndex := block.EncodedData[idx]
|
||||
if colorIndex != 0 {
|
||||
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+3] = 255
|
||||
}
|
||||
offset := (((blockY + y + tileYOffset) * tileWidth) + (blockX + x))
|
||||
(*pixels)[offset] = block.EncodedData[idx]
|
||||
x++
|
||||
n--
|
||||
idx++
|
||||
@ -56,17 +49,8 @@ func (mr *MapRenderer) decodeTileGfxData(blocks []d2dt1.Block, pixels *[]byte, t
|
||||
x += int32(b1)
|
||||
length -= int32(b2)
|
||||
for b2 > 0 {
|
||||
colorIndex := block.EncodedData[idx]
|
||||
if colorIndex != 0 {
|
||||
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+3] = 255
|
||||
|
||||
}
|
||||
offset := (((blockY + y + tileYOffset) * tileWidth) + (blockX + x))
|
||||
(*pixels)[offset] = block.EncodedData[idx]
|
||||
idx++
|
||||
x++
|
||||
b2--
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
|
||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||
)
|
||||
|
||||
func (mr *MapRenderer) generateTileCache() {
|
||||
@ -73,8 +74,10 @@ func (mr *MapRenderer) generateFloorCache(tile *d2ds1.FloorShadowRecord, tileX,
|
||||
tileYOffset := d2common.AbsInt32(tileYMinimum)
|
||||
tileHeight := d2common.AbsInt32(tileData[i].Height)
|
||||
image, _ := mr.renderer.NewSurface(int(tileData[i].Width), int(tileHeight), d2enum.FilterNearest)
|
||||
pixels := make([]byte, 4*tileData[i].Width*tileHeight)
|
||||
mr.decodeTileGfxData(tileData[i].Blocks, &pixels, tileYOffset, tileData[i].Width)
|
||||
indexData := make([]byte, tileData[i].Width*tileHeight)
|
||||
mr.decodeTileGfxData(tileData[i].Blocks, &indexData, tileYOffset, tileData[i].Width)
|
||||
pixels := d2asset.ImgIndexToRGBA(indexData, mr.palette)
|
||||
|
||||
_ = image.ReplacePixels(pixels)
|
||||
mr.setImageCacheRecord(tile.Style, tile.Sequence, 0, tileIndex, image)
|
||||
}
|
||||
@ -112,8 +115,9 @@ func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord, tileX,
|
||||
}
|
||||
|
||||
image, _ := mr.renderer.NewSurface(int(tileData.Width), tileHeight, d2enum.FilterNearest)
|
||||
pixels := make([]byte, 4*tileData.Width*int32(tileHeight))
|
||||
mr.decodeTileGfxData(tileData.Blocks, &pixels, tileYOffset, tileData.Width)
|
||||
indexData := make([]byte, tileData.Width*int32(tileHeight))
|
||||
mr.decodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, tileData.Width)
|
||||
pixels := d2asset.ImgIndexToRGBA(indexData, mr.palette)
|
||||
_ = image.ReplacePixels(pixels)
|
||||
mr.setImageCacheRecord(tile.Style, tile.Sequence, 13, tileIndex, image)
|
||||
}
|
||||
@ -173,14 +177,16 @@ func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord, tileX, tileY in
|
||||
}
|
||||
|
||||
image, _ := mr.renderer.NewSurface(160, int(realHeight), d2enum.FilterNearest)
|
||||
pixels := make([]byte, 4*160*realHeight)
|
||||
indexData := make([]byte, 160*realHeight)
|
||||
|
||||
mr.decodeTileGfxData(tileData.Blocks, &pixels, tileYOffset, 160)
|
||||
mr.decodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, 160)
|
||||
|
||||
if newTileData != nil {
|
||||
mr.decodeTileGfxData(newTileData.Blocks, &pixels, tileYOffset, 160)
|
||||
mr.decodeTileGfxData(newTileData.Blocks, &indexData, tileYOffset, 160)
|
||||
}
|
||||
|
||||
pixels := d2asset.ImgIndexToRGBA(indexData, mr.palette)
|
||||
|
||||
if err := image.ReplacePixels(pixels); err != nil {
|
||||
log.Panicf(err.Error())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user