1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-06-15 20:15:24 +00:00
OpenDiablo2/d2core/d2map/d2maprenderer/tile_cache.go

204 lines
5.5 KiB
Go
Raw Normal View History

2020-06-21 22:40:37 +00:00
package d2maprenderer
import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
2020-06-21 22:40:37 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2ds1"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
2020-09-12 20:25:09 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
2020-06-21 22:40:37 +00:00
)
func (mr *MapRenderer) generateTileCache() {
remove d2asset singleton (#726) * export d2asset singleton * add *d2asset.AssetManager to d2app - d2app now has a reference to an asset manager which it will use for loading - added asset loader methods to the asset manager - functions in d2asset are now wrappers for asset manager methods * add asset manager reference to audio provider - d2app asset manager reference is now passed to audio provider - asset manager is created in main.go for now to pass into audio provider - CreateSoundEffect is now a method, no longer exported, uses the asset manager reference * d2app passes asset manager refence to map engine test * in d2asset, all calls to LoadFile replaced with call to Singleton.Loadfile * blizzard intro and credits screen - d2app passes reference to the asset manager to these screens * asset manager for d2map - adding MapStampFactory, takes an asset manager reference - embedded MapStampFactory into the MapEngine - LoadStamp is now a method of the MapStampFactory * d2asset: removed LoadFileStream, LoadFile, and FileExists * d2gui changes - singleton now has an asset manager reference - calls to d2asset loader functions removed - createButton is now a method of LayoutManager - moved LayoutEntry to its own file * map entity factory - Map engine has an embedded map entity factory - Map stamp factory gets a reference to the map engine's entity factory - Stamps are given a reference to the map engine entity factory when created - Character select gets a map entity factory - Embedded the stamp factory into the MapEngine * asset manager for d2ui - d2ui is passed an asset manager reference when created - all calls to d2asset loader functions in d2ui now refer to the asset manager - d2gamescreen gets a ui manager when created - help overlay is now passed a ui manager when created * d2gamescreen + d2player: asset manager references added an asset manager reference to - inventory panel + inventory grid - mini panel - game controls - help overlay - character select - main menu - select hero class - hero stats panel * Removed d2asset.LoadAnimation all references to this function have been replaced with calls to the asset manager method * adding asset to help overlay, bugfix for 4d59c91 * Removed d2asset.LoadFont and d2asset.LoadAnimationWithEffect all references to these have been replaced with calls to the asset manager methods * MapRenderer now gets an asset manager reference * removed d2asset.LoadPalette all references have been replaced with calls to an asset manager instance * merged d2object with d2mapentity d2object was only being used to create objects in the map, so the provider function is now a method of the map entity factory. calls to d2asset have been removed. * removed d2asset.LoadComposite all calls are now made to the asset manager method * removed d2asset singleton all singleton references have been removed, a single instance of the asset manager is passed around the entire app * rename Initialize to NewAssetManager
2020-09-12 20:51:30 +00:00
mr.palette, _ = mr.loadPaletteForAct(d2enum.RegionIdType(mr.mapEngine.LevelType().ID))
2020-06-21 22:40:37 +00:00
2020-07-23 16:56:50 +00:00
tiles := *mr.mapEngine.Tiles()
for idx := range tiles {
tile := &tiles[idx]
for i := range tile.Components.Floors {
if !tile.Components.Floors[i].Hidden && tile.Components.Floors[i].Prop1 != 0 {
2020-07-23 16:56:50 +00:00
mr.generateFloorCache(&tile.Components.Floors[i])
2020-06-21 22:40:37 +00:00
}
}
for i := range tile.Components.Shadows {
if !tile.Components.Shadows[i].Hidden && tile.Components.Shadows[i].Prop1 != 0 {
2020-07-23 16:56:50 +00:00
mr.generateShadowCache(&tile.Components.Shadows[i])
2020-06-21 22:40:37 +00:00
}
}
for i := range tile.Components.Walls {
if !tile.Components.Walls[i].Hidden && tile.Components.Walls[i].Prop1 != 0 {
2020-07-23 16:56:50 +00:00
mr.generateWallCache(&tile.Components.Walls[i])
2020-06-21 22:40:37 +00:00
}
}
}
}
2020-07-23 16:56:50 +00:00
func (mr *MapRenderer) generateFloorCache(tile *d2ds1.FloorShadowRecord) {
tileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), 0)
2020-06-21 22:40:37 +00:00
var tileData []*d2dt1.Tile
2020-06-21 22:40:37 +00:00
if tileOptions == nil {
log.Printf("Could not locate tile Style:%d, Seq: %d, Type: %d\n", tile.Style, tile.Sequence, 0)
2020-06-21 22:40:37 +00:00
tileData = append(tileData, &d2dt1.Tile{})
tileData[0].Width = 10
tileData[0].Height = 10
} else {
if !tileOptions[0].MaterialFlags.Lava {
tileData = append(tileData, &tileOptions[tile.RandomIndex])
2020-06-21 22:40:37 +00:00
} else {
tile.Animated = true
for i := range tileOptions {
tileData = append(tileData, &tileOptions[i])
}
}
}
var tileIndex byte
2020-06-21 22:40:37 +00:00
for i := range tileData {
if tileData[i].MaterialFlags.Lava {
2020-06-21 22:40:37 +00:00
tileIndex = byte(tileData[i].RarityFrameIndex)
} else {
tileIndex = tile.RandomIndex
2020-06-21 22:40:37 +00:00
}
2020-06-21 22:40:37 +00:00
cachedImage := mr.getImageCacheRecord(tile.Style, tile.Sequence, 0, tileIndex)
2020-06-21 22:40:37 +00:00
if cachedImage != nil {
return
}
2020-06-21 22:40:37 +00:00
tileYMinimum := int32(0)
2020-06-21 22:40:37 +00:00
for _, block := range tileData[i].Blocks {
tileYMinimum = d2math.MinInt32(tileYMinimum, int32(block.Y))
2020-06-21 22:40:37 +00:00
}
tileYOffset := d2math.AbsInt32(tileYMinimum)
tileHeight := d2math.AbsInt32(tileData[i].Height)
image, _ := mr.renderer.NewSurface(int(tileData[i].Width), int(tileHeight), d2enum.FilterNearest)
indexData := make([]byte, tileData[i].Width*tileHeight)
d2dt1.DecodeTileGfxData(tileData[i].Blocks, &indexData, tileYOffset, tileData[i].Width)
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
_ = image.ReplacePixels(pixels)
2020-06-21 22:40:37 +00:00
mr.setImageCacheRecord(tile.Style, tile.Sequence, 0, tileIndex, image)
}
}
2020-07-23 16:56:50 +00:00
func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord) {
tileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), 13)
2020-06-21 22:40:37 +00:00
var tileData *d2dt1.Tile
2020-06-21 22:40:37 +00:00
if tileOptions == nil {
return
}
2020-07-23 16:56:50 +00:00
tileData = &tileOptions[tile.RandomIndex]
2020-06-21 22:40:37 +00:00
if tileData.Width == 0 || tileData.Height == 0 {
return
}
tileMinY := int32(0)
tileMaxY := int32(0)
2020-06-21 22:40:37 +00:00
for _, block := range tileData.Blocks {
tileMinY = d2math.MinInt32(tileMinY, int32(block.Y))
tileMaxY = d2math.MaxInt32(tileMaxY, int32(block.Y+32))
2020-06-21 22:40:37 +00:00
}
2020-06-21 22:40:37 +00:00
tileYOffset := -tileMinY
tileHeight := int(tileMaxY - tileMinY)
tile.YAdjust = int(tileMinY + 80)
cachedImage := mr.getImageCacheRecord(tile.Style, tile.Sequence, 13, tile.RandomIndex)
2020-06-21 22:40:37 +00:00
if cachedImage != nil {
return
}
image, _ := mr.renderer.NewSurface(int(tileData.Width), tileHeight, d2enum.FilterNearest)
indexData := make([]byte, tileData.Width*int32(tileHeight))
d2dt1.DecodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, tileData.Width)
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
_ = image.ReplacePixels(pixels)
mr.setImageCacheRecord(tile.Style, tile.Sequence, 13, tile.RandomIndex, image)
2020-06-21 22:40:37 +00:00
}
2020-07-23 16:56:50 +00:00
func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord) {
tileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), int(tile.Type))
2020-06-21 22:40:37 +00:00
var tileData *d2dt1.Tile
2020-06-21 22:40:37 +00:00
if tileOptions == nil {
return
}
tileData = &tileOptions[tile.RandomIndex]
2020-06-21 22:40:37 +00:00
var newTileData *d2dt1.Tile = nil
if tile.Type == 3 {
newTileOptions := mr.mapEngine.GetTiles(int(tile.Style), int(tile.Sequence), int(4))
newTileData = &newTileOptions[tile.RandomIndex]
2020-06-21 22:40:37 +00:00
}
tileMinY := int32(0)
tileMaxY := int32(0)
target := tileData
if newTileData != nil && newTileData.Height < tileData.Height {
target = newTileData
}
for _, block := range target.Blocks {
tileMinY = d2math.MinInt32(tileMinY, int32(block.Y))
tileMaxY = d2math.MaxInt32(tileMaxY, int32(block.Y+32))
2020-06-21 22:40:37 +00:00
}
realHeight := d2math.MaxInt32(d2math.AbsInt32(tileData.Height), tileMaxY-tileMinY)
2020-06-21 22:40:37 +00:00
tileYOffset := -tileMinY
if tile.Type == 15 {
tile.YAdjust = -int(tileData.RoofHeight)
} else {
tile.YAdjust = int(tileMinY) + 80
}
cachedImage := mr.getImageCacheRecord(tile.Style, tile.Sequence, tile.Type, tile.RandomIndex)
2020-06-21 22:40:37 +00:00
if cachedImage != nil {
return
}
if realHeight == 0 {
log.Printf("Invalid 0 height for wall tile")
return
}
image, _ := mr.renderer.NewSurface(160, int(realHeight), d2enum.FilterNearest)
indexData := make([]byte, 160*realHeight)
d2dt1.DecodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, 160)
2020-06-21 22:40:37 +00:00
if newTileData != nil {
d2dt1.DecodeTileGfxData(newTileData.Blocks, &indexData, tileYOffset, 160)
2020-06-21 22:40:37 +00:00
}
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
2020-06-21 22:40:37 +00:00
if err := image.ReplacePixels(pixels); err != nil {
log.Panicf(err.Error())
}
mr.setImageCacheRecord(tile.Style, tile.Sequence, tile.Type, tile.RandomIndex, image)
2020-06-21 22:40:37 +00:00
}