glow/emissive for held items, even if the actor has no glow/emissive sprites

This commit is contained in:
minjaesong
2024-01-27 03:21:26 +09:00
parent b02f4d7703
commit b1ca1a9351
26 changed files with 345 additions and 106 deletions

Binary file not shown.

View File

@@ -0,0 +1,48 @@
# complete file name is: SPRITESHEET + bodypart name + EXTENSION
SPRITESHEET=mods/basegame/sprites/test_werebeastf2/taimuemsv_
EXTENSION=.tga
# defines frame size and origin point. Origin point is given as: (originx, 0)
CONFIG=SIZE 64,98;ORIGINX 40
! A skeleton also defines what body parts (images) be used.
! You can also write multiline text using reverse solidus; this is a feature of .properties
! skeleton joints are ordered: foremost-drawn object comes first, which means lowermost object IN THIS LIST
! are painted first, and any object that comes before it will paint over it. In other words, this list is
! first reversed then being iterated.
! Some keywords are considered special within the game, they are:
! HEADGEAR, HELD_ITEM, BOOT_L, BOOT_R, GAUNTLET_L, GAUNTLET_R and ARMOUR_* (star means any number starting from zero)
BODYPARTS=HEADGEAR 13,14;\
HEAD 13,14;\
ARM_REST_RIGHT 10,4;\
ARM_REST_LEFT 9,3;\
LEG_REST_RIGHT 15,6;\
LEG_REST_LEFT 8,6;\
TORSO_0 18,19;\
TORSO_1 18,19;\
TAIL_0 30,2;\
BUST_0 11,2;\
HELD_ITEM 0,0
SKELETON_STAND=HEADGEAR 0,78;\
ARM_REST_RIGHT -16,66;\
HELD_ITEM -11,33;\
HEAD 0,78;\
BUST_0 0,63;\
LEG_REST_RIGHT -5,41;\
TORSO_0 0,54;\
TORSO_1 0,54;\
LEG_REST_LEFT 3,41;\
ARM_REST_LEFT 8,66;\
TAIL_0 2,40
! When you move the arms/hands, make sure you move the HELD_ITEM as well
# RUNNING might need its own skeleton...
ANIM_RUN=DELAY 0.18;ROW 2;SKELETON SKELETON_STAND
ANIM_RUN_1=LEG_REST_RIGHT 2,2;LEG_REST_LEFT -2,0;TAIL_0 1,0;TORSO_1 0,-999
ANIM_RUN_2=ALL 0,2;LEG_REST_RIGHT 0,-2;LEG_REST_LEFT 0,2;TAIL_0 -1,0;TORSO_1 0,-999
ANIM_RUN_3=LEG_REST_RIGHT -2,0;LEG_REST_LEFT 2,2;TAIL_0 -1,0;TORSO_1 0,-999
ANIM_RUN_4=ALL 0,2;LEG_REST_RIGHT 0,2;LEG_REST_LEFT 0,-2;TAIL_0 1,0;TORSO_1 0,-999
ANIM_IDLE=DELAY 2;ROW 1;SKELETON SKELETON_STAND
ANIM_IDLE_1=TORSO_1 0,-999
ANIM_IDLE_2=TORSO_0 0,-999;ARM_REST_LEFT 0,1;ARM_REST_RIGHT 0,1;HELD_ITEM 0,1;BUST_0 0,1;HEAD 0,1

View File

