forked from mirrors/cobblemon
Merge branch 'feat/animated-party-portraits' into 'main'
Add support for animated portraits in the party overlay See merge request cable-mc/cobblemon!1302
This commit is contained in:
@@ -8,22 +8,25 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawPosablePortrait
|
||||
import com.cobblemon.mod.common.api.text.darkGray
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.gui.portrait.FullyAnimatedPortraitDrawer
|
||||
import com.cobblemon.mod.common.client.gui.portrait.SelectedAnimatedPortraitDrawer
|
||||
import com.cobblemon.mod.common.client.gui.portrait.InanimatePortraitDrawer
|
||||
import com.cobblemon.mod.common.client.gui.portrait.PortraitStyle
|
||||
import com.cobblemon.mod.common.client.gui.toast.CobblemonToast
|
||||
import com.cobblemon.mod.common.client.keybind.boundKey
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.HidePartyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.renderScaledGuiItemIcon
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -55,7 +58,10 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
private val genderIconMale = cobblemonResource("textures/gui/party/party_gender_male.png")
|
||||
private val genderIconFemale = cobblemonResource("textures/gui/party/party_gender_female.png")
|
||||
private val portraitBackground = cobblemonResource("textures/gui/party/party_slot_portrait_background.png")
|
||||
val state = FloatingState()
|
||||
|
||||
private val inanimatePortraitDrawer = InanimatePortraitDrawer()
|
||||
private val selectedAnimatedPortraitDrawer = SelectedAnimatedPortraitDrawer()
|
||||
private val fullyAnimatedPortraitDrawer = FullyAnimatedPortraitDrawer()
|
||||
}
|
||||
|
||||
private val screenExemptions: List<Class<out Screen>> = listOf(
|
||||
@@ -84,6 +90,7 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
|
||||
override fun render(context: GuiGraphics, tickCounter: DeltaTracker) {
|
||||
val partialDeltaTicks = tickCounter.realtimeDeltaTicks
|
||||
|
||||
val minecraft = Minecraft.getInstance()
|
||||
|
||||
// Hiding if a Screen is open and not exempt
|
||||
@@ -153,15 +160,14 @@ class PartyOverlay : Gui(Minecraft.getInstance()) {
|
||||
0.0
|
||||
)
|
||||
|
||||
state.currentAspects = pokemon.aspects
|
||||
val portraitDrawer = when (Cobblemon.config.partyPortraitAnimations) {
|
||||
PortraitStyle.NEVER_ANIMATE -> inanimatePortraitDrawer
|
||||
PortraitStyle.ANIMATE_SELECTED -> selectedAnimatedPortraitDrawer
|
||||
PortraitStyle.ALWAYS_ANIMATE -> fullyAnimatedPortraitDrawer
|
||||
}
|
||||
|
||||
portraitDrawer.draw(pokemon, matrices, partialDeltaTicks, selectedSlot == index, index)
|
||||
|
||||
drawPosablePortrait(
|
||||
identifier = pokemon.species.resourceIdentifier,
|
||||
matrixStack = matrices,
|
||||
partialTicks = 0F, // partialDeltaTicks, //Before you get any funny ideas about party animated pokemon, make sure they each get their own state instead of sharing.
|
||||
contextScale = pokemon.form.baseScale,
|
||||
state = state
|
||||
)
|
||||
matrices.popPose()
|
||||
context.disableScissor()
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.drawPosablePortrait
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Base logic for a [PortraitDrawer] that animates a portrait based on conditions.
|
||||
*/
|
||||
abstract class AnimatedPortraitDrawer : PortraitDrawer {
|
||||
|
||||
private val state = FloatingState()
|
||||
|
||||
private val stateAtIndex = hashMapOf<Int, Pair<UUID, FloatingState>>()
|
||||
|
||||
override fun draw(pokemon: Pokemon, poseStack: PoseStack, partialTicks: Float, isSelected: Boolean, index: Int) {
|
||||
drawPosablePortrait(
|
||||
identifier = pokemon.species.resourceIdentifier,
|
||||
matrixStack = poseStack,
|
||||
partialTicks = this.ticksFor(pokemon, isSelected, partialTicks),
|
||||
contextScale = pokemon.form.baseScale,
|
||||
state = this.stateFor(pokemon, isSelected, index)
|
||||
)
|
||||
}
|
||||
|
||||
protected abstract fun shouldAnimate(pokemon: Pokemon, isSelected: Boolean): Boolean
|
||||
|
||||
protected open fun ticksFor(pokemon: Pokemon, isSelected: Boolean, partialTicks: Float): Float {
|
||||
return if (this.shouldAnimate(pokemon, isSelected)) partialTicks else 0F
|
||||
}
|
||||
|
||||
protected open fun stateFor(pokemon: Pokemon, isSelected: Boolean, index: Int): FloatingState {
|
||||
if (!this.shouldAnimate(pokemon, isSelected)) {
|
||||
return this.state
|
||||
}
|
||||
val state = this.stateAtIndex.getOrPut(index) { pokemon.uuid to this.createState(pokemon) }
|
||||
if (state.first != pokemon.uuid) {
|
||||
val newState = this.createState(pokemon)
|
||||
this.stateAtIndex[index] = pokemon.uuid to newState
|
||||
return newState
|
||||
}
|
||||
return state.second
|
||||
}
|
||||
|
||||
protected open fun createState(pokemon: Pokemon): FloatingState {
|
||||
val state = FloatingState()
|
||||
state.currentAspects = pokemon.aspects
|
||||
return state
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.client.GraphicsStatus
|
||||
|
||||
/**
|
||||
* Draws portraits if the Pokemon is not fainted.
|
||||
*
|
||||
* Meant for client with [GraphicsStatus.FABULOUS].
|
||||
*/
|
||||
class FullyAnimatedPortraitDrawer : AnimatedPortraitDrawer() {
|
||||
|
||||
override fun shouldAnimate(pokemon: Pokemon, isSelected: Boolean): Boolean {
|
||||
return !pokemon.isFainted()
|
||||
}
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.drawPosablePortrait
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.GraphicsStatus
|
||||
|
||||
/**
|
||||
* The simplest implementation, the Pokemon is drawn staying still.
|
||||
*
|
||||
* Meant for client with [GraphicsStatus.FAST].
|
||||
*/
|
||||
class InanimatePortraitDrawer : PortraitDrawer {
|
||||
|
||||
private val state = FloatingState()
|
||||
|
||||
override fun draw(pokemon: Pokemon, poseStack: PoseStack, partialTicks: Float, isSelected: Boolean, index: Int) {
|
||||
state.currentAspects = pokemon.aspects
|
||||
drawPosablePortrait(
|
||||
identifier = pokemon.species.resourceIdentifier,
|
||||
matrixStack = poseStack,
|
||||
partialTicks = 0F,
|
||||
contextScale = pokemon.form.baseScale,
|
||||
state = this.state
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
|
||||
/**
|
||||
* Responsible for drawing a Pokemon portrait.
|
||||
*
|
||||
* Keep in mind any scaling and handling of the [PoseStack] must be done on the implementations using this system.
|
||||
*/
|
||||
fun interface PortraitDrawer {
|
||||
|
||||
/**
|
||||
* Draws the portrait.
|
||||
*
|
||||
* @param pokemon The [Pokemon] being drawn.
|
||||
* @param poseStack The [PoseStack] being used.
|
||||
* @param partialTicks The partial ticks of the screen using this.
|
||||
* @param isSelected If the [pokemon] is considered in a selected state for example hovered or the current party member.
|
||||
* @param index The index of the [pokemon] in the screen using this.
|
||||
*/
|
||||
fun draw(
|
||||
pokemon: Pokemon,
|
||||
poseStack: PoseStack,
|
||||
partialTicks: Float,
|
||||
isSelected: Boolean,
|
||||
index: Int
|
||||
)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.mojang.serialization.Codec
|
||||
import net.minecraft.util.StringRepresentable
|
||||
|
||||
enum class PortraitStyle : StringRepresentable {
|
||||
|
||||
NEVER_ANIMATE,
|
||||
ANIMATE_SELECTED,
|
||||
ALWAYS_ANIMATE;
|
||||
|
||||
override fun getSerializedName(): String = this.name
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
val CODEC: Codec<PortraitStyle> = StringRepresentable.fromEnum(PortraitStyle::values)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.portrait
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.client.GraphicsStatus
|
||||
|
||||
/**
|
||||
* Draws portraits if the Pokemon is not fainted and selected.
|
||||
*
|
||||
* Meant for client with [GraphicsStatus.FANCY].
|
||||
*/
|
||||
class SelectedAnimatedPortraitDrawer : AnimatedPortraitDrawer() {
|
||||
|
||||
override fun shouldAnimate(pokemon: Pokemon, isSelected: Boolean): Boolean {
|
||||
return !pokemon.isFainted() && isSelected
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.config
|
||||
import com.cobblemon.mod.common.api.drop.ItemDropMethod
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.client.gui.portrait.PortraitStyle
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.pokeball.catching.calculators.CobblemonCaptureCalculator
|
||||
import com.cobblemon.mod.common.util.adapters.CaptureCalculatorAdapter
|
||||
@@ -255,6 +256,9 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Interface, lang = "summary_pokemon_follow_cursor")
|
||||
var summaryPokemonFollowCursor = true
|
||||
|
||||
@CobblemonConfigField(Category.Interface, lang = "party_portrait_animations")
|
||||
var partyPortraitAnimations = PortraitStyle.NEVER_ANIMATE
|
||||
|
||||
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys")
|
||||
var enableDebugKeys = false
|
||||
|
||||
|
||||
@@ -1715,6 +1715,13 @@
|
||||
"cobblemon.config.ui.hide_unimplemented_pokemon_in_the_pokedex.tooltip": "Whether to hide unimplemented Pokémon from the Pokédex.",
|
||||
"cobblemon.config.ui.summary_pokemon_follow_cursor": "Make Pokémon Follow Cursor",
|
||||
"cobblemon.config.ui.summary_pokemon_follow_cursor.tooltip": "Whether or not Pokémon should follow the mouse cursor with their heads in the Summary screen.",
|
||||
"cobblemon.config.ui.party_portrait_animations": "Party Portrait Animations",
|
||||
"cobblemon.config.ui.party_portrait_animations.never_animate": "Never Animate",
|
||||
"cobblemon.config.ui.party_portrait_animations.never_animate.tooltip": "No portraits animate",
|
||||
"cobblemon.config.ui.party_portrait_animations.animate_selected": "Animate Selected",
|
||||
"cobblemon.config.ui.party_portrait_animations.animate_selected.tooltip": "Selected Pokémon animates unless fainted",
|
||||
"cobblemon.config.ui.party_portrait_animations.always_animate": "Always animate",
|
||||
"cobblemon.config.ui.party_portrait_animations.always_animate.tooltip": "Entire party animates unless fainted",
|
||||
"cobblemon.config.ui.enable_debug_keys": "Enable Debug Keys",
|
||||
"cobblemon.config.ui.enable_debug_keys.tooltip": "Enables additional commands and chat logging to assist with implementing Pokémon (see the wiki for a list of commands).",
|
||||
|
||||
|
||||
Reference in New Issue
Block a user