mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-17 14:04:05 +09:00
tileatlas: atlas size will automatically expand if it's too small
This commit is contained in:
@@ -699,7 +699,7 @@ open class ActorWithBody : Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun displaceHitbox() {
|
private fun displaceHitbox() {
|
||||||
val printdbg1 = true && App.IS_DEVELOPMENT_BUILD
|
val printdbg1 = false && App.IS_DEVELOPMENT_BUILD
|
||||||
// // HOW IT SHOULD WORK // //
|
// // HOW IT SHOULD WORK // //
|
||||||
// ////////////////////////
|
// ////////////////////////
|
||||||
// combineVeloToMoveDelta now
|
// combineVeloToMoveDelta now
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ internal object BlocksDrawer {
|
|||||||
val tileNumber = if (thisTile == Block.AIR) 0
|
val tileNumber = if (thisTile == Block.AIR) 0
|
||||||
// special case: actorblocks and F3 key
|
// special case: actorblocks and F3 key
|
||||||
else if (BlockCodex.hasProp(thisTile) && BlockCodex[thisTile].isActorBlock &&
|
else if (BlockCodex.hasProp(thisTile) && BlockCodex[thisTile].isActorBlock &&
|
||||||
!BlockCodex[thisTile].tags.contains("DORENDER") && !KeyToggler.isOn(Keys.F3))
|
!BlockCodex[thisTile].hasTag("DORENDER") && !KeyToggler.isOn(Keys.F3))
|
||||||
0
|
0
|
||||||
// special case: fluids
|
// special case: fluids
|
||||||
else if (mode == FLUID)
|
else if (mode == FLUID)
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.Pixmap
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
|
import net.torvald.gdx.graphics.PixmapIO2
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarum.App.printdbg
|
import net.torvald.terrarum.App.printdbg
|
||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
@@ -15,6 +17,7 @@ import net.torvald.terrarum.gameitems.ItemID
|
|||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.AtlasSource.*
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.AtlasSource.*
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements work_files/dynamic_shape_2_0.psd
|
* This class implements work_files/dynamic_shape_2_0.psd
|
||||||
@@ -28,13 +31,12 @@ import kotlin.math.roundToInt
|
|||||||
*/
|
*/
|
||||||
class CreateTileAtlas {
|
class CreateTileAtlas {
|
||||||
|
|
||||||
// min size 1024 = tile_size 16 * atlasCursor 64
|
var MAX_TEX_SIZE = App.getConfigInt("atlastexsize").coerceIn(1024, App.glInfo.GL_MAX_TEXTURE_SIZE); private set
|
||||||
val MAX_TEX_SIZE = App.getConfigInt("atlastexsize").coerceIn(1024, App.glInfo.GL_MAX_TEXTURE_SIZE)
|
var TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE; private set
|
||||||
val TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE
|
|
||||||
|
|
||||||
val SHADER_SIZE_KEYS = floatArrayOf(MAX_TEX_SIZE.toFloat(), MAX_TEX_SIZE.toFloat(), TILES_IN_X.toFloat(), TILES_IN_X.toFloat())
|
var SHADER_SIZE_KEYS = floatArrayOf(MAX_TEX_SIZE.toFloat(), MAX_TEX_SIZE.toFloat(), TILES_IN_X.toFloat(), TILES_IN_X.toFloat()); private set
|
||||||
|
|
||||||
private val TOTAL_TILES = TILES_IN_X * TILES_IN_X
|
private var TOTAL_TILES = TILES_IN_X * TILES_IN_X
|
||||||
|
|
||||||
val wallOverlayColour = Color(.65f, .65f, .65f, 1f)
|
val wallOverlayColour = Color(.65f, .65f, .65f, 1f)
|
||||||
|
|
||||||
@@ -66,12 +68,54 @@ class CreateTileAtlas {
|
|||||||
private val atlasInit = "./assets/graphics/blocks/init.tga"
|
private val atlasInit = "./assets/graphics/blocks/init.tga"
|
||||||
private var itemSheetCursor = 16
|
private var itemSheetCursor = 16
|
||||||
|
|
||||||
internal val itemTerrainPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
internal lateinit var itemTerrainPixmap: Pixmap
|
||||||
internal val itemTerrainPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
internal lateinit var itemTerrainPixmapGlow: Pixmap
|
||||||
internal val itemWallPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
internal lateinit var itemWallPixmap: Pixmap
|
||||||
internal val itemWallPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
internal lateinit var itemWallPixmapGlow: Pixmap
|
||||||
|
|
||||||
|
|
||||||
|
private fun drawInitPixmap() {
|
||||||
|
val initPixmap = Pixmap(Gdx.files.internal(atlasInit))
|
||||||
|
|
||||||
|
val tilesInInitPixmap = (initPixmap.width * initPixmap.height) / (TILE_SIZE * TILE_SIZE)
|
||||||
|
val tilesPossibleInCurrentPixmap = (atlas.width * atlas.height) / (TILE_SIZE * TILE_SIZE)
|
||||||
|
|
||||||
|
if (tilesInInitPixmap > tilesPossibleInCurrentPixmap) throw Error("Atlas size too small -- can't even fit the init.tga (MAX_TEX_SIZE must be at least ${FastMath.nextPowerOfTwo((sqrt(tilesInInitPixmap.toFloat()) * TILE_SIZE).ceilToInt())})")
|
||||||
|
|
||||||
|
if (MAX_TEX_SIZE >= initPixmap.width) {
|
||||||
|
atlas.drawPixmap(initPixmap, 0, 0)
|
||||||
|
atlasAutumn.drawPixmap(initPixmap, 0, 0)
|
||||||
|
atlasWinter.drawPixmap(initPixmap, 0, 0)
|
||||||
|
atlasSpring.drawPixmap(initPixmap, 0, 0)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
What's happening:
|
||||||
|
|
||||||
|
src: dest:
|
||||||
|
AAAABBBBCCCCDDDD AAAA
|
||||||
|
BBBB
|
||||||
|
CCCC
|
||||||
|
DDDD
|
||||||
|
*/
|
||||||
|
val destX = 0
|
||||||
|
val srcY = 0
|
||||||
|
val scanW = MAX_TEX_SIZE
|
||||||
|
val scanH = TILE_SIZE
|
||||||
|
for (scantile in 0 until (initPixmap.width.toFloat() / MAX_TEX_SIZE).ceilToInt()) {
|
||||||
|
val srcX = scantile * scanW
|
||||||
|
val destY = scantile * TILE_SIZE
|
||||||
|
|
||||||
|
atlas.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||||
|
atlasAutumn.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||||
|
atlasWinter.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||||
|
atlasSpring.drawPixmap(initPixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initPixmap.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Must be called AFTER mods' loading so that all the block props are loaded
|
* Must be called AFTER mods' loading so that all the block props are loaded
|
||||||
*/
|
*/
|
||||||
@@ -80,27 +124,17 @@ class CreateTileAtlas {
|
|||||||
tags = HashMap<ItemID, RenderTag>()
|
tags = HashMap<ItemID, RenderTag>()
|
||||||
itemSheetNumbers = HashMap<ItemID, Int>()
|
itemSheetNumbers = HashMap<ItemID, Int>()
|
||||||
|
|
||||||
atlas = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
atlas = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||||
atlasAutumn = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
atlasAutumn = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||||
atlasWinter = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
atlasWinter = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||||
atlasSpring = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
atlasSpring = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||||
atlasFluid = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
atlasFluid = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||||
atlasGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
atlasGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
|
||||||
|
|
||||||
atlas.blending = Pixmap.Blending.None
|
|
||||||
atlasAutumn.blending = Pixmap.Blending.None
|
|
||||||
atlasWinter.blending = Pixmap.Blending.None
|
|
||||||
atlasSpring.blending = Pixmap.Blending.None
|
|
||||||
atlasFluid.blending = Pixmap.Blending.None
|
|
||||||
atlasGlow.blending = Pixmap.Blending.None
|
|
||||||
|
|
||||||
// populate the atlantes with atlasInit
|
// populate the atlantes with atlasInit
|
||||||
// this just directly copies the image to the atlantes :p
|
// this just directly copies the image to the atlantes :p
|
||||||
val initPixmap = Pixmap(Gdx.files.internal(atlasInit))
|
drawInitPixmap()
|
||||||
atlas.drawPixmap(initPixmap, 0, 0)
|
|
||||||
atlasAutumn.drawPixmap(initPixmap, 0, 0)
|
|
||||||
atlasWinter.drawPixmap(initPixmap, 0, 0)
|
|
||||||
atlasSpring.drawPixmap(initPixmap, 0, 0)
|
|
||||||
|
|
||||||
// get all the files applicable
|
// get all the files applicable
|
||||||
// first, get all the '/blocks' directory, and add all the files, regardless of their extension, to the list
|
// first, get all the '/blocks' directory, and add all the files, regardless of their extension, to the list
|
||||||
@@ -135,8 +169,8 @@ class CreateTileAtlas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// test print
|
// test print
|
||||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlas.tga"), atlas, false)
|
// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false)
|
||||||
//PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false)
|
// PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -161,6 +195,11 @@ class CreateTileAtlas {
|
|||||||
// val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
// val itemTerrainPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||||
// val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
// val itemWallPixmap = Pixmap(16 * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||||
|
|
||||||
|
itemTerrainPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||||
|
itemTerrainPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||||
|
itemWallPixmap = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||||
|
itemWallPixmapGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
|
||||||
|
|
||||||
tags.toMap().forEach { id, tag ->
|
tags.toMap().forEach { id, tag ->
|
||||||
val tilePosFromAtlas = tag.tileNumber + maskTypetoTileIDForItemImage(tag.maskType)
|
val tilePosFromAtlas = tag.tileNumber + maskTypetoTileIDForItemImage(tag.maskType)
|
||||||
val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE
|
val srcX = (tilePosFromAtlas % TILES_IN_X) * TILE_SIZE
|
||||||
@@ -217,7 +256,6 @@ class CreateTileAtlas {
|
|||||||
itemWallTextureGlow = Texture(itemWallPixmapGlow)
|
itemWallTextureGlow = Texture(itemWallPixmapGlow)
|
||||||
// itemTerrainPixmap.dispose()
|
// itemTerrainPixmap.dispose()
|
||||||
// itemWallPixmap.dispose()
|
// itemWallPixmap.dispose()
|
||||||
initPixmap.dispose()
|
|
||||||
|
|
||||||
initialised = true
|
initialised = true
|
||||||
} }
|
} }
|
||||||
@@ -242,6 +280,7 @@ class CreateTileAtlas {
|
|||||||
val blockName = matte.nameWithoutExtension().split('-').last().toInt() // basically a filename
|
val blockName = matte.nameWithoutExtension().split('-').last().toInt() // basically a filename
|
||||||
val blockID = "$modname:$blockName"
|
val blockID = "$modname:$blockName"
|
||||||
|
|
||||||
|
|
||||||
// determine the type of the block (populate tags list)
|
// determine the type of the block (populate tags list)
|
||||||
// predefined by the image dimension: 16x16 for (1,0)
|
// predefined by the image dimension: 16x16 for (1,0)
|
||||||
if (tilesPixmap.width == TILE_SIZE && tilesPixmap.height == TILE_SIZE) {
|
if (tilesPixmap.width == TILE_SIZE && tilesPixmap.height == TILE_SIZE) {
|
||||||
@@ -307,8 +346,10 @@ class CreateTileAtlas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun drawToAtlantes(matte: Pixmap, glow: Pixmap, tilesCount: Int) {
|
private fun drawToAtlantes(matte: Pixmap, glow: Pixmap, tilesCount: Int) {
|
||||||
if (atlasCursor >= TOTAL_TILES) {
|
if (atlasCursor + tilesCount >= TOTAL_TILES) {
|
||||||
throw Error("Too much tiles for $MAX_TEX_SIZE texture size: $atlasCursor")
|
// throw Error("Too much tiles for $MAX_TEX_SIZE texture size: $atlasCursor")
|
||||||
|
println("[CreateTileAtlas] Too much tiles for atlas of ${MAX_TEX_SIZE}x$MAX_TEX_SIZE (tiles so far: $atlasCursor/${(MAX_TEX_SIZE*MAX_TEX_SIZE)/(TILE_SIZE* TILE_SIZE)}, tiles to be added: $tilesCount), trying to expand the atlas...")
|
||||||
|
expandAtlantes()
|
||||||
}
|
}
|
||||||
|
|
||||||
val seasonal = matte.width == matte.height && matte.width == 14 * TILE_SIZE
|
val seasonal = matte.width == matte.height && matte.width == 14 * TILE_SIZE
|
||||||
@@ -413,4 +454,60 @@ class CreateTileAtlas {
|
|||||||
private enum class AtlasSource {
|
private enum class AtlasSource {
|
||||||
FOUR_SEASONS, SUMMER, AUTUMN, WINTER, SPRING, FLUID, GLOW
|
FOUR_SEASONS, SUMMER, AUTUMN, WINTER, SPRING, FLUID, GLOW
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun expandAtlantes() {
|
||||||
|
if (MAX_TEX_SIZE >= App.glInfo.GL_MAX_TEXTURE_SIZE) {
|
||||||
|
throw RuntimeException("Cannot expand atlas: texture size is already at its maximum possible size allowed by the graphics processor (${MAX_TEX_SIZE}x${MAX_TEX_SIZE})")
|
||||||
|
}
|
||||||
|
|
||||||
|
val oldTexSize = MAX_TEX_SIZE
|
||||||
|
val newTexSize = oldTexSize * 2
|
||||||
|
|
||||||
|
|
||||||
|
MAX_TEX_SIZE = newTexSize
|
||||||
|
TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE
|
||||||
|
SHADER_SIZE_KEYS = floatArrayOf(MAX_TEX_SIZE.toFloat(), MAX_TEX_SIZE.toFloat(), TILES_IN_X.toFloat(), TILES_IN_X.toFloat())
|
||||||
|
TOTAL_TILES = TILES_IN_X * TILES_IN_X
|
||||||
|
|
||||||
|
|
||||||
|
val newAtlantes = Array<Pixmap>(5) {
|
||||||
|
Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also {
|
||||||
|
it.blending = Pixmap.Blending.None
|
||||||
|
it.filter = Pixmap.Filter.NearestNeighbour
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listOf(atlas, atlasAutumn, atlasWinter, atlasSpring, atlasGlow).forEachIndexed { index, pixmap ->
|
||||||
|
/*
|
||||||
|
How it works:
|
||||||
|
|
||||||
|
old: new:
|
||||||
|
AAAAAAAA AAAAAAAABBBBBBBB
|
||||||
|
BBBBBBBB CCCCCCCCDDDDDDDD
|
||||||
|
CCCCCCCC ...
|
||||||
|
DDDDDDDD
|
||||||
|
...
|
||||||
|
|
||||||
|
*/
|
||||||
|
for (scantile in 0 until pixmap.height / TILE_SIZE) {
|
||||||
|
val srcX = 0
|
||||||
|
val srcY = scantile * TILE_SIZE
|
||||||
|
val destX = (scantile % 2) * oldTexSize
|
||||||
|
val destY = (scantile / 2) * TILE_SIZE
|
||||||
|
val scanW = pixmap.width
|
||||||
|
val scanH = TILE_SIZE
|
||||||
|
|
||||||
|
newAtlantes[index].drawPixmap(pixmap, srcX, srcY, scanW, scanH, destX, destY, scanW, scanH)
|
||||||
|
}
|
||||||
|
pixmap.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
atlas = newAtlantes[0]
|
||||||
|
atlasAutumn = newAtlantes[1]
|
||||||
|
atlasWinter = newAtlantes[2]
|
||||||
|
atlasSpring = newAtlantes[3]
|
||||||
|
atlasGlow = newAtlantes[4]
|
||||||
|
|
||||||
|
|
||||||
|
App.setConfig("atlastexsize", newTexSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -33,12 +33,12 @@ object FeaturesDrawer {
|
|||||||
TileSurvey.submitProposal(
|
TileSurvey.submitProposal(
|
||||||
TileSurvey.SurveyProposal(
|
TileSurvey.SurveyProposal(
|
||||||
"basegame.FeaturesDrawer.coldTiles", 72, 48, 2, 2
|
"basegame.FeaturesDrawer.coldTiles", 72, 48, 2, 2
|
||||||
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].tags.contains("COLD") }
|
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].hasTag("COLD") }
|
||||||
)
|
)
|
||||||
TileSurvey.submitProposal(
|
TileSurvey.submitProposal(
|
||||||
TileSurvey.SurveyProposal(
|
TileSurvey.SurveyProposal(
|
||||||
"basegame.FeaturesDrawer.warmTiles", 72, 48, 2, 2
|
"basegame.FeaturesDrawer.warmTiles", 72, 48, 2, 2
|
||||||
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].tags.contains("WARM") }
|
) { world, x, y -> BlockCodex[world.getTileFromTerrain(x, y)].hasTag("WARM") }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user