@@ -1,5 +1,6 @@
package net.torvald.spriteanimation
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
@@ -31,10 +32,11 @@ class AssembledSpriteAnimation(
parentActor: ActorWithBody,
@Transient val disk: SimpleFileSystem?, // specify if the resources for the animation is contained in the disk archive
@Transient val bodypartToFileMap: EntryID?, // which file in the disk contains bodypart-to-fileid mapping for this particular instance of sprite animation
@Transient val isGlow: Boolean
@Transient val isGlow: Boolean,
@Transient val isEmissive: Boolean
) : SpriteAnimation(parentActor) {
constructor(adp: ADProperties, parentActor: ActorWithBody, isGlow: Boolean) : this(adp, parentActor, null, null, isGlow)
constructor(adp: ADProperties, parentActor: ActorWithBody, isGlow: Boolean, isEmissive: Boolean) : this(adp, parentActor, null, null, isGlow, isEmissive)
var currentFrame = 0 // while this number is zero-based, the frame number on the ADP is one-based
private set
@@ -112,9 +114,23 @@ class AssembledSpriteAnimation(
}
}
private fun fetchItemImage(item: GameItem) = if (isGlow) ItemCodex.getItemImageGlow(item) else ItemCodex.getItemImage(item)
private fun fetchItemImage(item: GameItem) = if (isEmissive)
ItemCodex.getItemImageEmissive(item)
else if (isGlow)
ItemCodex.getItemImageGlow(item)
else
ItemCodex.getItemImage(item)
private fun fetchItemImage(mode: Int, item: GameItem) = when (mode) {
0 -> ItemCodex.getItemImage(item)
1 -> ItemCodex.getItemImageGlow(item)
2 -> ItemCodex.getItemImageEmissive(item)
else -> throw IllegalArgumentException()
}
fun renderThisAnimation(batch: SpriteBatch, posX: Float, posY: Float, scale: Float, animName: String, mode: Int = 0) {
val oldBatchColour = batch.color.cpy()
fun renderThisAnimation(batch: SpriteBatch, posX: Float, posY: Float, scale: Float, animName: String) {
val animNameRoot = animName.substring(0, animName.indexOfLast { it == '_' }).ifBlank { return@renderThisAnimation }
// quick fix for the temporary de-sync bug in which when the update-rate per frame is much greater than once, it attempts to load animation with blank name
@@ -138,8 +154,9 @@ class AssembledSpriteAnimation(
// draw held items/armours?
if (name in jointNameToEquipPos) {
batch.color = if (mode > 0) Color.WHITE else oldBatchColour
ItemCodex[(parentActor as? Pocketed)?.inventory?.itemEquipped?.get(jointNameToEquipPos[name]!!)]?.let { item ->
fetchItemImage(item)?.let { image ->
fetchItemImage(mode, item)?.let { image ->
val drawPos = adp.origin + bodypartPos // imgCentre for held items are (0,0)
val w = image.regionWidth * scale
val h = image.regionHeight * scale
@@ -159,6 +176,7 @@ class AssembledSpriteAnimation(
}
}
else {
batch.color = oldBatchColour
res[name]?.let { image ->
var imgCentre = bodypartOrigins[name]!!
if (flipVertical) imgCentre = imgCentre.invertY()
@@ -185,10 +203,15 @@ class AssembledSpriteAnimation(
} ?: throw NullPointerException("Animation with name '$animNameRoot' is not found")
}
override fun render(frameDelta: Float, batch: SpriteBatch, posX: Float, posY: Float, scale: Float) {
/**
* Held items will ignore forcedColourFilter if mode > 0
*
* @param mode specifies the mode for drawing the held item. 0=diffuse, 1=glow, 2=emissive
*/
override fun render(frameDelta: Float, batch: SpriteBatch, posX: Float, posY: Float, scale: Float, mode: Int, forcedColourFilter: Color?) {
if (parentActor.isVisible) {
batch.color = colourFilter
renderThisAnimation(batch, posX, posY, scale, "${currentAnimation}_${1+currentFrame}")
batch.color = forcedColourFilter ?: colourFilter
renderThisAnimation(batch, posX, posY, scale, "${currentAnimation}_${1+currentFrame}", mode)
}
}

View File

@@ -16,7 +16,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
abstract class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
protected abstract val currentDelay: Second
abstract fun update(delta: Float)
abstract fun render(frameDelta: Float, batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f)
abstract fun render(frameDelta: Float, batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f, mode: Int = 0, forcedColourFilter: Color? = null)
var flipHorizontal = false
var flipVertical = false
@@ -143,14 +143,14 @@ class SheetSpriteAnimation(parentActor: ActorWithBody) : SpriteAnimation(parentA
* *
* @param scale
*/
override fun render(frameDelta: Float, batch: SpriteBatch, posX: Float, posY: Float, scale: Float) {
override fun render(frameDelta: Float, batch: SpriteBatch, posX: Float, posY: Float, scale: Float, mode: Int, forcedColourFilter: Color?) {
assert(cellWidth > 0 || cellHeight > 0) {
"Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor"
}
if (visible) {
val region = textureRegion.get(currentFrame, currentRow)
batch.color = colourFilter
batch.color = forcedColourFilter ?: colourFilter
val tx = (parentActor.hitboxTranslateX) * scale
val txF = (parentActor.hitboxTranslateX + parentActor.baseHitboxW) * scale

View File

@@ -1793,16 +1793,22 @@ open class ActorWithBody : Actor {
}
open fun drawGlow(frameDelta: Float, batch: SpriteBatch) {
if (isVisible && spriteGlow != null) {
if (isVisible) {
blendNormalStraightAlpha(batch)
drawSpriteInGoodPosition(frameDelta, spriteGlow!!, batch)
if (spriteGlow != null)
drawSpriteInGoodPosition(frameDelta, spriteGlow!!, batch, 2)
else
drawSpriteInGoodPosition(frameDelta, sprite!!, batch, 1, Color.BLACK)
}
}
open fun drawEmissive(frameDelta: Float, batch: SpriteBatch) {
if (isVisible && spriteEmissive != null) {
if (isVisible) {
blendNormalStraightAlpha(batch)
drawSpriteInGoodPosition(frameDelta, spriteEmissive!!, batch)
if (spriteEmissive != null)
drawSpriteInGoodPosition(frameDelta, spriteEmissive!!, batch, 1)
else
drawSpriteInGoodPosition(frameDelta, sprite!!, batch, 2, Color.BLACK)
}
}
@@ -1830,7 +1836,7 @@ open class ActorWithBody : Actor {
}
}
protected fun drawSpriteInGoodPosition(frameDelta: Float, sprite: SpriteAnimation, batch: SpriteBatch) {
protected fun drawSpriteInGoodPosition(frameDelta: Float, sprite: SpriteAnimation, batch: SpriteBatch, mode: Int = 0, forcedColourFilter: Color? = null) {
if (world == null) return
val offsetX = 0f
@@ -1840,7 +1846,7 @@ open class ActorWithBody : Actor {
val posY = hitbox.startY.plus(PHYS_EPSILON_DIST).toFloat()
drawBodyInGoodPosition(posX, posY) { x, y ->
sprite.render(frameDelta, batch, x + offsetX, y + offsetY, scale.toFloat())
sprite.render(frameDelta, batch, x + offsetX, y + offsetY, scale.toFloat(), mode, forcedColourFilter)
}
}

View File

@@ -137,6 +137,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable<GameItem>, Cloneabl
*/
@Transient open val itemImage: TextureRegion? = null
@Transient open val itemImageGlow: TextureRegion? = null
@Transient open val itemImageEmissive: TextureRegion? = null
/**
* Apparent mass of the item. (basemass * scale^3)

View File

@@ -135,6 +135,11 @@ class ItemCodex {
return getItemImageGlow(item.originalID)
}
fun getItemImageEmissive(item: GameItem?): TextureRegion? {
if (item == null) return null
return getItemImageEmissive(item.originalID)
}
fun getItemImage(itemID: ItemID?): TextureRegion? {
if (itemID == null) return null
@@ -193,6 +198,35 @@ class ItemCodex {
}
}
fun getItemImageEmissive(itemID: ItemID?): TextureRegion? {
if (itemID == null) return null
if (itemID.isDynamic()) {
return getItemImageEmissive(dynamicToStaticID(itemID))
}
else if (itemID.isItem()) {
return itemCodex[itemID]?.itemImageEmissive
}
else if (itemID.isWire()) {
return itemCodex[itemID]?.itemImageEmissive
}
else if (itemID.isWall()) {
val itemSheetNumber = App.tileMaker.tileIDtoItemSheetNumber(itemID.substring(5))
return BlocksDrawer.tileItemWallEmissive.get(
itemSheetNumber % App.tileMaker.TILES_IN_X,
itemSheetNumber / App.tileMaker.TILES_IN_X
)
}
// else: terrain
else {
val itemSheetNumber = App.tileMaker.tileIDtoItemSheetNumber(itemID)
return BlocksDrawer.tileItemTerrainEmissive.get(
itemSheetNumber % App.tileMaker.TILES_IN_X,
itemSheetNumber / App.tileMaker.TILES_IN_X
)
}
}
fun hasItem(itemID: ItemID): Boolean = dynamicItemInventory.containsKey(itemID)
fun isEmpty(): Boolean = itemCodex.isEmpty()
}

View File

@@ -53,6 +53,7 @@ class FixtureJukebox : Electric, PlaysMusic {
(mainUI as UIJukebox).parent = this
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/jukebox.tga")
val itemImage2 = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/jukebox_emsv.tga")
density = 1400.0
setHitboxDimension(TILE_SIZE * 2, TILE_SIZE * 3, 0, 0)
@@ -60,6 +61,9 @@ class FixtureJukebox : Electric, PlaysMusic {
makeNewSprite(TextureRegionPack(itemImage.texture, TILE_SIZE * 2, TILE_SIZE * 3)).let {
it.setRowsAndFrames(1,1)
}
makeNewSpriteEmissive(TextureRegionPack(itemImage2.texture, TILE_SIZE * 2, TILE_SIZE * 3)).let {
it.setRowsAndFrames(1,1)
}
actorValue[AVKey.BASEMASS] = 200.0
@@ -130,6 +134,7 @@ class FixtureJukebox : Electric, PlaysMusic {
}
@Transient private var lampDecay = 0f
@Transient private var lampIntensity = 0f
/**
* Try to stop the disc being played, and reset the background music cue
@@ -146,15 +151,27 @@ class FixtureJukebox : Electric, PlaysMusic {
if (isVisible && musicNowPlaying != null) {
val vol0 = (musicTracks[musicNowPlaying]?.processor?.maxSigLevel?.average() ?: 0.0).toFloat()
val vol = FastMath.interpolateLinear(0.8f, vol0, lampDecay)
lampIntensity = vol.coerceIn(0f, 1f)
blendScreen(batch)
backLamp.colourFilter = Color(0f, vol.coerceIn(0f, 1f), 0f, 1f)
backLamp.colourFilter = Color(0f, lampIntensity, 0f, 1f)
drawSpriteInGoodPosition(frameDelta, backLamp, batch)
lampDecay = vol
}
}
override fun drawEmissive(frameDelta: Float, batch: SpriteBatch) {
blendNormalStraightAlpha(batch)
super.drawEmissive(frameDelta, batch)
if (isVisible && musicNowPlaying != null) {
blendScreen(batch)
backLamp.colourFilter = Color(0f, lampIntensity / 2f, 0f, 1f)
drawSpriteInGoodPosition(frameDelta, backLamp, batch)
}
}
private fun stopDiscPlayback() {
musicNowPlaying?.let {
stopAudio(it)

View File

@@ -45,9 +45,10 @@ class IngamePlayer : ActorHumanoid, HasAssembledSprite, NoSerialise {
private constructor()
constructor(animDescPath: String, animDescPathGlow: String?, born: Long) : super(born) {
constructor(animDescPath: String, animDescPathGlow: String?, animDescPathEmissive: String?, born: Long) : super(born) {
animDesc = ADProperties(Gdx.files.internal(animDescPath))
if (animDescPathGlow != null) animDescGlow = ADProperties(Gdx.files.internal(animDescPathGlow))
if (animDescPathEmissive != null) animDescEmissive = ADProperties(Gdx.files.internal(animDescPathEmissive))
actorValue[AVKey.__HISTORICAL_BORNTIME] = born
}

View File

@@ -13,7 +13,7 @@ object PlayerBuilder {
operator fun invoke(): Actor {
val world = (Terrarum.ingame!! as TerrarumIngame).world
val p: Actor = IngamePlayer("lol", "lol_glow", world.worldTime.TIME_T)
val p: Actor = IngamePlayer("lol", "lol_glow", "lol_emsv", world.worldTime.TIME_T)
InjectCreatureRaw(p.actorValue, "basegame", "CreaturePlayer.json")
// attach sprite

View File

@@ -10,9 +10,10 @@ import net.torvald.terrarum.gameactors.AVKey
object PlayerBuilderTestSubject1 {
operator fun invoke(): IngamePlayer {
val p: IngamePlayer = IngamePlayer(
ModMgr.getGdxFile("basegame", "sprites/test_sprite.properties").path(),
ModMgr.getGdxFile("basegame", "sprites/test_sprite_glow.properties").path(),
-589141658L // random value thrown
ModMgr.getGdxFile("basegame", "sprites/test_sprite.properties").path(),
ModMgr.getGdxFile("basegame", "sprites/test_sprite_glow.properties").path(),
ModMgr.getGdxFile("basegame", "sprites/test_sprite_emsv.properties").path(),
0L // random value thrown
)
InjectCreatureRaw(p.actorValue, "basegame", "CreaturePlayer.json")
@@ -23,13 +24,11 @@ object PlayerBuilderTestSubject1 {
p.actorValue[AVKey.NAME] = "Test Subject 1"
/*p.makeNewSprite(TextureRegionPack(ModMgr.getGdxFile("basegame", "sprites/npc_template_anim_prototype.tga"), 48, 52))
p.sprite!!.delays = floatArrayOf(2f, 1f/12f) // second value does nothing -- overridden by ActorHumanoid.updateSprite(float)
p.sprite!!.setRowsAndFrames(2, 4)*/
// TODO make null animation if animDesc is null
p.animDesc?.let { p.sprite = AssembledSpriteAnimation(it, p, false, false) }
p.animDescGlow?.let { p.spriteGlow = AssembledSpriteAnimation(it, p, true, false) }
p.animDescEmissive?.let { p.spriteEmissive = AssembledSpriteAnimation(it, p, true, true) }
p.animDesc?.let { p.sprite = AssembledSpriteAnimation(it, p, false) }
p.animDescGlow?.let { p.spriteGlow = AssembledSpriteAnimation(it, p, true) }
//p.reassembleSprite(p.sprite, p.spriteGlow, null)
p.setHitboxDimension(15, p.actorValue.getAsInt(AVKey.BASEHEIGHT) ?: ActorHumanoid.BASE_HEIGHT, 21, 0)
// ingame must teleport the player to the spawn point

View File

@@ -12,9 +12,10 @@ import net.torvald.terrarum.gameactors.AVKey
object PlayerBuilderWerebeastTest {
operator fun invoke(): IngamePlayer {
val p: IngamePlayer = IngamePlayer(
ModMgr.getGdxFile("basegame", "sprites/taimu2.properties").path(),
ModMgr.getGdxFile("basegame", "sprites/taimu2_glow.properties").path(),
-589141658L // random value thrown
ModMgr.getGdxFile("basegame", "sprites/taimu2.properties").path(),
ModMgr.getGdxFile("basegame", "sprites/taimu2_glow.properties").path(),
ModMgr.getGdxFile("basegame", "sprites/taimu2_emsv.properties").path(),
-589141658L // random value thrown
)
InjectCreatureRaw(p.actorValue, "basegame", "CreatureWerebeastBossBase.json")
@@ -24,9 +25,9 @@ object PlayerBuilderWerebeastTest {
p.actorValue[AVKey.ACTION_INTERVAL] = ActorHumanoid.BASE_ACTION_INTERVAL
p.actorValue[AVKey.NAME] = "Taimu"
p.animDesc?.let { p.sprite = AssembledSpriteAnimation(it, p, false) }
p.animDescGlow?.let { p.spriteGlow = AssembledSpriteAnimation(it, p, true) }
p.animDescEmissive?.let { p.spriteEmissive = AssembledSpriteAnimation(it, p, true) }
p.animDesc?.let { p.sprite = AssembledSpriteAnimation(it, p, false, false) }
p.animDescGlow?.let { p.spriteGlow = AssembledSpriteAnimation(it, p, true, false) }
p.animDescEmissive?.let { p.spriteEmissive = AssembledSpriteAnimation(it, p, false, true) }
p.setHitboxDimension(22, p.actorValue.getAsInt(AVKey.BASEHEIGHT)!!, 30, 0)
p.setPosition(3.0 * TILE_SIZE, 3.0 * TILE_SIZE)

View File

@@ -14,6 +14,8 @@ class ItemFurnaceAndAnvil(originalID: ItemID) : FixtureItemBase(originalID, "net
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/metalworking_furnace_and_anvil.tga")
override val itemImageEmissive: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/metalworking_furnace_and_anvil_emsv.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_FURNACE_AND_ANVIL"

View File

@@ -14,6 +14,8 @@ class ItemJukebox(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/jukebox.tga")
override val itemImageEmissive: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/jukebox_emsv.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_JUKEBOX"

View File

@@ -14,6 +14,8 @@ class ItemSmelterBasic(originalID: ItemID) : FixtureItemBase(originalID, "net.to
override val materialId = ""
override val itemImage: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/smelter_tall.tga")
override val itemImageEmissive: TextureRegion
get() = getItemImageFromSingleImage("basegame", "sprites/fixtures/smelter_tall_emsv.tga")
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_SMELTER_SMALL"

View File

@@ -180,8 +180,9 @@ object ReadActor {
actor,
if (bodypartsFile != null) disk else null,
if (bodypartsFile != null) BODYPART_TO_ENTRY_MAP else null,
false
false, false
)
if (animFileGlow != null) {
actor.animDescGlow = ADProperties(ByteArray64Reader(animFileGlow.bytes, Common.CHARSET))
actor.spriteGlow = AssembledSpriteAnimation(
@@ -189,9 +190,10 @@ object ReadActor {
actor,
if (bodypartsFile != null) disk else null,
if (bodypartsFile != null) BODYPARTGLOW_TO_ENTRY_MAP else null,
true
true, false
)
}
if (animFileEmissive != null) {
actor.animDescEmissive = ADProperties(ByteArray64Reader(animFileEmissive.bytes, Common.CHARSET))
actor.spriteEmissive = AssembledSpriteAnimation(
@@ -199,7 +201,7 @@ object ReadActor {
actor,
if (bodypartsFile != null) disk else null,
if (bodypartsFile != null) BODYPARTEMISSIVE_TO_ENTRY_MAP else null,
true
false, true
)
}
@@ -213,12 +215,58 @@ object ReadActor {
actor.reassembleSprite(actor.sprite!!, actor.spriteGlow, heldItem)*/
}
else if (actor is ActorWithBody && actor is HasAssembledSprite) {
if (actor.animDesc != null) actor.sprite = AssembledSpriteAnimation(actor.animDesc!!, actor, false)
if (actor.animDescGlow != null) actor.spriteGlow = AssembledSpriteAnimation(actor.animDescGlow!!, actor, true)
if (actor.animDescEmissive != null) actor.spriteEmissive = AssembledSpriteAnimation(actor.animDescEmissive!!, actor, true)
if (actor.animDesc != null) actor.sprite = AssembledSpriteAnimation(actor.animDesc!!, actor, false, false)
if (actor.animDescGlow != null) actor.spriteGlow = AssembledSpriteAnimation(actor.animDescGlow!!, actor, true, false)
if (actor.animDescEmissive != null) actor.spriteEmissive = AssembledSpriteAnimation(actor.animDescEmissive!!, actor, false, true)
//actor.reassembleSprite(actor.sprite, actor.spriteGlow, null)
}
}
private fun makeSprite(mode: Int, actor: IngamePlayer, disk: SimpleFileSystem, file: EntryFile?, bodypartsFile: EntryFile?) {
val animDesc = when (mode) {
0 -> actor.animDesc
1 -> actor.animDescGlow
2 -> actor.animDescEmissive
else -> throw IllegalArgumentException()
}
if (file != null) {
when (mode) {
0 -> { actor.animDesc = ADProperties(ByteArray64Reader(file.bytes, Common.CHARSET)) }
1 -> { actor.animDescGlow = ADProperties(ByteArray64Reader(file.bytes, Common.CHARSET)) }
2 -> { actor.animDescEmissive = ADProperties(ByteArray64Reader(file.bytes, Common.CHARSET)) }
else -> throw IllegalArgumentException()
}
when (mode) {
0 -> { actor.sprite = AssembledSpriteAnimation(
actor.animDesc!!,
actor,
if (bodypartsFile != null) disk else null,
if (bodypartsFile != null) BODYPART_TO_ENTRY_MAP else null,
false, false
) }
1 -> { actor.spriteGlow = AssembledSpriteAnimation(
actor.animDescGlow!!,
actor,
if (bodypartsFile != null) disk else null,
if (bodypartsFile != null) BODYPARTGLOW_TO_ENTRY_MAP else null,
true, false
) }
2 -> { actor.spriteEmissive = AssembledSpriteAnimation(
actor.animDescEmissive!!,
actor,
if (bodypartsFile != null) disk else null,
if (bodypartsFile != null) BODYPARTEMISSIVE_TO_ENTRY_MAP else null,
false, true
) }
else -> throw IllegalArgumentException()
}
}
else {
}
}
}

View File

@@ -51,25 +51,26 @@ object AssembleSheetPixmap {
}
private fun drawAndGetCanvas(properties: ADProperties, fileGetter: (String) -> InputStream?, injectedItem: GameItem?): Pixmap {
private fun drawAndGetCanvas(properties: ADProperties, fileGetter: (String) -> InputStream?, injectedItem: GameItem?, layerMode: Int): Pixmap {
val canvas = Pixmap(properties.cols * (properties.frameWidth), properties.rows * (properties.frameHeight), Pixmap.Format.RGBA8888)
canvas.blending = Pixmap.Blending.SourceOver
// actually draw
properties.transforms.forEach { (t, _) ->
drawThisFrame(t, canvas, properties, fileGetter, injectedItem)
drawThisFrame(t, canvas, properties, fileGetter, injectedItem, layerMode)
}
return canvas
}
fun fromAssetsDir(properties: ADProperties, injectedItem: GameItem?) = drawAndGetCanvas(properties, getAssetsDirFileGetter(properties), injectedItem)
fun fromAssetsDir(properties: ADProperties, injectedItem: GameItem?, layerMode: Int) =
drawAndGetCanvas(properties, getAssetsDirFileGetter(properties), injectedItem, layerMode)
fun fromVirtualDisk(disk: SimpleFileSystem, entrynum: Long, properties: ADProperties, injectedItem: GameItem?): Pixmap {
fun fromVirtualDisk(disk: SimpleFileSystem, entrynum: Long, properties: ADProperties, injectedItem: GameItem?, layerMode: Int): Pixmap {
val bodypartMapping = Properties()
bodypartMapping.load(ByteArray64Reader(disk.getFile(entrynum)!!.bytes, Common.CHARSET))
return drawAndGetCanvas(properties, getVirtualDiskFileGetter(bodypartMapping, disk), injectedItem)
return drawAndGetCanvas(properties, getVirtualDiskFileGetter(bodypartMapping, disk), injectedItem, layerMode)
}
fun getPartPixmap(getFile: (String) -> InputStream?, partName: String): Pixmap? {
@@ -133,10 +134,11 @@ object AssembleSheetPixmap {
}
fun drawThisFrame(frameName: String,
canvas: Pixmap,
properties: ADProperties,
fileGetter: (String) -> InputStream?,
injectedItem: GameItem?
canvas: Pixmap,
properties: ADProperties,
fileGetter: (String) -> InputStream?,
injectedItem: GameItem?,
layerMode: Int
) {
val theAnim = properties.getAnimByFrameName(frameName)
val skeleton = theAnim.skeleton.joints.reversed()
@@ -163,18 +165,29 @@ object AssembleSheetPixmap {
// AppLoader.printdbg(this, "Frame to draw: $frameName (R$animRow C$animFrame)")
drawFrame(animRow, animFrame, canvas, properties, bodypartOrigins, bodypartImages, transformList, injectedItem)
drawFrame(animRow, animFrame, canvas, properties, bodypartOrigins, bodypartImages, transformList, injectedItem, layerMode)
bodypartImages.values.forEach { it?.dispose() }
}
private fun getItemImage(layerMode: Int, injectedItem: GameItem?): TextureRegion? {
return when (layerMode) {
0 -> ItemCodex.getItemImage(injectedItem)
1 -> ItemCodex.getItemImageGlow(injectedItem)
2 -> ItemCodex.getItemImageEmissive(injectedItem)
else -> throw IllegalArgumentException()
}
}
fun drawFrame(row: Int, column: Int,
canvas: Pixmap,
props: ADProperties,
bodypartOrigins: HashMap<String, ADPropertyObject.Vector2i>,
bodypartImages: Map<String, Pixmap?>,
transformList: List<Pair<String, ADPropertyObject.Vector2i>>,
injectedItem: GameItem?
canvas: Pixmap,
props: ADProperties,
bodypartOrigins: HashMap<String, ADPropertyObject.Vector2i>,
bodypartImages: Map<String, Pixmap?>,
transformList: List<Pair<String, ADPropertyObject.Vector2i>>,
injectedItem: GameItem?,
layerMode: Int
) {
val tmpFrame = Pixmap(props.frameWidth, props.frameHeight, Pixmap.Format.RGBA8888)
@@ -182,7 +195,7 @@ object AssembleSheetPixmap {
if (name == "HELD_ITEM" && injectedItem != null) {
// printdbg(this, "ID of the held item: ${injectedItem.originalID}")
ItemCodex.getItemImage(injectedItem)?.let { textureRegion ->
getItemImage(layerMode, injectedItem)?.let { textureRegion ->
// printdbg(this, "and it did have a textureregion")
val texdata = textureRegion.texture.textureData

View File

@@ -299,7 +299,7 @@ class SpriteAssemblerPreview: Game() {
}
private fun assembleImage(prop: ADProperties) {
image = AssembleSheetPixmap.fromAssetsDir(prop, null)
image = AssembleSheetPixmap.fromAssetsDir(prop, null, 0)
}
// TODO rename to requestAssembly

View File

@@ -11,7 +11,7 @@ class SpriteAssemblerTest {
operator fun invoke() {
val properties = ADProperties(StringReader(ADLParsingTest().TEST_STR))
AssembleSheetPixmap.fromAssetsDir(properties, null)
AssembleSheetPixmap.fromAssetsDir(properties, null, 0)
}
}

View File

@@ -53,10 +53,13 @@ internal object BlocksDrawer {
//val tilesWire: TextureRegionPack
val tileItemTerrain: TextureRegionPack
val tileItemTerrainGlow: TextureRegionPack
val tileItemTerrainEmissive: TextureRegionPack
val tileItemWall: TextureRegionPack
val tileItemWallGlow: TextureRegionPack
val tileItemWallEmissive: TextureRegionPack
val tilesFluid: TextureRegionPack
val tilesGlow: TextureRegionPack
val tilesEmissive: TextureRegionPack
//val tileItemWall = Image(TILE_SIZE * 16, TILE_SIZE * GameWorld.TILES_SUPPORTED / 16) // 4 MB
@@ -119,6 +122,7 @@ internal object BlocksDrawer {
//tilesWire = TextureRegionPack(ModMgr.getGdxFile("basegame", "wires/wire.tga"), TILE_SIZE, TILE_SIZE)
tilesFluid = TextureRegionPack(Texture(App.tileMaker.atlasFluid), TILE_SIZE, TILE_SIZE)
tilesGlow = TextureRegionPack(Texture(App.tileMaker.atlasGlow), TILE_SIZE, TILE_SIZE)
tilesEmissive = TextureRegionPack(Texture(App.tileMaker.atlasEmissive), TILE_SIZE, TILE_SIZE)
printdbg(this, "Making terrain and wall item textures...")
@@ -129,8 +133,10 @@ internal object BlocksDrawer {
tileItemTerrain = TextureRegionPack(App.tileMaker.itemTerrainTexture, TILE_SIZE, TILE_SIZE)
tileItemTerrainGlow = TextureRegionPack(App.tileMaker.itemTerrainTextureGlow, TILE_SIZE, TILE_SIZE)
tileItemTerrainEmissive = TextureRegionPack(App.tileMaker.itemTerrainTextureEmissive, TILE_SIZE, TILE_SIZE)
tileItemWall = TextureRegionPack(App.tileMaker.itemWallTexture, TILE_SIZE, TILE_SIZE)
tileItemWallGlow = TextureRegionPack(App.tileMaker.itemWallTextureGlow, TILE_SIZE, TILE_SIZE)
tileItemWallEmissive = TextureRegionPack(App.tileMaker.itemWallTextureEmissive, TILE_SIZE, TILE_SIZE)
// val texdata = tileItemTerrain.texture.textureData
@@ -217,28 +223,28 @@ internal object BlocksDrawer {
}
}
internal fun drawWall(projectionMatrix: Matrix4, drawGlow: Boolean, drawBlack: Boolean = false) {
internal fun drawWall(projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean = false) {
gdxBlendNormalStraightAlpha()
renderUsingBuffer(WALL, projectionMatrix, drawGlow, drawBlack)
renderUsingBuffer(WALL, projectionMatrix, drawGlow, drawEmissive)
gdxBlendMul()
renderUsingBuffer(OCCLUSION, projectionMatrix, false, drawBlack)
renderUsingBuffer(OCCLUSION, projectionMatrix, false, drawEmissive)
}
internal fun drawTerrain(projectionMatrix: Matrix4, drawGlow: Boolean, drawBlack: Boolean = false) {
internal fun drawTerrain(projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean = false) {
gdxBlendNormalStraightAlpha()
renderUsingBuffer(TERRAIN, projectionMatrix, drawGlow, drawBlack)
renderUsingBuffer(ORES, projectionMatrix, drawGlow, drawBlack)
renderUsingBuffer(FLUID, projectionMatrix, drawGlow, drawBlack)
renderUsingBuffer(TERRAIN, projectionMatrix, drawGlow, drawEmissive)
renderUsingBuffer(ORES, projectionMatrix, drawGlow, drawEmissive)
renderUsingBuffer(FLUID, projectionMatrix, drawGlow, drawEmissive)
}
internal fun drawFront(projectionMatrix: Matrix4, drawBlack: Boolean = false) {
internal fun drawFront(projectionMatrix: Matrix4, drawEmissive: Boolean = false) {
gdxBlendMul()
// let's just not MUL on terrain, make it FLUID only...
renderUsingBuffer(FLUID, projectionMatrix, false, drawBlack)
renderUsingBuffer(FLUID, projectionMatrix, false, drawEmissive)
@@ -708,7 +714,7 @@ internal object BlocksDrawer {
private var _tilesBufferAsTex: Texture = Texture(1, 1, Pixmap.Format.RGBA8888)
private val occlusionIntensity = 0.22222222f // too low value and dark-coloured walls won't darken enough
private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawBlack: Boolean) {
private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean) {
//Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
//Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
@@ -732,7 +738,7 @@ internal object BlocksDrawer {
OCCLUSION -> occlusionBuffer
else -> throw IllegalArgumentException()
}
val vertexColour = if (drawBlack) Color.BLACK else when (mode) {
val vertexColour = when (mode) {
TERRAIN, /*WIRE,*/ ORES, FLUID, OCCLUSION -> Color.WHITE
WALL -> WALL_OVERLAY_COLOUR
else -> throw IllegalArgumentException()
@@ -754,7 +760,12 @@ internal object BlocksDrawer {
_tilesBufferAsTex = Texture(tilesBuffer)
_tilesBufferAsTex.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
if (drawGlow) {
if (drawEmissive) {
tilesEmissive.texture.bind(2)
_tilesBufferAsTex.bind(1) // trying 1 and 0...
tilesEmissive.texture.bind(0) // for some fuck reason, it must be bound as last
}
else if (drawGlow) {
tilesGlow.texture.bind(2)
_tilesBufferAsTex.bind(1) // trying 1 and 0...
tilesGlow.texture.bind(0) // for some fuck reason, it must be bound as last
@@ -880,11 +891,13 @@ internal object BlocksDrawer {
weatherTerrains.forEach { it.dispose() }
tilesGlow.dispose()
//tilesWire.dispose()
tilesEmissive.dispose()
tileItemTerrain.dispose()
tileItemTerrainGlow.dispose()
tileItemTerrainEmissive.dispose()
tileItemWall.dispose()
tileItemWallGlow.dispose()
tileItemWallEmissive.dispose()
tilesFluid.dispose()
tilesBuffer.dispose()
_tilesBufferAsTex.dispose()

View File

@@ -11,13 +11,10 @@ import net.torvald.gdx.graphics.Cvec
import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.utils.HashArray
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.AtlasSource.*
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.RenderTag.Companion.MASK_47
import kotlin.math.roundToInt
import kotlin.math.sqrt
/**
@@ -51,10 +48,13 @@ class CreateTileAtlas {
lateinit var atlasHibernal: Pixmap
lateinit var atlasFluid: Pixmap
lateinit var atlasGlow: Pixmap // glowing won't be affected by the season... for now
lateinit var atlasEmissive: Pixmap // glowing won't be affected by the season... for now
lateinit var itemTerrainTexture: Texture
lateinit var itemTerrainTextureGlow: Texture
lateinit var itemTerrainTextureEmissive: Texture
lateinit var itemWallTexture: Texture
lateinit var itemWallTextureGlow: Texture
lateinit var itemWallTextureEmissive: Texture
lateinit var terrainTileColourMap: HashMap<ItemID, Cvec>
lateinit var tags: HashMap<ItemID, RenderTag> // TileID, RenderTag
private set
@@ -76,8 +76,10 @@ class CreateTileAtlas {
internal lateinit var itemTerrainPixmap: Pixmap
internal lateinit var itemTerrainPixmapGlow: Pixmap
internal lateinit var itemTerrainPixmapEmissive: Pixmap
internal lateinit var itemWallPixmap: Pixmap
internal lateinit var itemWallPixmapGlow: Pixmap
internal lateinit var itemWallPixmapEmissive: Pixmap
val atlas: Pixmap
get() = atlasVernal
@@ -145,6 +147,7 @@ class CreateTileAtlas {
atlasHibernal = 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).also { it.blending = Pixmap.Blending.None }
atlasGlow = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
atlasEmissive = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
// populate the atlantes with atlasInit
// this just directly copies the image to the atlantes :p
@@ -203,7 +206,15 @@ class CreateTileAtlas {
val glowFile = Gdx.files.internal(
filehandle.path().dropLast(4) + "_glow.tga"
) // assuming strict ".tga" file for now...
fileToAtlantes(modname, filehandle, if (glowFile.exists()) glowFile else null, if (dirName == "blocks") null else dirName)
val emissiveFile = Gdx.files.internal(
filehandle.path().dropLast(4) + "_emsv.tga"
) // assuming strict ".tga" file for now...
fileToAtlantes(
modname, filehandle,
if (glowFile.exists()) glowFile else null,
if (emissiveFile.exists()) emissiveFile else null,
if (dirName == "blocks") null else dirName
)
}
catch (e: GdxRuntimeException) {
System.err.println("Couldn't load file $filehandle from $modname, skipping...")
@@ -240,8 +251,10 @@ class CreateTileAtlas {
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)
itemTerrainPixmapEmissive = 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)
itemWallPixmapEmissive = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888)
tags.toMap().forEach { id, tag ->
val tilePosFromAtlas = tag.tileNumber + maskTypetoTileIDForItemImage(tag.maskType)
@@ -252,8 +265,10 @@ class CreateTileAtlas {
val destY = (t / TILES_IN_X) * TILE_SIZE
itemTerrainPixmap.drawPixmap(atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
itemTerrainPixmapGlow.drawPixmap(atlasGlow, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
itemTerrainPixmapEmissive.drawPixmap(atlasEmissive, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
itemWallPixmap.drawPixmap(atlas, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
itemWallPixmapGlow.drawPixmap(atlasGlow, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
itemWallPixmapEmissive.drawPixmap(atlasEmissive, srcX, srcY, TILE_SIZE, TILE_SIZE, destX, destY, TILE_SIZE, TILE_SIZE)
}
// darken things for the wall
for (y in 0 until itemWallPixmap.height) {
@@ -262,6 +277,8 @@ class CreateTileAtlas {
itemWallPixmap.drawPixel(x, y, c1)
val c2 = Color(itemWallPixmapGlow.getPixel(x, y)).mulAndAssign(WALL_OVERLAY_COLOUR).toRGBA()
itemWallPixmapGlow.drawPixel(x, y, c2)
val c3 = Color(itemWallPixmapEmissive.getPixel(x, y)).mulAndAssign(WALL_OVERLAY_COLOUR).toRGBA()
itemWallPixmapEmissive.drawPixel(x, y, c3)
}
}
@@ -295,8 +312,10 @@ class CreateTileAtlas {
itemTerrainTexture = Texture(itemTerrainPixmap)
itemTerrainTextureGlow = Texture(itemTerrainPixmapGlow)
itemTerrainTextureEmissive = Texture(itemTerrainPixmapEmissive)
itemWallTexture = Texture(itemWallPixmap)
itemWallTextureGlow = Texture(itemWallPixmapGlow)
itemWallTextureEmissive = Texture(itemWallPixmapEmissive)
// itemTerrainPixmap.dispose()
// itemWallPixmap.dispose()
@@ -314,10 +333,11 @@ class CreateTileAtlas {
val nullTile = Pixmap(TILE_SIZE * 16, TILE_SIZE * 16, Pixmap.Format.RGBA8888)
private fun fileToAtlantes(modname: String, matte: FileHandle, glow: FileHandle?, mode: String?) {
val tilesPixmap = Pixmap(matte)
private fun fileToAtlantes(modname: String, diffuse: FileHandle, glow: FileHandle?, emissive: FileHandle?, mode: String?) {
val tilesPixmap = Pixmap(diffuse)
val tilesGlowPixmap = if (glow != null) Pixmap(glow) else nullTile
val blockName = matte.nameWithoutExtension().split('-').last().toInt() // basically a filename
val tilesEmissivePixmap = if (emissive != null) Pixmap(emissive) else nullTile
val blockName = diffuse.nameWithoutExtension().split('-').last().toInt() // basically a filename
val blockID = if (mode != null) "$mode@$modname:$blockName" else "$modname:$blockName"
@@ -325,37 +345,37 @@ class CreateTileAtlas {
// predefined by the image dimension: 16x16 for (1,0)
if (tilesPixmap.width == TILE_SIZE && tilesPixmap.height == TILE_SIZE) {
addTag(blockID, RenderTag.CONNECT_SELF, RenderTag.MASK_NA)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, RenderTag.MASK_NA)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, RenderTag.MASK_NA)
}
// predefined by the image dimension: 64x16 for (2,3)
else if (tilesPixmap.width == TILE_SIZE * 4 && tilesPixmap.height == TILE_SIZE) {
addTag(blockID, RenderTag.CONNECT_WALL_STICKER, RenderTag.MASK_TORCH)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, RenderTag.MASK_TORCH)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, RenderTag.MASK_TORCH)
}
// predefined by the image dimension: 128x16 for (3,4)
else if (tilesPixmap.width == TILE_SIZE * 8 && tilesPixmap.height == TILE_SIZE) {
addTag(blockID, RenderTag.CONNECT_WALL_STICKER_CONNECT_SELF, RenderTag.MASK_PLATFORM)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, RenderTag.MASK_PLATFORM)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, RenderTag.MASK_PLATFORM)
}
// predefined by the image dimension: 256x16
else if (tilesPixmap.width == TILE_SIZE * 16 && tilesPixmap.height == TILE_SIZE) {
addTag(blockID, RenderTag.CONNECT_SELF, RenderTag.MASK_16)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, RenderTag.MASK_16)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, RenderTag.MASK_16)
}
// predefined by the image dimension: 256x64
else if (tilesPixmap.width == TILE_SIZE * 16 && tilesPixmap.height == TILE_SIZE * 4) {
addTag(blockID, RenderTag.CONNECT_SELF, RenderTag.MASK_16X4)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, RenderTag.MASK_16X4)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, RenderTag.MASK_16X4)
}
// predefined by the image dimension: 256x256
else if (tilesPixmap.width == TILE_SIZE * 16 && tilesPixmap.height == TILE_SIZE * 16) {
addTag(blockID, RenderTag.CONNECT_SELF, RenderTag.MASK_16X16)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, RenderTag.MASK_16X16)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, RenderTag.MASK_16X16)
}
// 112x112 or 224x224
else {
if (tilesPixmap.width != tilesPixmap.height && tilesPixmap.width % (7 * TILE_SIZE) >= 2) {
throw IllegalArgumentException("Unrecognized image dimension ${tilesPixmap.width}x${tilesPixmap.height} from $modname:${matte.name()}")
throw IllegalArgumentException("Unrecognized image dimension ${tilesPixmap.width}x${tilesPixmap.height} from $modname:${diffuse.name()}")
}
// figure out the tags
var connectionType = 0
@@ -371,7 +391,7 @@ class CreateTileAtlas {
}
addTag(blockID, connectionType, maskType)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, maskType)
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, maskType)
}
itemSheetNumbers[blockID] = itemSheetCursor
@@ -400,7 +420,7 @@ class CreateTileAtlas {
printdbg(this, "tileName ${id} ->> tileNumber ${atlasCursor}")
}
private fun drawToAtlantes(matte: Pixmap, glow: Pixmap, renderMask: Int) {
private fun drawToAtlantes(diffuse: Pixmap, glow: Pixmap, emissive: Pixmap, renderMask: Int) {
val tilesCount = RenderTag.maskTypeToTileCount(renderMask)
if (atlasCursor + tilesCount >= TOTAL_TILES) {
// throw Error("Too much tiles for $MAX_TEX_SIZE texture size: $atlasCursor")
@@ -408,30 +428,33 @@ class CreateTileAtlas {
expandAtlantes()
}
val sixSeasonal = matte.width == 21 * TILE_SIZE && matte.height == 14 * TILE_SIZE
val txOfPixmap = matte.width / TILE_SIZE
val sixSeasonal = diffuse.width == 21 * TILE_SIZE && diffuse.height == 14 * TILE_SIZE
val txOfPixmap = diffuse.width / TILE_SIZE
val txOfPixmapGlow = glow.width / TILE_SIZE
val txOfPixmapEmissive = emissive.width / TILE_SIZE
for (i in 0 until tilesCount) {
//printdbg(this, "Rendering to atlas, tile# $atlasCursor, tilesCount = $tilesCount, seasonal = $seasonal")
// different texture for different seasons (224x224)
if (sixSeasonal) {
val i = if (renderMask == MASK_47) (if (i < 41) i else i + 1) else i // to compensate the discontinuity between 40th and 41st tile
_drawToAtlantes(matte, atlasCursor, i % 7 , i / 7, PREVERNAL)
_drawToAtlantes(matte, atlasCursor, i % 7 + 7 , i / 7, VERNAL)
_drawToAtlantes(matte, atlasCursor, i % 7 + 14, i / 7, AESTIVAL)
_drawToAtlantes(diffuse, atlasCursor, i % 7 , i / 7, PREVERNAL)
_drawToAtlantes(diffuse, atlasCursor, i % 7 + 7 , i / 7, VERNAL)
_drawToAtlantes(diffuse, atlasCursor, i % 7 + 14, i / 7, AESTIVAL)
_drawToAtlantes(matte, atlasCursor, i % 7 + 14, i / 7 + 7, SEROTINAL)
_drawToAtlantes(matte, atlasCursor, i % 7 + 7 , i / 7 + 7, AUTUMNAL)
_drawToAtlantes(matte, atlasCursor, i % 7 , i / 7 + 7, HIBERNAL)
_drawToAtlantes(diffuse, atlasCursor, i % 7 + 14, i / 7 + 7, SEROTINAL)
_drawToAtlantes(diffuse, atlasCursor, i % 7 + 7 , i / 7 + 7, AUTUMNAL)
_drawToAtlantes(diffuse, atlasCursor, i % 7 , i / 7 + 7, HIBERNAL)
_drawToAtlantes(glow, atlasCursor, i % 7, i / 7, GLOW)
_drawToAtlantes(emissive, atlasCursor, i % 7, i / 7, EMISSIVE)
atlasCursor += 1
}
else {
val i = if (renderMask == MASK_47) (if (i < 41) i else i + 1) else i // to compensate the discontinuity between 40th and 41st tile
_drawToAtlantes(matte, atlasCursor, i % txOfPixmap, i / txOfPixmap, SIX_SEASONS)
_drawToAtlantes(diffuse, atlasCursor, i % txOfPixmap, i / txOfPixmap, SIX_SEASONS)
_drawToAtlantes(glow, atlasCursor, i % txOfPixmapGlow, i / txOfPixmapGlow, GLOW)
_drawToAtlantes(emissive, atlasCursor, i % txOfPixmapGlow, i / txOfPixmapGlow, EMISSIVE)
atlasCursor += 1
}
}
@@ -466,6 +489,7 @@ class CreateTileAtlas {
HIBERNAL -> atlasHibernal.drawPixmap(pixmap, sourceX, sourceY, TILE_SIZE, TILE_SIZE, atlasX, atlasY, TILE_SIZE, TILE_SIZE)
FLUID -> atlasFluid.drawPixmap(pixmap, sourceX, sourceY, TILE_SIZE, TILE_SIZE, atlasX, atlasY, TILE_SIZE, TILE_SIZE)
GLOW -> atlasGlow.drawPixmap(pixmap, sourceX, sourceY, TILE_SIZE, TILE_SIZE, atlasX, atlasY, TILE_SIZE, TILE_SIZE)
EMISSIVE -> atlasEmissive.drawPixmap(pixmap, sourceX, sourceY, TILE_SIZE, TILE_SIZE, atlasX, atlasY, TILE_SIZE, TILE_SIZE)
else -> throw IllegalArgumentException("Unknown draw source $source")
}
}
@@ -511,6 +535,7 @@ class CreateTileAtlas {
atlasHibernal.dispose()
atlasFluid.dispose()
atlasGlow.dispose()
atlasEmissive.dispose()
//itemTerrainTexture.dispose() //BlocksDrawer will dispose of it as it disposes of 'tileItemTerrain (TextureRegionPack)'
//itemTerrainTextureGlow.dispose() //BlocksDrawer will dispose of it as it disposes of 'tileItemTerrain (TextureRegionPack)'
//itemWallTexture.dispose() //BlocksDrawer will dispose of it as it disposes of 'tileItemWall (TextureRegionPack)'
@@ -522,7 +547,7 @@ class CreateTileAtlas {
}
private enum class AtlasSource {
/*FOUR_SEASONS, SUMMER, AUTUMN, WINTER, SPRING,*/ FLUID, GLOW,
/*FOUR_SEASONS, SUMMER, AUTUMN, WINTER, SPRING,*/ FLUID, GLOW, EMISSIVE,
SIX_SEASONS, PREVERNAL, VERNAL, AESTIVAL, SEROTINAL, AUTUMNAL, HIBERNAL,
}
@@ -541,13 +566,13 @@ class CreateTileAtlas {
TOTAL_TILES = TILES_IN_X * TILES_IN_X
val newAtlantes = Array(7) {
val newAtlantes = Array(8) {
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(atlasPrevernal, atlasVernal, atlasAestival, atlasSerotinal, atlasAutumnal, atlasHibernal, atlasGlow).forEachIndexed { index, pixmap ->
listOf(atlasPrevernal, atlasVernal, atlasAestival, atlasSerotinal, atlasAutumnal, atlasHibernal, atlasGlow, atlasEmissive).forEachIndexed { index, pixmap ->
/*
How it works:
@@ -579,6 +604,7 @@ class CreateTileAtlas {
atlasAutumnal = newAtlantes[4]
atlasHibernal = newAtlantes[5]
atlasGlow = newAtlantes[6]
atlasEmissive = newAtlantes[7]
App.setConfig("atlastexsize", newTexSize)