Add NPC transparency for gamemaster lisibility

This commit is contained in:
Thomas Andres Gomez 2025-03-19 21:20:56 +01:00
parent 49723892fc
commit 5eafe057f1
5 changed files with 53 additions and 9 deletions

View file

@ -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)

View file

@ -15,6 +15,7 @@ class CharacterRibbonFactory(
alterations: Map<String, List<FieldAlteration>>,
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(

View file

@ -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<CharacterInstance.Id, MutableState<CharacterPortraitRollUio?>>()
abstract val Campaign.data: Map<CharacterInstance.Id, CharacterInstance>
abstract fun fetch(
campaign: Campaign,
settings: Settings,
): Map<CharacterInstance.Id, CharacterInstance>
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<List<CharacterPortraitUio>> = campaignRepository.campaignFlow
.flatMapLatest { campaign ->
when (campaign.data.isEmpty()) {
val characters: StateFlow<List<CharacterPortraitUio>> = 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<CharacterPortraitUio?, List<CharacterPortraitUio>>(
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,

View file

@ -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<Campaign.CharacterInstance.Id, Campaign.CharacterInstance> {
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
}

View file

@ -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<Campaign.CharacterInstance.Id, Campaign.CharacterInstance> {
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
}