Add free dice throw for the GameMaster.
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
BIN
composeApp/src/commonMain/composeResources/drawable/icon_d4.webp
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
composeApp/src/commonMain/composeResources/drawable/icon_d6.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
composeApp/src/commonMain/composeResources/drawable/icon_d8.webp
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
|
|
@ -57,7 +57,6 @@
|
|||
<string name="roll_page__criticality_special__label">Spécial</string>
|
||||
<string name="roll_page__criticality_critical__label">Critique</string>
|
||||
|
||||
<string name="resources__content_descriptions">Ressources</string>
|
||||
<string name="resources__virtual_table__title">Table de jeu</string>
|
||||
<string name="resources__rules__title">Règles de jeu</string>
|
||||
<string name="resources__map_title">Carte du monde</string>
|
||||
|
|
|
|||
|
|
@ -13,13 +13,14 @@ import androidx.compose.material.Text
|
|||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.material.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.LocalWindowController
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
|
|
@ -34,12 +35,17 @@ import lwacharactersheet.composeapp.generated.resources.ic_link_24dp
|
|||
import lwacharactersheet.composeapp.generated.resources.ic_settings_24dp
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_wifi_24dp
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_wifi_off_24dp
|
||||
import lwacharactersheet.composeapp.generated.resources.resources__content_descriptions
|
||||
import lwacharactersheet.composeapp.generated.resources.settings__title
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
||||
@Stable
|
||||
data class MenuState(
|
||||
val isResourcesMenuOpen: MutableState<Boolean> = mutableStateOf(false),
|
||||
val isNetworkMenuOpen: MutableState<Boolean> = mutableStateOf(false),
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun CampaignToolbar(
|
||||
viewModel: CampaignToolbarViewModel = koinViewModel(),
|
||||
|
|
@ -47,8 +53,7 @@ fun CampaignToolbar(
|
|||
val windows = LocalWindowController.current
|
||||
val screen = LocalScreenController.current
|
||||
|
||||
val isResourcesMenuOpen = remember { mutableStateOf(false) }
|
||||
val isNetworkMenuOpen = remember { mutableStateOf(false) }
|
||||
val menuState = remember { MenuState() }
|
||||
|
||||
val title = viewModel.title.collectAsState()
|
||||
val status = viewModel.status.collectAsState()
|
||||
|
|
@ -58,25 +63,24 @@ fun CampaignToolbar(
|
|||
title = title,
|
||||
status = status,
|
||||
isAdmin = isAdmin,
|
||||
isNetworkMenuOpen = isNetworkMenuOpen,
|
||||
isResourcesMenuOpen = isResourcesMenuOpen,
|
||||
state = menuState,
|
||||
onAdmin = {
|
||||
windows.navigateToGameMasterWindow()
|
||||
},
|
||||
onNetwork = {
|
||||
isNetworkMenuOpen.value = true
|
||||
menuState.isNetworkMenuOpen.value = true
|
||||
},
|
||||
onResources = {
|
||||
isResourcesMenuOpen.value = true
|
||||
menuState.isResourcesMenuOpen.value = true
|
||||
},
|
||||
onSettings = {
|
||||
screen.navigateToSettings()
|
||||
},
|
||||
onDismissNetworkMenu = {
|
||||
isNetworkMenuOpen.value = false
|
||||
menuState.isNetworkMenuOpen.value = false
|
||||
},
|
||||
onDismissResourcesMenu = {
|
||||
isResourcesMenuOpen.value = false
|
||||
menuState.isResourcesMenuOpen.value = false
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -87,8 +91,7 @@ private fun CampaignToolbarContent(
|
|||
title: State<String>,
|
||||
status: State<NetworkRepository.Status>,
|
||||
isAdmin: State<Boolean>,
|
||||
isNetworkMenuOpen: State<Boolean>,
|
||||
isResourcesMenuOpen: State<Boolean>,
|
||||
state: MenuState,
|
||||
onAdmin: () -> Unit,
|
||||
onNetwork: () -> Unit,
|
||||
onResources: () -> Unit,
|
||||
|
|
@ -124,7 +127,16 @@ private fun CampaignToolbarContent(
|
|||
Icon(
|
||||
painter = painterResource(Res.drawable.ic_link_24dp),
|
||||
tint = MaterialTheme.colors.primary,
|
||||
contentDescription = stringResource(Res.string.resources__content_descriptions),
|
||||
contentDescription = null,
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = state.isResourcesMenuOpen.value,
|
||||
onDismissRequest = onDismissResourcesMenu,
|
||||
content = {
|
||||
ResourcesMenu(
|
||||
modifier = Modifier.width(384.dp + 96.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
|
|
@ -143,6 +155,15 @@ private fun CampaignToolbarContent(
|
|||
},
|
||||
contentDescription = null,
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = state.isNetworkMenuOpen.value,
|
||||
onDismissRequest = onDismissNetworkMenu,
|
||||
content = {
|
||||
NetworkMenu(
|
||||
modifier = Modifier.size(384.dp + 96.dp, 240.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
onClick = onSettings,
|
||||
|
|
@ -153,26 +174,6 @@ private fun CampaignToolbarContent(
|
|||
contentDescription = stringResource(Res.string.settings__title),
|
||||
)
|
||||
}
|
||||
DropdownMenu(
|
||||
offset = remember { DpOffset(x = -(48.dp + 8.dp), y = 8.dp) },
|
||||
expanded = isNetworkMenuOpen.value,
|
||||
onDismissRequest = onDismissNetworkMenu,
|
||||
content = {
|
||||
NetworkMenu(
|
||||
modifier = Modifier.size(384.dp + 96.dp, 240.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
DropdownMenu(
|
||||
offset = remember { DpOffset(x = -(48.dp + 8.dp), y = 8.dp) },
|
||||
expanded = isResourcesMenuOpen.value,
|
||||
onDismissRequest = onDismissResourcesMenu,
|
||||
content = {
|
||||
ResourcesMenu(
|
||||
modifier = Modifier.width(384.dp + 96.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,353 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.dice
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||
import androidx.compose.animation.ContentTransform
|
||||
import androidx.compose.animation.SizeTransform
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.PointerMatcher
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.onClick
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.input.pointer.PointerButton
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.ui.theme.color.component.LwaButtonColors
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d10
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d100
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d12
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d20
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d4
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d6
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d8
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import java.util.UUID
|
||||
import kotlin.math.max
|
||||
import kotlin.random.Random
|
||||
import kotlin.random.nextInt
|
||||
|
||||
@Stable
|
||||
data class DiceMenuUio(
|
||||
val d4: Int = 0,
|
||||
val d6: Int = 0,
|
||||
val d8: Int = 0,
|
||||
val d10: Int = 0,
|
||||
val d12: Int = 0,
|
||||
val d20: Int = 0,
|
||||
val d100: Int = 1,
|
||||
val result: Result? = null,
|
||||
) {
|
||||
@Stable
|
||||
data class Result(
|
||||
val id: String,
|
||||
val value: Int,
|
||||
)
|
||||
}
|
||||
|
||||
@Stable
|
||||
data object DiceMenuDefault {
|
||||
@Stable
|
||||
val size: Dp = 32.dp
|
||||
|
||||
@Stable
|
||||
val spacings: DpSize = DpSize(width = 2.dp, height = 8.dp)
|
||||
|
||||
@Stable
|
||||
val paddings = PaddingValues(horizontal = 8.dp)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DiceMenu(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val dices = remember {
|
||||
mutableStateOf(
|
||||
DiceMenuUio()
|
||||
)
|
||||
}
|
||||
DiceMenuContent(
|
||||
modifier = modifier,
|
||||
dices = dices,
|
||||
onAddD4 = {
|
||||
dices.value = dices.value.copy(d4 = max(0, dices.value.d4 + 1))
|
||||
},
|
||||
onRemoveD4 = {
|
||||
dices.value = dices.value.copy(d4 = max(0, dices.value.d4 - 1))
|
||||
},
|
||||
onAddD6 = {
|
||||
dices.value = dices.value.copy(d6 = max(0, dices.value.d6 + 1))
|
||||
},
|
||||
onRemoveD6 = {
|
||||
dices.value = dices.value.copy(d6 = max(0, dices.value.d6 - 1))
|
||||
},
|
||||
onAddD8 = {
|
||||
dices.value = dices.value.copy(d8 = max(0, dices.value.d8 + 1))
|
||||
},
|
||||
onRemoveD8 = {
|
||||
dices.value = dices.value.copy(d8 = max(0, dices.value.d8 - 1))
|
||||
},
|
||||
onAddD10 = {
|
||||
dices.value = dices.value.copy(d10 = max(0, dices.value.d10 + 1))
|
||||
},
|
||||
onRemoveD10 = {
|
||||
dices.value = dices.value.copy(d10 = max(0, dices.value.d10 - 1))
|
||||
},
|
||||
onAddD12 = {
|
||||
dices.value = dices.value.copy(d12 = max(0, dices.value.d12 + 1))
|
||||
},
|
||||
onRemoveD12 = {
|
||||
dices.value = dices.value.copy(d12 = max(0, dices.value.d12 - 1))
|
||||
},
|
||||
onAddD20 = {
|
||||
dices.value = dices.value.copy(d20 = max(0, dices.value.d20 + 1))
|
||||
},
|
||||
onRemoveD20 = {
|
||||
dices.value = dices.value.copy(d20 = max(0, dices.value.d20 - 1))
|
||||
},
|
||||
onAddD100 = {
|
||||
dices.value = dices.value.copy(d100 = max(0, dices.value.d100 + 1))
|
||||
},
|
||||
onRemoveD100 = {
|
||||
dices.value = dices.value.copy(d100 = max(0, dices.value.d100 - 1))
|
||||
},
|
||||
onRoll = {
|
||||
dices.value.let { dice ->
|
||||
val d4 = (0 until dice.d4)
|
||||
.also { print("${it.last + 1}d4:(") }
|
||||
.sumOf { Random.nextInt(range = 1..4).also { print("$it,") } }
|
||||
.also { print(")+") }
|
||||
val d6 = (0 until dice.d6)
|
||||
.also { print("${it.last + 1}:d6(") }
|
||||
.sumOf { Random.nextInt(range = 1..6).also { print("$it,") } }
|
||||
.also { print(")+") }
|
||||
val d8 = (0 until dice.d8)
|
||||
.also { print("${it.last + 1}d8:(") }
|
||||
.sumOf { Random.nextInt(range = 1..8).also { print("$it,") } }
|
||||
.also { print(")+") }
|
||||
val d10 = (0 until dice.d10)
|
||||
.also { print("${it.last + 1}d10:(") }
|
||||
.sumOf { Random.nextInt(range = 1..10).also { print("$it,") } }
|
||||
.also { print(")+") }
|
||||
val d12 = (0 until dice.d12)
|
||||
.also { print("${it.last + 1}d12:(") }
|
||||
.sumOf { Random.nextInt(range = 1..12).also { print("$it,") } }
|
||||
.also { print(")+") }
|
||||
val d20 = (0 until dice.d20)
|
||||
.also { print("${it.last + 1}d20:(") }
|
||||
.sumOf { Random.nextInt(range = 1..20).also { print("$it,") } }
|
||||
.also { print(")+") }
|
||||
val d100 = (0 until dice.d100)
|
||||
.also { print("${it.last + 1}d100:(") }
|
||||
.sumOf { Random.nextInt(range = 1..100).also { print("$it,") } }
|
||||
.also { println(")") }
|
||||
dices.value = dices.value.copy(
|
||||
result = DiceMenuUio.Result(
|
||||
id = UUID.randomUUID().toString(),
|
||||
value = d4 + d6 + d8 + d10 + d12 + d20 + d100,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DiceMenuContent(
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp = DiceMenuDefault.size,
|
||||
spacings: DpSize = DiceMenuDefault.spacings,
|
||||
paddingValues: PaddingValues = DiceMenuDefault.paddings,
|
||||
dices: State<DiceMenuUio>,
|
||||
onAddD4: () -> Unit,
|
||||
onRemoveD4: () -> Unit,
|
||||
onAddD6: () -> Unit,
|
||||
onRemoveD6: () -> Unit,
|
||||
onAddD8: () -> Unit,
|
||||
onRemoveD8: () -> Unit,
|
||||
onAddD10: () -> Unit,
|
||||
onRemoveD10: () -> Unit,
|
||||
onAddD12: () -> Unit,
|
||||
onRemoveD12: () -> Unit,
|
||||
onAddD20: () -> Unit,
|
||||
onRemoveD20: () -> Unit,
|
||||
onAddD100: () -> Unit,
|
||||
onRemoveD100: () -> Unit,
|
||||
onRoll: () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues = paddingValues)
|
||||
.then(other = modifier),
|
||||
verticalArrangement = Arrangement.spacedBy(space = spacings.height),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d4),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d4,
|
||||
onAdd = onAddD4,
|
||||
onRemove = onRemoveD4,
|
||||
)
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d6),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d6,
|
||||
onAdd = onAddD6,
|
||||
onRemove = onRemoveD6,
|
||||
)
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d8),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d8,
|
||||
onAdd = onAddD8,
|
||||
onRemove = onRemoveD8,
|
||||
)
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d10),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d10,
|
||||
onAdd = onAddD10,
|
||||
onRemove = onRemoveD10,
|
||||
)
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d12),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d12,
|
||||
onAdd = onAddD12,
|
||||
onRemove = onRemoveD12,
|
||||
)
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d20),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d20,
|
||||
onAdd = onAddD20,
|
||||
onRemove = onRemoveD20,
|
||||
)
|
||||
Dice(
|
||||
painter = painterResource(Res.drawable.icon_d100),
|
||||
size = size,
|
||||
spacings = spacings.width,
|
||||
value = dices.value.d100,
|
||||
postSign = "=",
|
||||
onAdd = onAddD100,
|
||||
onRemove = onRemoveD100,
|
||||
)
|
||||
AnimatedContent(
|
||||
modifier = Modifier.padding(top = spacings.height),
|
||||
targetState = dices.value.result,
|
||||
transitionSpec = {
|
||||
val enter = fadeIn() + slideInVertically { -16 }
|
||||
val exit = fadeOut() + slideOutVertically { 16 }
|
||||
enter togetherWith exit using SizeTransform(clip = false)
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = MaterialTheme.lwa.typography.dice.result,
|
||||
textAlign = TextAlign.Center,
|
||||
text = "${it?.value ?: ""}"
|
||||
)
|
||||
}
|
||||
TextButton(
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally),
|
||||
colors = LwaButtonColors(),
|
||||
onClick = onRoll,
|
||||
) {
|
||||
Text(
|
||||
text = "Roll"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
private fun Dice(
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp,
|
||||
spacings: Dp,
|
||||
painter: Painter,
|
||||
value: Int,
|
||||
postSign: String = "+",
|
||||
onAdd: () -> Unit,
|
||||
onRemove: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.onClick(
|
||||
matcher = PointerMatcher.mouse(PointerButton.Primary),
|
||||
onClick = onAdd,
|
||||
)
|
||||
.onClick(
|
||||
matcher = PointerMatcher.mouse(PointerButton.Secondary),
|
||||
onClick = onRemove,
|
||||
)
|
||||
.then(
|
||||
other = modifier,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = spacings),
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(size),
|
||||
painter = painter,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.dice.dice,
|
||||
text = "×"
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = value,
|
||||
transitionSpec = { contentTransform() }
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.dice.dice,
|
||||
text = "$it"
|
||||
)
|
||||
}
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.dice.dice,
|
||||
text = postSign,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun AnimatedContentTransitionScope<Int>.contentTransform(): ContentTransform {
|
||||
val sign = if (initialState < targetState) 1 else -1
|
||||
val enter = fadeIn() + slideInVertically { -16 * sign }
|
||||
val exit = fadeOut() + slideOutVertically { 16 * sign }
|
||||
return enter togetherWith exit using SizeTransform(clip = false)
|
||||
}
|
||||
|
|
@ -1,17 +1,14 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
|
|
@ -87,7 +84,9 @@ private fun ResourcesContent(
|
|||
spacing: Dp = ResourcesDialogDefault.spacing,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(paddingValues = padding).then(other = modifier),
|
||||
modifier = Modifier
|
||||
.padding(paddingValues = padding)
|
||||
.then(other = modifier),
|
||||
verticalArrangement = Arrangement.spacedBy(space = spacing),
|
||||
) {
|
||||
dialog.resources.forEach { resource ->
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.gamemaster
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
|
|
@ -8,8 +9,12 @@ import androidx.compose.foundation.layout.Row
|
|||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.DropdownMenu
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Surface
|
||||
|
|
@ -19,6 +24,8 @@ import androidx.compose.material.TopAppBar
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -39,6 +46,7 @@ import com.pixelized.desktop.lwa.ui.navigation.screen.destination.gamemaster.nav
|
|||
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.gamemaster.navigateToGameMasterAlterationPage
|
||||
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.gamemaster.navigateToGameMasterCharacterPage
|
||||
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.gamemaster.navigateToGameMasterObjectPage
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.dice.DiceMenu
|
||||
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.GMTab
|
||||
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.GMTabUio
|
||||
import com.pixelized.desktop.lwa.ui.theme.color.component.LwaSwitchColors
|
||||
|
|
@ -47,6 +55,8 @@ import lwacharactersheet.composeapp.generated.resources.Res
|
|||
import lwacharactersheet.composeapp.generated.resources.game_master__action
|
||||
import lwacharactersheet.composeapp.generated.resources.game_master__title
|
||||
import lwacharactersheet.composeapp.generated.resources.app_version
|
||||
import lwacharactersheet.composeapp.generated.resources.icon_d100
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
||||
|
|
@ -56,10 +66,12 @@ fun GameMasterScreen(
|
|||
controller: NavHostController = LocalGMScreenController.current,
|
||||
) {
|
||||
val gameMaster = gameMasterViewModel.isGameMaster.collectAsState()
|
||||
val isDiceMenuOpen = remember { mutableStateOf(false) }
|
||||
|
||||
GameMasterContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
controller = controller,
|
||||
isDiceMenuOpen = isDiceMenuOpen,
|
||||
gameMaster = gameMaster,
|
||||
onGameMaster = gameMasterViewModel::onGameMaster,
|
||||
onTab = {
|
||||
|
|
@ -70,6 +82,9 @@ fun GameMasterScreen(
|
|||
GMTabUio.Objects -> controller.navigateToGameMasterObjectPage()
|
||||
}
|
||||
},
|
||||
onDice = {
|
||||
isDiceMenuOpen.value = it
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +92,9 @@ fun GameMasterScreen(
|
|||
private fun GameMasterContent(
|
||||
modifier: Modifier = Modifier,
|
||||
controller: NavHostController = rememberNavController(),
|
||||
isDiceMenuOpen: State<Boolean>,
|
||||
gameMaster: State<Boolean>,
|
||||
onDice: (Boolean) -> Unit,
|
||||
onGameMaster: (Boolean) -> Unit,
|
||||
onTab: (GMTabUio) -> Unit,
|
||||
) {
|
||||
|
|
@ -121,6 +138,24 @@ private fun GameMasterContent(
|
|||
onCheckedChange = null,
|
||||
)
|
||||
}
|
||||
IconButton(
|
||||
onClick = { onDice(true) },
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(32.dp),
|
||||
painter = painterResource(Res.drawable.icon_d100),
|
||||
contentDescription = null,
|
||||
)
|
||||
DropdownMenu(
|
||||
expanded = isDiceMenuOpen.value,
|
||||
onDismissRequest = { onDice(false) },
|
||||
content = {
|
||||
DiceMenu(
|
||||
modifier = Modifier.widthIn(min = 92.dp),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -18,6 +18,20 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.unit.sp
|
||||
import com.pixelized.desktop.lwa.ui.theme.color.LwaColors
|
||||
import com.pixelized.desktop.lwa.ui.theme.typography.LwaTypography.Settings
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_Bold
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_BoldItalic
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_ExtraBold
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_ExtraBoldItalic
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_ExtraLight
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_ExtraLightItalic
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_Italic
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_Light
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_LightItalic
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_Medium
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_MediumItalic
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_Regular
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_SemiBold
|
||||
import lwacharactersheet.composeapp.generated.resources.AtkinsonHyperlegibleMono_SemiBoldItalic
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.consola_mono_bold
|
||||
import lwacharactersheet.composeapp.generated.resources.consola_mono_book
|
||||
|
|
@ -30,6 +44,7 @@ data class LwaTypography(
|
|||
val settings: Settings,
|
||||
val portrait: Portrait,
|
||||
val inventory: Inventory,
|
||||
val dice: Dice,
|
||||
) {
|
||||
@Stable
|
||||
data class Chat(
|
||||
|
|
@ -57,6 +72,12 @@ data class LwaTypography(
|
|||
val countInline: TextStyle,
|
||||
val label: TextStyle,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class Dice(
|
||||
val dice: TextStyle,
|
||||
val result: TextStyle,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -66,6 +87,81 @@ fun ConsolaFontFamily() = FontFamily(
|
|||
Font(resource = Res.font.consola_mono_bold, weight = FontWeight.Bold),
|
||||
)
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
fun AtkinsonHyperLigibleMonoFontFamily() = FontFamily(
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_ExtraLight,
|
||||
weight = FontWeight.ExtraLight,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_Light,
|
||||
weight = FontWeight.Light,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_Regular,
|
||||
weight = FontWeight.Normal,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_Medium,
|
||||
weight = FontWeight.Medium,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_SemiBold,
|
||||
weight = FontWeight.SemiBold,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_Bold,
|
||||
weight = FontWeight.Bold,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_ExtraBold,
|
||||
weight = FontWeight.ExtraBold,
|
||||
style = FontStyle.Normal
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_ExtraLightItalic,
|
||||
weight = FontWeight.ExtraLight,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_LightItalic,
|
||||
weight = FontWeight.Light,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_Italic,
|
||||
weight = FontWeight.Normal,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_MediumItalic,
|
||||
weight = FontWeight.Medium,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_SemiBoldItalic,
|
||||
weight = FontWeight.SemiBold,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_BoldItalic,
|
||||
weight = FontWeight.Bold,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
Font(
|
||||
resource = Res.font.AtkinsonHyperlegibleMono_ExtraBoldItalic,
|
||||
weight = FontWeight.ExtraBold,
|
||||
style = FontStyle.Italic
|
||||
),
|
||||
)
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
fun lwaTypography(
|
||||
|
|
@ -73,6 +169,7 @@ fun lwaTypography(
|
|||
colors: LwaColors,
|
||||
): LwaTypography {
|
||||
val consolaFontFamily = ConsolaFontFamily()
|
||||
val atkinsonHyperLigibleMonoFontFamily = AtkinsonHyperLigibleMonoFontFamily()
|
||||
|
||||
return remember(consolaFontFamily) {
|
||||
LwaTypography(
|
||||
|
|
@ -146,6 +243,16 @@ fun lwaTypography(
|
|||
label = base.body1.copy(
|
||||
fontWeight = FontWeight.Normal,
|
||||
),
|
||||
),
|
||||
dice = LwaTypography.Dice(
|
||||
dice = base.h6.copy(
|
||||
fontFamily = atkinsonHyperLigibleMonoFontFamily,
|
||||
color = colors.base.onSurface,
|
||||
),
|
||||
result = base.h4.copy(
|
||||
fontFamily = atkinsonHyperLigibleMonoFontFamily,
|
||||
color = colors.base.onSurface,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||