jukebox ui wip

This commit is contained in:
minjaesong
2024-01-13 17:20:10 +09:00
parent fb9640e615
commit 1b74ee8efc
11 changed files with 226 additions and 75 deletions

View File

@@ -18,11 +18,13 @@ import net.torvald.terrarum.audio.dsp.NullFilter
import net.torvald.terrarum.blendNormalStraightAlpha
import net.torvald.terrarum.blendScreen
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.MusicContainer
import net.torvald.terrarum.modulebasegame.TerrarumMusicGovernor
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.modulebasegame.ui.UIJukebox
import net.torvald.terrarum.modulebasegame.ui.UIJukebox.Companion.SLOT_SIZE
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
@@ -51,7 +53,11 @@ class FixtureJukebox : Electric {
@Transient private val backLamp: SheetSpriteAnimation
internal val discInventory = arrayOfNulls<ItemID>(SLOT_SIZE)
init {
(mainUI as UIJukebox).parent = this
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/jukebox.tga")
density = 1400.0

View File

@@ -12,6 +12,8 @@ import java.util.UUID
*/
open class ItemFileRef(originalID: ItemID) : GameItem(originalID) {
var author = ""
open var uuid: UUID = UUID(0, 0)
/**

View File

@@ -7,6 +7,11 @@ import net.torvald.terrarum.gameitems.ItemID
* Created by minjaesong on 2024-01-13.
*/
class MusicDisc01(originalID: ItemID) : ItemFileRef(originalID) {
init {
name = "Thousands of Shards"
author = "Orstphone"
}
override var refPath = "audio/music/discs/01 Thousands of Shards.ogg"
override var refModuleName = "basegame"
override val isDynamic = false

View File

@@ -17,6 +17,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.listGap
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemCatBar.Companion.FILTER_CAT_ALL
import net.torvald.unicode.getKeycapPC
import kotlin.math.ceil
import kotlin.math.max
@@ -87,7 +88,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
override fun getPlayerInventory(): FixtureInventory = INGAME.actorNowPlaying!!.inventory
private var halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2
private val halfSlotOffset = (UIItemInventoryElemSimple.height + listGap) / 2
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + listGap - halfSlotOffset
private val thisOffsetX2 = thisOffsetX + (listGap + UIItemInventoryElemWide.height) * 7
@@ -100,8 +101,6 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
private var recipeClicked: CraftingCodex.CraftingRecipe? = null
private val catAll = arrayOf(CAT_ALL)
private val controlHelp: String
get() = if (App.environment == RunningEnvironment.PC)
"${getKeycapPC(ControlPresets.getKey("control_key_inventory"))} ${Lang["GAME_ACTION_CLOSE"]}"
@@ -181,9 +180,9 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
it.removeFromForceHighlightList(oldSelectedItems)
filterPlayerListUsing(recipeClicked)
it.addToForceHighlightList(selectedItems)
it.rebuild(catAll)
it.rebuild(FILTER_CAT_ALL)
}
_getItemListIngredients().rebuild(catAll)
_getItemListIngredients().rebuild(FILTER_CAT_ALL)
// highlighting CraftingCandidateButton by searching for the buttons that has the recipe
_getItemListCraftables().let {
@@ -254,7 +253,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
_getItemListPlayer().addToForceHighlightList(selectedItems)
_getItemListPlayer().itemPage = 0
filterPlayerListUsing(recipeClicked)
_getItemListIngredients().rebuild(catAll)
_getItemListIngredients().rebuild(FILTER_CAT_ALL)
highlightCraftingCandidateButton(recipe)
@@ -270,9 +269,9 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
spinnerCraftCount = UIItemSpinner(this, thisOffsetX + 1, craftButtonsY, 1, 1, App.getConfigInt("basegame:gameplay_max_crafting"), 1, buttonWidth, numberToTextFunction = {"×\u200A${it.toInt()}"})
spinnerCraftCount.selectionChangeListener = {
itemListIngredients.numberMultiplier = it.toLong()
itemListIngredients.rebuild(catAll)
itemListIngredients.rebuild(FILTER_CAT_ALL)
itemListCraftable.numberMultiplier = it.toLong()
itemListCraftable.rebuild(catAll)
itemListCraftable.rebuild(FILTER_CAT_ALL)
refreshCraftButtonStatus()
}
@@ -293,8 +292,8 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
// reset selection status after a crafting to hide the possible artefact where no-longer-craftable items are still displayed due to ingredient depletion
resetUI() // also clears forcehighlightlist
playerThings.rebuild(catAll)
itemListCraftable.rebuild(catAll)
playerThings.rebuild(FILTER_CAT_ALL)
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
} }
refreshCraftButtonStatus()
@@ -314,7 +313,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
private fun filterPlayerListUsing(recipe: CraftingCodex.CraftingRecipe?) {
if (recipe == null)
playerThings.rebuild(catAll)
playerThings.rebuild(FILTER_CAT_ALL)
else {
val items = recipe.ingredients.flatMap {
getItemCandidatesForIngredient(getPlayerInventory(), it).map { it.itm }
@@ -353,12 +352,12 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
it.remove(old.itm, amount)
it.add(new, amount)
}
itemListIngredients.rebuild(catAll)
itemListIngredients.rebuild(FILTER_CAT_ALL)
}
private fun highlightCraftingCandidateButton(recipe: CraftingCodex.CraftingRecipe?) { // a proxy function
itemListCraftable.highlightRecipe(recipe)
itemListCraftable.rebuild(catAll)
itemListCraftable.rebuild(FILTER_CAT_ALL)
}
/**
@@ -386,7 +385,7 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
highlightCraftingCandidateButton(null)
ingredients.clear()
playerThings.removeFromForceHighlightList(oldSelectedItems)
itemListIngredients.rebuild(catAll)
itemListIngredients.rebuild(FILTER_CAT_ALL)
refreshCraftButtonStatus()
}
@@ -418,8 +417,8 @@ class UICrafting(val full: UIInventoryFull) : UICanvas(), HasInventory {
private fun itemListUpdate() {
// let itemlists be sorted
itemListCraftable.rebuild(catAll)
playerThings.rebuild(catAll)
itemListCraftable.rebuild(FILTER_CAT_ALL)
playerThings.rebuild(FILTER_CAT_ALL)
encumbrancePerc = getPlayerInventory().let {
it.capacity.toFloat() / it.maxCapacity
}

View File

@@ -3,6 +3,10 @@ package net.torvald.terrarum.modulebasegame.ui
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.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
@@ -14,6 +18,12 @@ class UIJukebox : UICanvas(
toggleButtonLiteral = "control_gamepad_start",
) {
lateinit var parent: FixtureJukebox
companion object {
const val SLOT_SIZE = 8
}
init {
CommonResourcePool.addToLoadingList("basegame-gui-jukebox_caticons") {
TextureRegionPack(ModMgr.getGdxFile("basegame", "gui/jukebox_caticons.tga"), 20, 20)
@@ -30,11 +40,14 @@ class UIJukebox : UICanvas(
intArrayOf(0, 1),
emptyList(),
listOf({ "" }, { "" })
)
).also {
it.catBar.selectionChangeListener = { old, new ->
transitionPanel.requestTransition(new)
}
}
private val transitionalSonglistPanel = UIJukeboxSonglistPanel(this)
private val transitionalDiscInventory = UIJukeboxInventory(this)
private val transitionPanel = UIItemHorizontalFadeSlide(
this,
0, 0, width, height, 0f,
@@ -42,6 +55,9 @@ class UIJukebox : UICanvas(
listOf(transitionalDiscInventory)
)
internal val discInventory: Array<ItemID?>
get() = parent.discInventory
init {
addUIitem(catbar)
addUIitem(transitionPanel)

View File

@@ -1,68 +1,85 @@
package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.App
import net.torvald.terrarum.*
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.InventoryPair
import net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef
import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemInventoryElemSimple
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.defaultInventoryCellTheme
import net.torvald.terrarum.modulebasegame.ui.UIJukebox.Companion.SLOT_SIZE
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemInventoryElemWide
/**
* Created by minjaesong on 2024-01-13.
*/
class UIJukeboxInventory(val parent: UICanvas) : UICanvas(), HasInventory {
class UIJukeboxInventory(val parent: UIJukebox) : UICanvas() {
override var width = Toolkit.drawWidth
override var height = App.scr.height
private val negotiator = object : InventoryTransactionNegotiator() {
override fun accept(player: FixtureInventory, fixture: FixtureInventory, item: GameItem, amount: Long) {
if (item is ItemFileRef && item.mediumIdentifier == "music_disc") {
player.remove(item, amount)
fixture.add(item, amount)
}
}
override fun refund(fixture: FixtureInventory, player: FixtureInventory, item: GameItem, amount: Long) {
fixture.remove(item, amount)
player.add(item, amount)
}
}
private val thisInventory = FixtureInventory()
private var halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) / 2
private val halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) / 2
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap - halfSlotOffset
private val thisOffsetY = UIInventoryFull.INVENTORY_CELLS_OFFSET_Y()
private val fixtureInventoryCells = (0..7).map {
UIItemInventoryElemWide(this,
thisOffsetX, thisOffsetY + (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) * it,
private var currentFreeSlot = 0
private val playerInventory: ActorInventory
get() = INGAME.actorNowPlaying!!.inventory
private val fixtureDiscCell: List<UIItemJukeboxSonglist> = (0 until SLOT_SIZE).map { index ->
UIItemJukeboxSonglist(this,
thisOffsetX, thisOffsetY + (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) * index,
6 * UIItemInventoryElemSimple.height + 5 * UIItemInventoryItemGrid.listGap,
keyDownFun = { _, _, _, _, _ -> Unit },
touchDownFun = { gameItem, amount, button, _, _ ->
if (button == App.getConfigInt("config_mouseprimary")) {
touchDownFun = { gameItem, amount, mouseButton, _, _ ->
if (mouseButton == App.getConfigInt("config_mouseprimary")) {
if (gameItem != null) {
negotiator.refund(getFixtureInventory(), getPlayerInventory(), gameItem, amount)
parent.discInventory[index] = null
playerInventory.add(gameItem, 1)
// shift discs
for (i in index + 1 until SLOT_SIZE) {
parent.discInventory[i - 1] = parent.discInventory[i]
}
parent.discInventory[SLOT_SIZE - 1] = null
}
}
}
},
)
}
private val playerInventoryUI = UITemplateHalfInventory(this, false)
private val playerInventoryUI = UITemplateHalfInventory(this, false).also {
it.itemListTouchDownFun = { gameItem, _, _, _, _ ->
if (currentFreeSlot < SLOT_SIZE) {
fixtureDiscCell[currentFreeSlot].title = (gameItem as ItemFileRef).name
fixtureDiscCell[currentFreeSlot].artist = (gameItem as ItemFileRef).author
currentFreeSlot += 1
}
}
}
init {
fixtureInventoryCells.forEach {
addUIitem(it)
fixtureDiscCell.forEach { thisButton ->
addUIitem(thisButton)
}
addUIitem(playerInventoryUI)
}
private val playerInventoryFilterFun = { (itm, _): InventoryPair ->
ItemCodex[itm].let {
it is ItemFileRef && it.mediumIdentifier == "music_disc"
}
}
override fun show() {
super.show()
playerInventoryUI.rebuild(playerInventoryFilterFun)
}
override fun updateUI(delta: Float) {
uiItems.forEach { it.update(delta) }
}
@@ -74,27 +91,58 @@ class UIJukeboxInventory(val parent: UICanvas) : UICanvas(), HasInventory {
override fun dispose() {
}
override fun getNegotiator() = negotiator
override fun getFixtureInventory(): FixtureInventory {
TODO()
}
override fun getPlayerInventory(): FixtureInventory {
TODO()
}
}
class UIJukeboxSonglistPanel(val parent: UICanvas) : UICanvas() {
class UIJukeboxSonglistPanel(val parent: UIJukebox) : UICanvas() {
override var width = Toolkit.drawWidth
override var height = App.scr.height
private val halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) / 2
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap - halfSlotOffset
private val thisOffsetX2 = thisOffsetX + (UIItemInventoryItemGrid.listGap + UIItemInventoryElemWide.height) * 7
private val thisOffsetY = UIInventoryFull.INVENTORY_CELLS_OFFSET_Y()
private val songButtonColourTheme = defaultInventoryCellTheme.copy(
cellHighlightNormalCol = Color(0xfec753c8.toInt()),
cellBackgroundCol = Color(0x704c20c8.toInt())
)
private val jukeboxPlayButtons = (0 until SLOT_SIZE).map { index ->
UIItemJukeboxSonglist(this,
if (index % 2 == 0) thisOffsetX else thisOffsetX2,
thisOffsetY + (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) * index.shr(1),
6 * UIItemInventoryElemSimple.height + 5 * UIItemInventoryItemGrid.listGap,
colourTheme = songButtonColourTheme,
keyDownFun = { _, _, _, _, _ -> Unit },
touchDownFun = { gameItem, amount, button, _, _ ->
if (button == App.getConfigInt("config_mouseprimary")) {
}
}
)
}
fun rebuild() {
jukeboxPlayButtons.forEachIndexed { index, button ->
parent.discInventory[index].let {
val item = ItemCodex[it] as? ItemFileRef
button.title = item?.name ?: ""
button.artist = item?.author ?: ""
}
}
}
init {
jukeboxPlayButtons.forEach {
addUIitem(it)
}
}
override fun updateUI(delta: Float) {
uiItems.forEach { it.update(delta) }
@@ -110,3 +158,87 @@ class UIJukeboxSonglistPanel(val parent: UICanvas) : UICanvas() {
}
class UIItemJukeboxSonglist(
parentUI: UICanvas,
initialX: Int,
initialY: Int,
override val width: Int,
var title: String = "",
var artist: String = "",
var keyDownFun: (GameItem?, Long, Int, Any?, UIItemJukeboxSonglist) -> Unit, // Item, Amount, Keycode, extra info, self
var touchDownFun: (GameItem?, Long, Int, Any?, UIItemJukeboxSonglist) -> Unit, // Item, Amount, Button, extra info, self
var colourTheme: InventoryCellColourTheme = UIItemInventoryCellCommonRes.defaultInventoryCellTheme
) : UIItem(parentUI, initialX, initialY) {
companion object {
val height = 48
}
override val height = Companion.height
private val textOffsetX = 50f
private val textOffsetY = 8f
/** Custom highlight rule to highlight tihs button to primary accent colour (blue by default).
* Set to `null` to use default rule:
*
* "`equippedSlot` defined and set to `highlightEquippedItem`" or "`forceHighlighted`" */
var customHighlightRuleMain: ((UIItemJukeboxSonglist) -> Boolean)? = null
/** Custom highlight rule to highlight this button to secondary accent colour (yellow by default). Set to `null` to use default rule (which does nothing). */
var customHighlightRule2: ((UIItemJukeboxSonglist) -> Boolean)? = null
var forceHighlighted = false
private var highlightToMainCol = false
private var highlightToSubCol = false
override fun render(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
blendNormalStraightAlpha(batch)
highlightToMainCol = customHighlightRuleMain?.invoke(this) ?: false || forceHighlighted
highlightToSubCol = customHighlightRule2?.invoke(this) ?: false
// cell background
batch.color = colourTheme.cellBackgroundCol
Toolkit.fillArea(batch, posX, posY, width, height)
// cell border
batch.color = if (highlightToMainCol) colourTheme.cellHighlightMainCol
else if (highlightToSubCol) colourTheme.cellHighlightSubCol
else if (mouseUp && title.isNotEmpty()) colourTheme.cellHighlightMouseUpCol
else colourTheme.cellHighlightNormalCol
Toolkit.drawBoxBorder(batch, posX, posY, width, height)
if (title.isNotEmpty()) {
blendNormalStraightAlpha(batch)
// if mouse is over, text lights up
// highlight item name and count (blocks/walls) if the item is equipped
batch.color =
if (highlightToMainCol) colourTheme.textHighlightMainCol
else if (highlightToSubCol) colourTheme.textHighlightSubCol
else if (mouseUp && title.isNotEmpty()) colourTheme.textHighlightMouseUpCol
else colourTheme.textHighlightNormalCol
// draw title
App.fontGame.draw(batch, title, posX + textOffsetX, posY + textOffsetY)
// draw artist
App.fontGame.draw(batch, artist, posX + textOffsetX, posY + textOffsetY + 24f)
}
// see IFs above?
batch.color = Color.WHITE
}
override fun dispose() {
}
}

View File

@@ -51,7 +51,7 @@ internal class UIStorageChest : UICanvas(
private var encumbrancePerc = 0f
private var isEncumbered = false
private var halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap * 2) / 2
private val halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap * 2) / 2
init {
catBar = UIItemCatBar(

View File

@@ -27,7 +27,7 @@ class UITemplateHalfInventory(
val itemList: UIItemInventoryItemGrid
private var halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) / 2
private val halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap) / 2
private val thisOffsetX = UIInventoryFull.INVENTORY_CELLS_OFFSET_X() + UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap - halfSlotOffset
private val thisOffsetX2 = thisOffsetX + (UIItemInventoryItemGrid.listGap + UIItemInventoryElemWide.height) * 7
private val thisOffsetY = UIInventoryFull.INVENTORY_CELLS_OFFSET_Y()

View File

@@ -44,7 +44,7 @@ class UIWorldPortalCargo(val full: UIWorldPortal) : UICanvas(), HasInventory {
private var encumbrancePerc = 0f
private var isEncumbered = false
private var halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap * 2) / 2
private val halfSlotOffset = (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap * 2) / 2
init {
catBar = UIItemCatBar(

View File

@@ -28,6 +28,7 @@ class UIItemCatBar(
companion object {
const val CAT_ALL = "__all__"
val FILTER_CAT_ALL = arrayOf(CAT_ALL)
}

View File

@@ -69,16 +69,6 @@ class UIItemInventoryElemWide(
private var highlightToMainCol = false
private var highlightToSubCol = false
var cellHighlightMainCol = Toolkit.Theme.COL_SELECTED
var cellHighlightSubCol = Toolkit.Theme.COL_LIST_DEFAULT
var cellHighlightMouseUpCol = Toolkit.Theme.COL_MOUSE_UP
var cellHighlightNormalCol = Toolkit.Theme.COL_INVENTORY_CELL_BORDER
var textHighlightMainCol = Toolkit.Theme.COL_SELECTED
var textHighlightSubCol = Color.WHITE
var textHighlightMouseUpCol = Toolkit.Theme.COL_MOUSE_UP
var textHighlightNormalCol = Color.WHITE
override fun render(frameDelta: Float, batch: SpriteBatch, camera: OrthographicCamera) {
blendNormalStraightAlpha(batch)