From a973d33e02cd13a0d658958c4b4e85fc7d063fb3 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sun, 14 Jan 2024 22:16:19 +0900 Subject: [PATCH] randomised music disc sprite --- .../basegame/items/record_sprite_base.tga | 3 + .../torvald/terrarum/audio/AudioProcessBuf.kt | 2 +- .../modulebasegame/gameitems/ItemFileRef.kt | 1 + .../modulebasegame/gameitems/MusicDisc.kt | 91 ++++++++++++++++++- .../terrarum/modulebasegame/ui/UIJukebox.kt | 19 ++++ 5 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 assets/mods/basegame/items/record_sprite_base.tga diff --git a/assets/mods/basegame/items/record_sprite_base.tga b/assets/mods/basegame/items/record_sprite_base.tga new file mode 100644 index 000000000..4bd0269d8 --- /dev/null +++ b/assets/mods/basegame/items/record_sprite_base.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af4e55a0d9bf946b1d9ca3e0c55363cead522199ed5635f463ca9d2cb1847765 +size 1042 diff --git a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt index 7af03960d..9c2e6f6b0 100644 --- a/src/net/torvald/terrarum/audio/AudioProcessBuf.kt +++ b/src/net/torvald/terrarum/audio/AudioProcessBuf.kt @@ -35,7 +35,7 @@ class AudioProcessBuf(val inputSamplingRate: Int, val audioReadFun: (ByteArray) get() = inputSamplingRate * playbackSpeed private val doResample - get() = inputSamplingRate == SAMPLING_RATE && (playbackSpeed - 1f).absoluteValue < (1f / 1024f) + get() = !(inputSamplingRate == SAMPLING_RATE && (playbackSpeed - 1f).absoluteValue < (1f / 1024f)) companion object { private val epsilon: Double = Epsilon.E diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemFileRef.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemFileRef.kt index 03b815f73..e1ab97eb2 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemFileRef.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemFileRef.kt @@ -16,6 +16,7 @@ import java.util.UUID open class ItemFileRef(originalID: ItemID) : GameItem(originalID) { var author = "" + var collection = "" open var uuid: UUID = UUID(0, 0) diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/MusicDisc.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/MusicDisc.kt index e6e6d49b7..f07fe36fe 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/MusicDisc.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/MusicDisc.kt @@ -1,14 +1,26 @@ package net.torvald.terrarum.modulebasegame.gameitems import com.badlogic.gdx.files.FileHandle +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.Pixmap +import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.g2d.TextureRegion +import net.torvald.colourutil.HUSLColorConverter +import net.torvald.colourutil.OKLCh +import net.torvald.random.HQRNG +import net.torvald.random.XXHash32 +import net.torvald.random.XXHash64 +import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.ModMgr import net.torvald.terrarum.gameitems.ItemID +import net.torvald.terrarum.savegame.toHex import net.torvald.terrarum.utils.JsonFetcher +import net.torvald.terrarum.worlddrawer.toRGBA /** * Created by minjaesong on 2024-01-13. */ -data class MusicDiscMetadata(val title: String, val author: String) +data class MusicDiscMetadata(val title: String, val author: String, val album: String) object MusicDiscHelper { fun getMetadata(musicFile: FileHandle): MusicDiscMetadata { @@ -18,8 +30,9 @@ object MusicDiscHelper { val artist = propForThisFile.get("artist").asString() val title = propForThisFile.get("title").asString() + val album = propForThisFile.get("album").asString() - return MusicDiscMetadata(title, artist) + return MusicDiscMetadata(title, artist, album) } } @@ -34,6 +47,80 @@ open class MusicDiscPrototype(originalID: ItemID, module: String, path: String) val meta = MusicDiscHelper.getMetadata(getAsGdxFile()) name = meta.title author = meta.author + collection = meta.album + } + + @Transient override val itemImage: TextureRegion = generateSprite() + + /** + * Reads a channel-wise black and white image and tints it using HSLuv colour space + */ + private fun generateSprite(): TextureRegion { + val authorHash = XXHash64.hash(author.encodeToByteArray(), 54) + val albumHash = XXHash64.hash(collection.encodeToByteArray(), 32) + val nameHash = XXHash64.hash(name.encodeToByteArray(), 10) + + val authorRand = HQRNG(authorHash) + val albumRand = HQRNG(albumHash) + val nameRand = HQRNG(nameHash) + + val discColour = floatArrayOf( + albumRand.nextFloat() * 360f, + albumRand.nextFloat() * 70f + 10f, + albumRand.nextFloat() * 40f + 5f, + ) // HSLuv + + val labelColour = floatArrayOf( + nameRand.nextFloat() * 360f, + nameRand.nextFloat() * 20f + 75f, + nameRand.nextFloat() * 30f + 50f + ) // HSLuv + + val pixmap = Pixmap(ModMgr.getGdxFile("basegame", "items/record_sprite_base.tga")) + + // tint the pixmap + for (y in 0 until pixmap.height) { + for (x in 0 until pixmap.width) { + val pixel = pixmap.getPixel(x, y) // RGBA + + if (pixel and 0xFF == 0xFF) { + // red part + if (pixel and 0xFF000000.toInt() != 0) { + val b = pixel.ushr(24).and(255).toFloat() / 255f + + val B = discColour.copyOf().also { + it[2] *= b + } + + val outCol = HUSLColorConverter.hsluvToRgb(B).let { + Color(it[0], it[1], it[2], 1f) + } + + pixmap.drawPixel(x, y, outCol.toRGBA()) + } + // green part + else if (pixel and 0x00FF0000.toInt() != 0) { + val b = pixel.ushr(16).and(255).toFloat() / 255f + + val B = labelColour.copyOf().also { + it[2] *= b + } + + val outCol = HUSLColorConverter.hsluvToRgb(B).let { + Color(it[0], it[1], it[2], 1f) + } + + pixmap.drawPixel(x, y, outCol.toRGBA()) + } + + } + } + } + + val ret = TextureRegion(Texture(pixmap)) + pixmap.dispose() + + return ret } } diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UIJukebox.kt b/src/net/torvald/terrarum/modulebasegame/ui/UIJukebox.kt index 4adec6aa1..7a82d59e3 100644 --- a/src/net/torvald/terrarum/modulebasegame/ui/UIJukebox.kt +++ b/src/net/torvald/terrarum/modulebasegame/ui/UIJukebox.kt @@ -4,11 +4,13 @@ import com.badlogic.gdx.graphics.OrthographicCamera import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.terrarum.* import net.torvald.terrarum.gameitems.ItemID +import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory import net.torvald.terrarum.modulebasegame.gameactors.FixtureJukebox import net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef import net.torvald.terrarum.ui.* import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack +import net.torvald.unicode.getKeycapPC /** * Created by minjaesong on 2024-01-13. @@ -46,6 +48,14 @@ class UIJukebox : UICanvas( } } + + private val controlHelp: String + get() = if (App.environment == RunningEnvironment.PC) + "${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}" + else + "${App.gamepadLabelStart} ${Lang["GAME_ACTION_CLOSE"]} " + + private val transitionalSonglistPanel = UIJukeboxSonglistPanel(this) private val transitionalDiscInventory = UIJukeboxInventory(this) private val transitionPanel = UIItemHorizontalFadeSlide( @@ -85,8 +95,17 @@ class UIJukebox : UICanvas( override fun renderUI(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) { UIInventoryFull.drawBackground(batch, 1f) uiItems.forEach { it.render(frameDelta, batch, camera) } + + val controlHintXPos = thisOffsetX + 2f + App.fontGame.draw(batch, controlHelp, controlHintXPos, yEnd - 20) } + + private val halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) / 2 + private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap - halfSlotOffset + private val yEnd = -UIInventoryFull.YPOS_CORRECTION + (App.scr.height + UIInventoryFull.internalHeight).div(2).toFloat() + + override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean { if (!openingClickLatched) { return super.touchDown(screenX, screenY, pointer, button)