From 5eafe057f168a53ea109444761e89d7fc0ff993e Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Wed, 19 Mar 2025 21:20:56 +0100 Subject: [PATCH] Add NPC transparency for gamemaster lisibility --- .../campaign/player/CharacterPortrait.kt | 3 ++ .../campaign/player/CharacterRibbonFactory.kt | 2 ++ .../player/ribbon/CharacterRibbonViewModel.kt | 31 ++++++++++++++----- .../player/ribbon/npc/NpcRibbonViewModel.kt | 13 +++++++- .../ribbon/player/PlayerRibbonViewModel.kt | 13 +++++++- 5 files changed, 53 insertions(+), 9 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt index ad507ce..dc56554 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt @@ -37,6 +37,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.FilterQuality +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp @@ -65,6 +66,7 @@ data class CharacterPortraitUio( val portrait: String?, val name: String, val levelUp: Boolean, + val hideOverruled: Boolean, val enableDetail: Boolean, val stats: StatsDetail?, ) { @@ -90,6 +92,7 @@ fun CharacterPortrait( Box( modifier = modifier + .graphicsLayer { if (character.hideOverruled) this.alpha = 0.3f } .size(size = size) .clip(shape = MaterialTheme.lwa.shapes.portrait) .background(color = colorScheme.elevated.base1dp) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt index 8a86e74..d1f373e 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt @@ -15,6 +15,7 @@ class CharacterRibbonFactory( alterations: Map>, characterInstanceId: Campaign.CharacterInstance.Id, characterInstance: Campaign.CharacterInstance, + hideOverruled: Boolean, enableCharacterId: Boolean, enableCharacterSheet: Boolean, enableCharacterStats: Boolean, @@ -32,6 +33,7 @@ class CharacterRibbonFactory( portrait = alteredCharacterSheet.thumbnail, name = alteredCharacterSheet.name, levelUp = alteredCharacterSheet.shouldLevelUp, + hideOverruled = hideOverruled, enableDetail = enableCharacterSheet, stats = takeIf { enableCharacterStats }?.let { CharacterPortraitUio.StatsDetail( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt index 59024ea..3cff5b6 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt @@ -13,6 +13,7 @@ import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository +import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitRollUio import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterPortraitUio import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterRibbonFactory @@ -22,6 +23,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn @@ -39,9 +41,18 @@ abstract class CharacterRibbonViewModel( private val rolls = hashMapOf>() - abstract val Campaign.data: Map + abstract fun fetch( + campaign: Campaign, + settings: Settings, + ): Map + + abstract fun hideOverruled( + campaign: Campaign, + settings: Settings, + ): Boolean abstract val enableCharacterSheet: Boolean + abstract val enableCharacterStats: Boolean /** @@ -52,22 +63,28 @@ abstract class CharacterRibbonViewModel( * Then sort the result. */ @OptIn(ExperimentalCoroutinesApi::class) - val characters: StateFlow> = campaignRepository.campaignFlow - .flatMapLatest { campaign -> - when (campaign.data.isEmpty()) { + val characters: StateFlow> = combine( + settingsRepository.settingsFlow(), + campaignRepository.campaignFlow, + ) { settings, campaign -> campaign to settings } + .distinctUntilChanged() + .flatMapLatest { (campaign, settings) -> + val hideOverruled = hideOverruled(campaign, settings) + val data = fetch(campaign, settings) + when (data.isEmpty()) { true -> flowOf(emptyList()) else -> combine>( - flows = campaign.data.map { entry -> + flows = data.map { entry -> combine( characterRepository.characterDetailFlow(characterSheetId = entry.key.characterSheetId), alterationRepository.alterationsFlow(characterInstanceId = entry.key), - settingsRepository.settingsFlow(), - ) { sheet, alterations, settings -> + ) { sheet, alterations -> ribbonFactory.convertToPlayerPortraitUio( characterSheet = sheet, alterations = alterations, characterInstanceId = entry.key, characterInstance = entry.value, + hideOverruled = hideOverruled, enableCharacterId = settings.isGameMaster ?: false, enableCharacterSheet = enableCharacterSheet || settings.isGameMaster ?: false, enableCharacterStats = enableCharacterStats || settings.isGameMaster ?: false, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt index dd0315b..5dd62f0 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt @@ -5,6 +5,7 @@ import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository +import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterRibbonFactory import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonViewModel import com.pixelized.shared.lwa.model.campaign.Campaign @@ -24,8 +25,18 @@ class NpcRibbonViewModel( campaignRepository = campaignRepository, ribbonFactory = ribbonFactory, ) { - override val Campaign.data get() = if (options.showNpcs) npcs else emptyMap() + override fun fetch( + campaign: Campaign, + settings: Settings, + ): Map { + return if (campaign.options.showNpcs || settings.isGameMaster == true) campaign.npcs else emptyMap() + } + + override fun hideOverruled(campaign: Campaign, settings: Settings): Boolean { + return !campaign.options.showNpcs && settings.isGameMaster == true + } override val enableCharacterSheet = false + override val enableCharacterStats = false } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt index a0ee28e..36a41ed 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt @@ -5,6 +5,7 @@ import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository +import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.screen.campaign.player.CharacterRibbonFactory import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonViewModel import com.pixelized.shared.lwa.model.campaign.Campaign @@ -24,8 +25,18 @@ class PlayerRibbonViewModel( campaignRepository = campaignRepository, ribbonFactory = ribbonFactory, ) { - override val Campaign.data get() = if (options.showParty) characters else emptyMap() + override fun fetch( + campaign: Campaign, + settings: Settings, + ): Map { + return if (campaign.options.showParty) campaign.characters else emptyMap() + } + + override fun hideOverruled(campaign: Campaign, settings: Settings): Boolean { + return !campaign.options.showParty && settings.isGameMaster == true + } override val enableCharacterSheet = true + override val enableCharacterStats = true } \ No newline at end of file