diff --git a/app/src/main/java/app/jerboa/spp/MainActivity.kt b/app/src/main/java/app/jerboa/spp/MainActivity.kt index 5e2a90a..11e3901 100644 --- a/app/src/main/java/app/jerboa/spp/MainActivity.kt +++ b/app/src/main/java/app/jerboa/spp/MainActivity.kt @@ -18,10 +18,13 @@ import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import app.jerboa.spp.viewmodel.MUSIC import app.jerboa.spp.viewmodel.REVIEW_RATE_LIMIT_MILLIS -import app.jerboa.spp.viewmodel.RenderViewModel +import app.jerboa.spp.viewmodel.SPPViewModel import app.jerboa.spp.viewmodel.SOCIAL -import app.jerboa.spp.composable.renderScreen +import app.jerboa.spp.composable.screen import app.jerboa.spp.ui.theme.SPPTheme +import app.jerboa.spp.viewmodel.AboutViewModel +import app.jerboa.spp.viewmodel.MainMenuViewModel +import app.jerboa.spp.viewmodel.MenuPromptViewModel import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.games.AuthenticationResult @@ -84,7 +87,10 @@ val achievementStates = mutableMapOf( class MainActivity : AppCompatActivity() { - private val renderViewModel by viewModels() + private val sppViewModel by viewModels() + private val aboutViewModel by viewModels() + private val menuPromptViewModel by viewModels() + private val mainMenuViewModel by viewModels() private var mediaPlayer = MediaPlayer() @@ -141,7 +147,7 @@ class MainActivity : AppCompatActivity() { private fun showAchievements() { if (!isGooglePlayGamesServicesInstalled(this)) { - renderViewModel.onRequestPGSAndNotInstalled() + sppViewModel.onRequestPGSAndNotInstalled() return } PlayGames.getAchievementsClient(this) @@ -173,7 +179,7 @@ class MainActivity : AppCompatActivity() { isAuthenticatedTask.isSuccessful && isAuthenticatedTask.result.isAuthenticated if (isAuthenticated) { // Continue with Play Games Services - renderViewModel.onPlaySuccess(true) + sppViewModel.onPlaySuccess(true) if (DEBUG) { Log.d("playGames", "success") } @@ -185,7 +191,7 @@ class MainActivity : AppCompatActivity() { if (DEBUG) { Log.d("playGames", "failure ${isAuthenticatedTask.result.toString()}") } - renderViewModel.onPlaySuccess(false) + sppViewModel.onPlaySuccess(false) } } } @@ -323,7 +329,7 @@ class MainActivity : AppCompatActivity() { val flow = reviewManager.launchReviewFlow(this, reviewInfo) //Log.d("reviewManager", "flow") flow.addOnCompleteListener { - renderViewModel.onInAppReviewShown() + sppViewModel.onInAppReviewShown() //Log.d("reviewManager", "complete: $reviewInfo") } } else { @@ -335,7 +341,7 @@ class MainActivity : AppCompatActivity() { } } - renderViewModel.onInAppReviewShown() + sppViewModel.onInAppReviewShown() seenReview = true if (lastReviewTries < 5) { @@ -368,7 +374,7 @@ class MainActivity : AppCompatActivity() { reviewManager = ReviewManagerFactory.create(this) - renderViewModel.requestingInAppReview.observe( + sppViewModel.requestingInAppReview.observe( this, androidx.lifecycle.Observer { if (it) { requestUserReviewPrompt() @@ -381,13 +387,13 @@ class MainActivity : AppCompatActivity() { Log.d("playServices", "$status ${status == ConnectionResult.SUCCESS}") } - renderViewModel.requestingPlayServices.observe( + sppViewModel.requestingPlayServices.observe( this, androidx.lifecycle.Observer { request -> if (request) { if (DEBUG) { - Log.d("playGames", "${renderViewModel.playSuccess.value!!}") + Log.d("playGames", "${sppViewModel.playSuccess.value!!}") } - if (!renderViewModel.playSuccess.value!! && isGooglePlayGamesServicesInstalled(this)) { + if (!sppViewModel.playSuccess.value!! && isGooglePlayGamesServicesInstalled(this)) { if (DEBUG) { Log.d("playGames", "login") } @@ -409,16 +415,16 @@ class MainActivity : AppCompatActivity() { } ) - renderViewModel.requestingInstallPGS.observe( + sppViewModel.requestingInstallPGS.observe( this, androidx.lifecycle.Observer { request -> if (request) { installPGS() - renderViewModel.onInstallPGSInitiated() + sppViewModel.onInstallPGSInitiated() } } ) - renderViewModel.requestingLicenses.observe( + aboutViewModel.requestingLicenses.observe( this, androidx.lifecycle.Observer { request -> if (request) { showLicenses() @@ -426,7 +432,7 @@ class MainActivity : AppCompatActivity() { } ) - renderViewModel.requestingSocial.observe( + aboutViewModel.requestingSocial.observe( this, androidx.lifecycle.Observer { request -> when (request) { SOCIAL.WEB -> web() @@ -438,7 +444,7 @@ class MainActivity : AppCompatActivity() { } ) - renderViewModel.showToys.observe( + mainMenuViewModel.showToys.observe( this, androidx.lifecycle.Observer { show -> val prefs = getSharedPreferences("jerboa.app.spp.prefs", MODE_PRIVATE) val prefsEdit = prefs.edit() @@ -447,7 +453,7 @@ class MainActivity : AppCompatActivity() { } ) - renderViewModel.playingMusic.observe( + menuPromptViewModel.playingMusic.observe( this, androidx.lifecycle.Observer { playingMusic -> when (playingMusic) { MUSIC.FORREST -> { @@ -469,7 +475,7 @@ class MainActivity : AppCompatActivity() { } ) - renderViewModel.playTime.observe( + sppViewModel.playTime.observe( this, androidx.lifecycle.Observer { time -> run { totalTime = if (seenReview) { @@ -536,7 +542,7 @@ class MainActivity : AppCompatActivity() { prefsEdit.apply() } - renderViewModel.onShowToysChanged(prefs.getBoolean("showToys", false)) + mainMenuViewModel.onShowToysChanged(prefs.getBoolean("showToys", false)) // if (BuildConfig.DEBUG){ // prefs.edit().clear().apply() @@ -552,11 +558,11 @@ class MainActivity : AppCompatActivity() { syncAchievementsState() - renderViewModel.setAchievementState(achievementStates) + sppViewModel.setAchievementState(achievementStates) } - renderViewModel.achievementStates.observe( + sppViewModel.achievementStates.observe( this, androidx.lifecycle.Observer { states -> updatePlayGamesAchievements(states) } @@ -590,9 +596,11 @@ class MainActivity : AppCompatActivity() { val width = displayMetrics.widthPixels setContent { SPPTheme { - // A surface container using the 'background' color from the theme - renderScreen( - renderViewModel, + screen( + sppViewModel, + aboutViewModel, + menuPromptViewModel, + mainMenuViewModel, Pair(width, height), imageResources, appInfo, @@ -604,7 +612,7 @@ class MainActivity : AppCompatActivity() { public override fun onStart() { super.onStart() - renderViewModel.startClock() + sppViewModel.startClock() } public override fun onStop() @@ -614,6 +622,6 @@ class MainActivity : AppCompatActivity() { prefsEdit.putLong("playTime", totalTime) prefsEdit.apply() super.onStop() - renderViewModel.stopClock() + sppViewModel.stopClock() } } \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/composable/about.kt b/app/src/main/java/app/jerboa/spp/composable/about.kt index 0fa1604..34b0d70 100644 --- a/app/src/main/java/app/jerboa/spp/composable/about.kt +++ b/app/src/main/java/app/jerboa/spp/composable/about.kt @@ -12,6 +12,8 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -21,19 +23,19 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import app.jerboa.spp.AppInfo import app.jerboa.spp.R +import app.jerboa.spp.viewmodel.AboutViewModel import app.jerboa.spp.viewmodel.SOCIAL @OptIn(ExperimentalAnimationApi::class) @Composable fun about( - displayingAbout: Boolean, + aboutViewModel: AboutViewModel, width75Percent: Double, images: Map, info: AppInfo, - onRequestingLicenses: () -> Unit, - onRequestingSocial: (SOCIAL) -> Unit, - onResetTutorial: () -> Unit, ){ + val displayingAbout: Boolean by aboutViewModel.displayingAbout.observeAsState(initial = false) + AnimatedVisibility( visible = displayingAbout, enter = fadeIn(), @@ -74,7 +76,7 @@ fun about( fontSize = MaterialTheme.typography.body1.fontSize * info.density, colour = Color.Black ) - TextButton(onClick = { onRequestingLicenses() }) { + TextButton(onClick = { aboutViewModel.onRequestingLicenses() }) { Text( stringResource(id = R.string.OSSprompt), textAlign = TextAlign.Center, @@ -96,7 +98,7 @@ fun about( textAlign = TextAlign.Center, color = Color.Black ) - TextButton(onClick = { onResetTutorial() }) { + TextButton(onClick = { aboutViewModel.onResetTutorial() }) { Text( stringResource(id = R.string.resetTutorial), textAlign = TextAlign.Center, @@ -108,7 +110,7 @@ fun about( } } Spacer(modifier = Modifier.size(8.dp)) - socials(images, info, onRequestingSocial) + socials(images, info) { aboutViewModel.onRequestingSocial(it) } } } diff --git a/app/src/main/java/app/jerboa/spp/composable/mainMenu.kt b/app/src/main/java/app/jerboa/spp/composable/mainMenu.kt index 09518e0..ee27ee5 100644 --- a/app/src/main/java/app/jerboa/spp/composable/mainMenu.kt +++ b/app/src/main/java/app/jerboa/spp/composable/mainMenu.kt @@ -15,6 +15,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Slider import androidx.compose.material.Text import androidx.compose.runtime.* +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -22,8 +23,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import app.jerboa.spp.AppInfo -import app.jerboa.spp.viewmodel.COLOUR_MAP +import app.jerboa.spp.viewmodel.AboutViewModel import app.jerboa.spp.viewmodel.MAX_LOG_AR import app.jerboa.spp.viewmodel.MAX_LOG_FADE import app.jerboa.spp.viewmodel.MAX_LOG_MASS @@ -36,7 +36,10 @@ import app.jerboa.spp.viewmodel.MIN_LOG_FADE import app.jerboa.spp.viewmodel.MIN_LOG_MASS import app.jerboa.spp.viewmodel.MIN_LOG_ORBIT import app.jerboa.spp.viewmodel.MIN_LOG_SPIN +import app.jerboa.spp.viewmodel.MainMenuViewModel import app.jerboa.spp.viewmodel.PARAM +import app.jerboa.spp.viewmodel.PARTICLES_SLIDER_DEFAULT +import app.jerboa.spp.viewmodel.SPPViewModel import app.jerboa.spp.viewmodel.TOY import kotlin.math.ceil import kotlin.math.log10 @@ -99,30 +102,28 @@ fun logSlider( } @OptIn(ExperimentalAnimationApi::class) @Composable -fun menu( +fun mainMenu( + mainMenuViewModel: MainMenuViewModel, + sppViewModel: SPPViewModel, + aboutViewModel: AboutViewModel, displayingMenu: Boolean, - playSuccess: Boolean, - particleNumber: Float, - speed: Float, - attraction: Float, - repulsion: Float, - orbit: Float, - spin: Float, - mass: Float, - fade: Float, - showToys: Boolean, width75Percent: Double, height10Percent: Double, menuItemHeight: Double, - images: Map, - info: AppInfo, - onDisplayingAboutChanged: (Boolean) -> Unit, - onAttractorChanged: (TOY) -> Unit, - onRequestPlayServices: () -> Unit, - onParameterChanged: (Pair) -> Unit, - onSelectColourMap: (COLOUR_MAP) -> Unit, - onShowToysChanged: (Boolean) -> Unit + images: Map ) { + + val playSuccess: Boolean by sppViewModel.playSuccess.observeAsState(initial = false) + val particleNumber: Float by mainMenuViewModel.particleNumber.observeAsState(initial = PARTICLES_SLIDER_DEFAULT) + val speed: Float by mainMenuViewModel.speed.observeAsState(initial = 1.0f) + val attraction: Float by mainMenuViewModel.attractorStrength.observeAsState(50000f) + val repulsion: Float by mainMenuViewModel.repellorStrength.observeAsState(50000f) + val orbit: Float by mainMenuViewModel.orbitStrength.observeAsState(0.5f) + val spin: Float by mainMenuViewModel.spinStrength.observeAsState(1500f) + val mass: Float by mainMenuViewModel.mass.observeAsState(0.1f) + val fade: Float by mainMenuViewModel.fade.observeAsState(initial = 1.0f) + val showToys: Boolean by mainMenuViewModel.showToys.observeAsState(initial = false) + var particleSliderValue by remember { mutableFloatStateOf(log10(particleNumber)) } @@ -154,7 +155,7 @@ fun menu( verticalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth(), ) { - colourMapMenu(images,menuItemHeight,onSelectColourMap) + colourMapMenu(images, menuItemHeight) { mainMenuViewModel.onSelectColourMap(it) } Box( modifier = Modifier @@ -168,7 +169,7 @@ fun menu( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center ) { - IconButton(onClick = { onRequestPlayServices() }) { + IconButton(onClick = { sppViewModel.onRequestPlayServices() }) { Image( modifier = Modifier .fillMaxHeight() @@ -184,7 +185,7 @@ fun menu( contentDescription = "play" ) } - IconButton(onClick = { onDisplayingAboutChanged(true) }) { + IconButton(onClick = { aboutViewModel.onDisplayingAboutChanged(true) }) { Image( modifier = Modifier .fillMaxHeight() @@ -217,7 +218,7 @@ fun menu( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { - IconButton(onClick = { onAttractorChanged(TOY.ATTRACTOR) }) { + IconButton(onClick = { mainMenuViewModel.onToyChanged(TOY.ATTRACTOR) }) { Image( modifier = Modifier .fillMaxHeight() @@ -227,7 +228,7 @@ fun menu( contentDescription = "Image" ) } - IconButton(onClick = { onAttractorChanged(TOY.REPELLOR) }) { + IconButton(onClick = { mainMenuViewModel.onToyChanged(TOY.REPELLOR) }) { Image( modifier = Modifier .fillMaxHeight() @@ -237,7 +238,7 @@ fun menu( contentDescription = "Image" ) } - IconButton(onClick = { onAttractorChanged(TOY.SPINNER) }) { + IconButton(onClick = { mainMenuViewModel.onToyChanged(TOY.SPINNER) }) { Image( modifier = Modifier .fillMaxHeight() @@ -247,7 +248,7 @@ fun menu( contentDescription = "Image" ) } - IconButton(onClick = { onAttractorChanged(TOY.FREEZER) }) { + IconButton(onClick = { mainMenuViewModel.onToyChanged(TOY.FREEZER) }) { Image( modifier = Modifier .fillMaxHeight() @@ -257,7 +258,7 @@ fun menu( contentDescription = "Image" ) } - IconButton(onClick = { onAttractorChanged(TOY.ORBITER) }) { + IconButton(onClick = { mainMenuViewModel.onToyChanged(TOY.ORBITER) }) { Image( modifier = Modifier .fillMaxHeight() @@ -284,7 +285,7 @@ fun menu( value = particleSliderValue, onValueChange = { particleSliderValue = it }, onValueChangeFinished = { - onParameterChanged( + mainMenuViewModel.onParameterChanged( Pair( 10.0f.pow( particleSliderValue @@ -300,14 +301,14 @@ fun menu( .background(color = Color(1, 1, 1, 1)) ) Spacer(modifier = Modifier.size(8.dp)) - logSlider(speed, -3.0f, MAX_LOG_SPEED, "Speed", {onParameterChanged(Pair(it, PARAM.SPEED))}, width75Percent) + logSlider(speed, -3.0f, MAX_LOG_SPEED, "Speed", {mainMenuViewModel.onParameterChanged(Pair(it, PARAM.SPEED))}, width75Percent) Spacer(modifier = Modifier.size(8.dp)) logSlider( attraction, MIN_LOG_AR, MAX_LOG_AR, "Attraction", - {onParameterChanged(Pair(it, PARAM.ATTRACTION))}, + {mainMenuViewModel.onParameterChanged(Pair(it, PARAM.ATTRACTION))}, width75Percent ) Spacer(modifier = Modifier.size(8.dp)) @@ -316,22 +317,22 @@ fun menu( MIN_LOG_AR, MAX_LOG_AR, "Repulsion", - {onParameterChanged(Pair(it, PARAM.REPULSION))}, + {mainMenuViewModel.onParameterChanged(Pair(it, PARAM.REPULSION))}, width75Percent ) Spacer(modifier = Modifier.size(8.dp)) - logSlider(orbit, MIN_LOG_ORBIT, MAX_LOG_ORBIT, "Orbit", {onParameterChanged(Pair(it, PARAM.ORBIT))}, width75Percent) + logSlider(orbit, MIN_LOG_ORBIT, MAX_LOG_ORBIT, "Orbit", {mainMenuViewModel.onParameterChanged(Pair(it, PARAM.ORBIT))}, width75Percent) Spacer(modifier = Modifier.size(8.dp)) - logSlider(spin, MIN_LOG_SPIN, MAX_LOG_SPIN, "Spin", {onParameterChanged(Pair(it, PARAM.SPIN))}, width75Percent) + logSlider(spin, MIN_LOG_SPIN, MAX_LOG_SPIN, "Spin", {mainMenuViewModel.onParameterChanged(Pair(it, PARAM.SPIN))}, width75Percent) Spacer(modifier = Modifier.size(8.dp)) - logSlider(mass, MIN_LOG_MASS, MAX_LOG_MASS, "Mass", {onParameterChanged(Pair(it, PARAM.MASS))}, width75Percent) + logSlider(mass, MIN_LOG_MASS, MAX_LOG_MASS, "Mass", {mainMenuViewModel.onParameterChanged(Pair(it, PARAM.MASS))}, width75Percent) Spacer(modifier = Modifier.size(8.dp)) label(text = "Tracing " + "${round(fadeSliderValue * 100.0f) / 100.0f}") Slider( value = fadeSliderValue, onValueChange = { fadeSliderValue = it }, onValueChangeFinished = { - onParameterChanged( + mainMenuViewModel.onParameterChanged( Pair( 10.0f.pow((1.0f - fadeSliderValue) * (MAX_LOG_FADE - MIN_LOG_FADE) + MIN_LOG_FADE), PARAM.FADE @@ -348,7 +349,7 @@ fun menu( label(text = "Show Toys") Checkbox( checked = showToysValue, - onCheckedChange = { showToysValue = it; onShowToysChanged(it) }, + onCheckedChange = { showToysValue = it; mainMenuViewModel.onShowToysChanged(it) }, colors = checkBoxColors() ) } diff --git a/app/src/main/java/app/jerboa/spp/composable/menuPrompt.kt b/app/src/main/java/app/jerboa/spp/composable/menuPrompt.kt index 1b2c1ef..11e38ba 100644 --- a/app/src/main/java/app/jerboa/spp/composable/menuPrompt.kt +++ b/app/src/main/java/app/jerboa/spp/composable/menuPrompt.kt @@ -13,27 +13,29 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import app.jerboa.spp.viewmodel.AboutViewModel import app.jerboa.spp.viewmodel.MUSIC +import app.jerboa.spp.viewmodel.MenuPromptViewModel @OptIn(ExperimentalAnimationApi::class) @Composable fun menuPrompt( + menuPromptViewModel: MenuPromptViewModel, + aboutViewModel: AboutViewModel, images: Map, - displayingMenu: Boolean, - displayingSound: Boolean, - menuItemHeight: Double, - pasued: Boolean, - onDisplayingMenuChanged: (Boolean) -> Unit, - onDisplayingMusicChanged: () -> Unit, - onMusicSelected: (MUSIC) -> Unit, - onPause: () -> Unit + menuItemHeight: Double ){ + val displayingMenu: Boolean by menuPromptViewModel.displayingMenu.observeAsState(initial = false) + val displayingSound: Boolean by menuPromptViewModel.displayingSound.observeAsState(initial = false) + val paused: Boolean by menuPromptViewModel.paused.observeAsState(initial = false) + val fadeAlpha = 0.33f val alphaM1: Float by animateFloatAsState( @@ -41,7 +43,7 @@ fun menuPrompt( animationSpec = tween( durationMillis = 500, easing = LinearEasing, - ) + ), label = "m1" ) val alphaM2: Float by animateFloatAsState( @@ -49,7 +51,7 @@ fun menuPrompt( animationSpec = tween( durationMillis = 500, easing = LinearEasing, - ) + ), label = "m2" ) val alphaS1: Float by animateFloatAsState( @@ -57,7 +59,7 @@ fun menuPrompt( animationSpec = tween( durationMillis = 500, easing = LinearEasing, - ) + ), label = "s1" ) val alphaS2: Float by animateFloatAsState( @@ -65,7 +67,7 @@ fun menuPrompt( animationSpec = tween( durationMillis = 500, easing = LinearEasing, - ) + ), label = "s2" ) @@ -92,7 +94,7 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMenuChanged(true); } + onClick = { menuPromptViewModel.onDisplayingMenuChanged(true); } ) .alpha(alphaM1) ) @@ -110,7 +112,10 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMenuChanged(true); } + onClick = { + menuPromptViewModel.onDisplayingMenuChanged(false) + aboutViewModel.onDisplayingAboutChanged(false) + } ) .alpha(alphaM2) ) @@ -143,7 +148,11 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMusicChanged(); onMusicSelected(MUSIC.RAIN) } + onClick = { + menuPromptViewModel.onDisplayingMusicChanged(false) + aboutViewModel.onDisplayingAboutChanged(false) + menuPromptViewModel.onMusicSelected(MUSIC.RAIN) + } ) .alpha(alphaS2) ) @@ -155,7 +164,11 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMusicChanged(); onMusicSelected(MUSIC.FORREST) } + onClick = { + menuPromptViewModel.onDisplayingMusicChanged(false) + aboutViewModel.onDisplayingAboutChanged(false) + menuPromptViewModel.onMusicSelected(MUSIC.FORREST) + } ) .alpha(alphaS2) ) @@ -167,7 +180,11 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMusicChanged(); onMusicSelected(MUSIC.NOTHING) } + onClick = { + menuPromptViewModel.onDisplayingMusicChanged(false) + aboutViewModel.onDisplayingAboutChanged(false) + menuPromptViewModel.onMusicSelected(MUSIC.NOTHING) + } ) .alpha(alphaS2) ) @@ -179,7 +196,10 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMusicChanged();} + onClick = { + menuPromptViewModel.onDisplayingMusicChanged(false) + aboutViewModel.onDisplayingAboutChanged(false) + } ) .alpha(alphaS2) ) @@ -194,7 +214,7 @@ fun menuPrompt( .align(alignment = Alignment.BottomCenter) ) { AnimatedVisibility( - visible = !pasued && !displayingMenu, + visible = !paused && !displayingMenu, enter = fadeIn(), exit = fadeOut() ) { @@ -206,13 +226,13 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onPause(); } + onClick = { menuPromptViewModel.onPause(); } ) .alpha(0.66f) ) } AnimatedVisibility( - visible = pasued && !displayingMenu, + visible = paused && !displayingMenu, enter = fadeIn(), exit = fadeOut() ) { @@ -224,7 +244,7 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onPause(); } + onClick = { menuPromptViewModel.onPause(); } ) .alpha(0.66f) ) @@ -250,7 +270,10 @@ fun menuPrompt( .clickable( interactionSource = MutableInteractionSource(), indication = null, - onClick = { onDisplayingMusicChanged(); } + onClick = + { + menuPromptViewModel.onDisplayingMusicChanged(true) + } ) .alpha(alphaS1) ) diff --git a/app/src/main/java/app/jerboa/spp/composable/renderScreen.kt b/app/src/main/java/app/jerboa/spp/composable/renderScreen.kt deleted file mode 100644 index 04a1cab..0000000 --- a/app/src/main/java/app/jerboa/spp/composable/renderScreen.kt +++ /dev/null @@ -1,118 +0,0 @@ -package app.jerboa.spp.composable - -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import app.jerboa.spp.AppInfo -import app.jerboa.spp.viewmodel.* - -@Composable -fun renderScreen( - renderViewModel: RenderViewModel, - resolution: Pair, - images: Map, - info: AppInfo, - showNews: Boolean = false -){ - val displayingMenu: Boolean by renderViewModel.displayingMenu.observeAsState(initial = false) - val displayingSound: Boolean by renderViewModel.displayingSound.observeAsState(initial = false) - val displayingAbout: Boolean by renderViewModel.displayingAbout.observeAsState(initial = false) - val toy: TOY by renderViewModel.toy.observeAsState(initial = TOY.ATTRACTOR) - val particleNumber: Float by renderViewModel.particleNumber.observeAsState(initial = PARTICLES_SLIDER_DEFAULT) - val allowAdapt: Boolean by renderViewModel.allowAdapt.observeAsState(initial = true) - val adaptMsg: Boolean by renderViewModel.autoAdaptMessage.observeAsState(initial = false) - val colourMap: COLOUR_MAP by renderViewModel.colourMap.observeAsState(COLOUR_MAP.R1) - val playingMusic: MUSIC by renderViewModel.playingMusic.observeAsState(initial = MUSIC.NOTHING) - val resetTutorial: Boolean by renderViewModel.resetTutorial.observeAsState(initial = false) - val dismissedTutorial: Boolean by renderViewModel.dismissedTutorial.observeAsState(initial = false) - val promptPGS: Boolean by renderViewModel.promptInstallPGS.observeAsState(initial = false) - val dismissedNews: Boolean by renderViewModel.dismissedNews.observeAsState(initial = false) - val paused: Boolean by renderViewModel.paused.observeAsState(initial = false) - val speed: Float by renderViewModel.speed.observeAsState(initial = 1.0f) - val attraction: Float by renderViewModel.attractorStrength.observeAsState(50000f) - val repulsion: Float by renderViewModel.repellorStrength.observeAsState(50000f) - val orbit: Float by renderViewModel.orbitStrength.observeAsState(0.5f) - val spin: Float by renderViewModel.spinStrength.observeAsState(1500f) - val mass: Float by renderViewModel.mass.observeAsState(0.1f) - val fade: Float by renderViewModel.fade.observeAsState(initial = 1.0f) - val showToys: Boolean by renderViewModel.showToys.observeAsState(initial = false) - val playSuccess: Boolean by renderViewModel.playSuccess.observeAsState(initial = false) - - screen( - displayingMenu, - displayingSound, - displayingAbout, - playSuccess, - toy, - particleNumber, - allowAdapt, - colourMap, - showToys, - playingMusic, - paused, - speed, - attraction, - repulsion, - orbit, - spin, - mass, - fade, - adaptMsg, - promptPGS, - resolution, - images, - info, - onDisplayingMenuChanged = {renderViewModel.onDisplayingMenuChanged(it)}, - onDisplayingMusicChanged = {renderViewModel.onDisplayingMusicChanged()}, - onDisplayingAboutChanged = {renderViewModel.onDisplayingAboutChanged(it)}, - onAttractorChanged = {renderViewModel.onToyChanged(it)}, - onRequestPlayServices = {renderViewModel.onRequestPlayServices()}, - onAchievementStateChanged = {renderViewModel.onAchievementStateChanged(it)}, - onAdapt = {renderViewModel.onAdapt(it)}, - onAllowAdaptChanged = {renderViewModel.onAllowAdaptChanged()}, - onAdaptMessageShown = {renderViewModel.onAdaptMessageShown()}, - onRequestingLicenses = {renderViewModel.onRequestingLicenses()}, - onParameterChanged = {renderViewModel.onParameterChanged(it)}, - onSelectColourMap = {renderViewModel.onSelectColourMap(it)}, - selectDefaultColourMap = {renderViewModel.selectDefaultColourMap()}, - onMusicSelected = {renderViewModel.onMusicSelected(it)}, - onRequestingSocial = {renderViewModel.onRequestingSocial(it)}, - onResetTutorial = {renderViewModel.onResetTutorial()}, - onPromptPGS = {renderViewModel.onPromptInstallPGS(it)}, - onToyChanged = {renderViewModel.onToyChanged(it)}, - onRequestReview = {renderViewModel.onRequestingInAppReview()}, - onUpdateClock = {renderViewModel.onUpdateClock()}, - onPause = {renderViewModel.onPause()}, - onShowToysChanged = {renderViewModel.onShowToysChanged(it)} - ) - - if (!dismissedTutorial && (info.firstLaunch || resetTutorial) ){ - Image( - painter = painterResource(id = images["tutorial"]!!), - contentDescription = "", - contentScale = ContentScale.Fit, - modifier = Modifier - .fillMaxWidth() - .clickable { - renderViewModel.onDismissTutorial() - } - ) - }else if (showNews && !dismissedNews){ - Image( - painter = painterResource(id = images["news"]!!), - contentDescription = "", - contentScale = ContentScale.Fit, - modifier = Modifier - .fillMaxWidth() - .clickable { - renderViewModel.onDismissNews() - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/composable/screen.kt b/app/src/main/java/app/jerboa/spp/composable/screen.kt index 0a99ae3..57a6abc 100644 --- a/app/src/main/java/app/jerboa/spp/composable/screen.kt +++ b/app/src/main/java/app/jerboa/spp/composable/screen.kt @@ -1,84 +1,73 @@ package app.jerboa.spp.composable import android.annotation.SuppressLint -import androidx.compose.animation.* -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.runtime.* +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.Scaffold +import androidx.compose.material.SnackbarDuration +import androidx.compose.material.SnackbarResult +import androidx.compose.material.rememberScaffoldState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource import androidx.compose.ui.viewinterop.AndroidView import app.jerboa.spp.AppInfo -import app.jerboa.spp.viewmodel.COLOUR_MAP -import app.jerboa.spp.viewmodel.MUSIC -import app.jerboa.spp.viewmodel.PARAM -import app.jerboa.spp.viewmodel.SOCIAL -import app.jerboa.spp.viewmodel.TOY import app.jerboa.spp.ui.view.SPPView +import app.jerboa.spp.viewmodel.* import kotlinx.coroutines.launch -@OptIn(ExperimentalAnimationApi::class) -// see scaffold below @SuppressLint("CoroutineCreationDuringComposition", "UnusedMaterialScaffoldPaddingParameter") @Composable fun screen( - displayingMenu: Boolean, - displayingSound: Boolean, - displayingAbout: Boolean, - playSuccess: Boolean, - toy: TOY, - particleNumber: Float, - allowAdapt: Boolean, - colourMap: COLOUR_MAP, - showToys: Boolean, - playingMusic: MUSIC, - paused: Boolean, - speed: Float, - attraction: Float, - repulsion: Float, - orbit: Float, - spin: Float, - mass: Float, - fade: Float, - adaptMsg: Boolean, - promptPGS: Boolean, + sppViewModel: SPPViewModel, + aboutViewModel: AboutViewModel, + menuPromptViewModel: MenuPromptViewModel, + mainMenuViewModel: MainMenuViewModel, resolution: Pair, images: Map, info: AppInfo, - onDisplayingMenuChanged: (Boolean) -> Unit, - onDisplayingMusicChanged: () -> Unit, - onDisplayingAboutChanged: (Boolean) -> Unit, - onAttractorChanged: (TOY) -> Unit, - onRequestPlayServices: () -> Unit, - onAchievementStateChanged: (Pair) -> Unit, - onAdapt: (Float) -> Unit, - onAllowAdaptChanged: () -> Unit, - onAdaptMessageShown: () -> Unit, - onRequestingLicenses: () -> Unit, - onParameterChanged: (Pair) -> Unit, - onSelectColourMap: (COLOUR_MAP) -> Unit, - selectDefaultColourMap: () -> Unit, - onMusicSelected: (MUSIC) -> Unit, - onRequestingSocial: (SOCIAL) -> Unit, - onResetTutorial: () -> Unit, - onPromptPGS: (Boolean) -> Unit, - onToyChanged: (TOY) -> Unit, - onRequestReview: () -> Unit, - onUpdateClock: () -> Unit, - onPause: () -> Unit, - onShowToysChanged: (Boolean) -> Unit -) { + showNews: Boolean = false +){ - val scaffoldState = rememberScaffoldState() - val coroutineScope = rememberCoroutineScope() - - val seenHelp = remember { mutableStateOf(!info.firstLaunch) } + val resetTutorial: Boolean by aboutViewModel.resetTutorial.observeAsState(initial = false) + val dismissedTutorial: Boolean by aboutViewModel.dismissedTutorial.observeAsState(initial = false) + val dismissedNews: Boolean by sppViewModel.dismissedNews.observeAsState(initial = false) val width75Percent = info.widthDp * 0.75 - val height25Percent = info.heightDp * 0.25 val height10Percent = info.heightDp * 0.1 val menuItemHeight = height10Percent * 0.66 - selectDefaultColourMap() + val displayingAbout: Boolean by aboutViewModel.displayingAbout.observeAsState(initial = false) + val displayingMenu: Boolean by menuPromptViewModel.displayingMenu.observeAsState(initial = false) + val paused: Boolean by menuPromptViewModel.paused.observeAsState(initial = false) + + val toy: TOY by mainMenuViewModel.toy.observeAsState(initial = TOY.ATTRACTOR) + val particleNumber: Float by mainMenuViewModel.particleNumber.observeAsState(initial = PARTICLES_SLIDER_DEFAULT) + val allowAdapt: Boolean by mainMenuViewModel.allowAdapt.observeAsState(initial = true) + val adaptMsg: Boolean by mainMenuViewModel.autoAdaptMessage.observeAsState(initial = false) + val colourMap: COLOUR_MAP by mainMenuViewModel.colourMap.observeAsState(COLOUR_MAP.R1) + val speed: Float by mainMenuViewModel.speed.observeAsState(initial = 1.0f) + val attraction: Float by mainMenuViewModel.attractorStrength.observeAsState(50000f) + val repulsion: Float by mainMenuViewModel.repellorStrength.observeAsState(50000f) + val orbit: Float by mainMenuViewModel.orbitStrength.observeAsState(0.5f) + val spin: Float by mainMenuViewModel.spinStrength.observeAsState(1500f) + val mass: Float by mainMenuViewModel.mass.observeAsState(0.1f) + val fade: Float by mainMenuViewModel.fade.observeAsState(initial = 1.0f) + val showToys: Boolean by mainMenuViewModel.showToys.observeAsState(initial = false) + + val promptPGS: Boolean by sppViewModel.promptInstallPGS.observeAsState(initial = false) + + + val scaffoldState = rememberScaffoldState() + val coroutineScope = rememberCoroutineScope() + + mainMenuViewModel.selectDefaultColourMap() Column( modifier = Modifier.fillMaxWidth() @@ -90,34 +79,20 @@ fun screen( topBar = { }, bottomBar = { - menu( + mainMenu( + mainMenuViewModel, + sppViewModel, + aboutViewModel, displayingMenu && !displayingAbout, - playSuccess, - particleNumber, - speed, - attraction, - repulsion, - orbit, - spin, - mass, - fade, - showToys, width75Percent, height10Percent, menuItemHeight, - images, - info, - onDisplayingAboutChanged, - onAttractorChanged, - onRequestPlayServices, - onParameterChanged, - onSelectColourMap, - onShowToysChanged + images ) } ) { if (adaptMsg) { - onAdaptMessageShown() + mainMenuViewModel.onAdaptMessageShown() coroutineScope.launch { val snackbarResult = scaffoldState.snackbarHostState.showSnackbar( message = "FPS lower than 30 adapting...", @@ -127,7 +102,7 @@ fun screen( when (snackbarResult) { //SnackbarResult.Dismissed -> Log.d("screen", "Dismissed") SnackbarResult.ActionPerformed -> { - onAllowAdaptChanged() + mainMenuViewModel.onAllowAdaptChanged() } else -> {} } @@ -143,24 +118,20 @@ fun screen( when (snackbarResult) { //SnackbarResult.Dismissed -> Log.d("screen", "Dismissed") SnackbarResult.ActionPerformed -> { - onPromptPGS(true) + sppViewModel.onPromptInstallPGS(true) } else -> {} } } - onPromptPGS(false) + sppViewModel.onPromptInstallPGS(false) } AndroidView( factory = { SPPView( it, null, resolution, - onDisplayingMenuChanged, - onAchievementStateChanged, - onToyChanged, - onRequestReview, - onAdapt, - onUpdateClock, + sppViewModel, + mainMenuViewModel, toy, particleNumber, allowAdapt, @@ -184,16 +155,44 @@ fun screen( view.showToys(showToys) } ) - about( - displayingAbout, - width75Percent, - images, - info, - onRequestingLicenses, - onRequestingSocial, - onResetTutorial - ) - menuPrompt(images,displayingMenu,displayingSound,menuItemHeight,paused,onDisplayingMenuChanged,onDisplayingMusicChanged,onMusicSelected, onPause) } } + + about( + aboutViewModel, + width75Percent, + images, + info + ) + + menuPrompt( + menuPromptViewModel, + aboutViewModel, + images, + menuItemHeight + ) + + if (!dismissedTutorial && (info.firstLaunch || resetTutorial) ){ + Image( + painter = painterResource(id = images["tutorial"]!!), + contentDescription = "", + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxWidth() + .clickable { + aboutViewModel.onDismissTutorial() + } + ) + }else if (showNews && !dismissedNews){ + Image( + painter = painterResource(id = images["news"]!!), + contentDescription = "", + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxWidth() + .clickable { + sppViewModel.onDismissNews() + } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/ui/view/SPPRenderer.kt b/app/src/main/java/app/jerboa/spp/ui/view/SPPRenderer.kt index 74a5b52..2eea551 100644 --- a/app/src/main/java/app/jerboa/spp/ui/view/SPPRenderer.kt +++ b/app/src/main/java/app/jerboa/spp/ui/view/SPPRenderer.kt @@ -34,11 +34,8 @@ enum class DRAG {START, STOP, CONTINUE} class SPPRenderer( private val resolution: Pair, - private val onAchievementStateChanged: (Pair) -> Unit, - private val onToyChanged: (TOY) -> Unit, - private val onRequestReview: () -> Unit, - private val onAdapt: (Float) -> Unit, - private val onUpdateClock: () -> Unit, + private val sppViewModel: SPPViewModel, + private val mainMenuViewModel: MainMenuViewModel, private var particleNumber: Float = PARTICLES_SLIDER_DEFAULT, private var allowAdapt: Boolean = true, private var colourMap: COLOUR_MAP = COLOUR_MAP.R1 @@ -401,7 +398,7 @@ class SPPRenderer( val toy = toySelected(wx, wy) if (toy != null) { touchEvent.draggedToy = toy - onToyChanged(toy.first) + mainMenuViewModel.onToyChanged(toy.first) touchEvent.dragPlacedToy = false } else { when (toyType) { @@ -410,7 +407,7 @@ class SPPRenderer( attractors.add(Pair(wx, wy)) } touchEvent.draggedToy = Pair(TOY.ATTRACTOR, attractors.sizeBack - 1) - onToyChanged(TOY.ATTRACTOR) + mainMenuViewModel.onToyChanged(TOY.ATTRACTOR) touchEvent.dragPlacedToy = true } @@ -419,7 +416,7 @@ class SPPRenderer( repellors.add(Pair(wx, wy)) } touchEvent.draggedToy = Pair(TOY.REPELLOR, repellors.sizeBack - 1) - onToyChanged(TOY.REPELLOR) + mainMenuViewModel.onToyChanged(TOY.REPELLOR) touchEvent.dragPlacedToy = true } @@ -428,7 +425,7 @@ class SPPRenderer( spinners.add(Pair(wx, wy)) } touchEvent.draggedToy = Pair(TOY.SPINNER, spinners.sizeBack - 1) - onToyChanged(TOY.SPINNER) + mainMenuViewModel.onToyChanged(TOY.SPINNER) touchEvent.dragPlacedToy = true } @@ -437,7 +434,7 @@ class SPPRenderer( freezers.add(Pair(wx, wy)) } touchEvent.draggedToy = Pair(TOY.FREEZER, freezers.sizeBack - 1) - onToyChanged(TOY.FREEZER) + mainMenuViewModel.onToyChanged(TOY.FREEZER) touchEvent.dragPlacedToy = true } @@ -446,7 +443,7 @@ class SPPRenderer( orbiters.add(Pair(wx, wy)) } touchEvent.draggedToy = Pair(TOY.ORBITER, orbiters.sizeBack - 1) - onToyChanged(TOY.ORBITER) + mainMenuViewModel.onToyChanged(TOY.ORBITER) touchEvent.dragPlacedToy = true } @@ -637,7 +634,7 @@ class SPPRenderer( newP = p reset = true - onAdapt(particleNumber) + mainMenuViewModel.onAdapt(particleNumber) } private fun compileDrawShader(){ @@ -1057,7 +1054,7 @@ class SPPRenderer( freezers.commit() orbiters.commit() - if (System.currentTimeMillis() - lastReviewRequest > REVIEW_RATE_LIMIT_MILLIS){onRequestReview(); lastReviewRequest = System.currentTimeMillis()} + if (System.currentTimeMillis() - lastReviewRequest > REVIEW_RATE_LIMIT_MILLIS){sppViewModel.onRequestingInAppReview(); lastReviewRequest = System.currentTimeMillis()} debugString = "" if (reset){ initGPUData() @@ -1146,7 +1143,7 @@ class SPPRenderer( deltas[frameNumber] = 1.0f / (delta.toFloat()*1e-9f) frameNumber += 1 if (frameNumber >= 60){ - onUpdateClock() + sppViewModel.onUpdateClock() frameNumber = 0 val mu = deltas.sum()/deltas.size if (PERFORMANCE){ @@ -1558,21 +1555,21 @@ class SPPRenderer( timeSinceLastTap += dt if (clock > 30f){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "AverageFan", clock.toInt() ) ) - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "AverageEnjoyer", clock.toInt() ) ) - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "SuperFan", clock.toInt() @@ -1587,7 +1584,7 @@ class SPPRenderer( spinners.sizeFront == maxOfOneToy && freezers.sizeFront == maxOfOneToy && orbiters.sizeFront == maxOfOneToy){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "ShowMeWhatYouGot", 1 @@ -1595,7 +1592,7 @@ class SPPRenderer( ) } if (!stillThereAchieved && timeSinceLastTap >= 60*10){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "StillThere", 1 @@ -1605,7 +1602,7 @@ class SPPRenderer( } if (!allParticlesOfScreenAchieved && allParticlesOfScreen){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "GetLost", 1 @@ -1615,7 +1612,7 @@ class SPPRenderer( } if (!insideAchieved && toyInsideAnother){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "DoubleTrouble", 1 @@ -1625,7 +1622,7 @@ class SPPRenderer( } if (!squareAchieved && toysInSquareFormation){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "HipToBeSquare", 1 @@ -1635,7 +1632,7 @@ class SPPRenderer( } if (!circleAchieved && toysInCircleFormation){ - onAchievementStateChanged( + sppViewModel.onAchievementStateChanged( Pair( "CirclesTheWay", 1 diff --git a/app/src/main/java/app/jerboa/spp/ui/view/SPPView.kt b/app/src/main/java/app/jerboa/spp/ui/view/SPPView.kt index 483dd3e..c347b43 100644 --- a/app/src/main/java/app/jerboa/spp/ui/view/SPPView.kt +++ b/app/src/main/java/app/jerboa/spp/ui/view/SPPView.kt @@ -8,32 +8,27 @@ import android.view.GestureDetector import android.view.MotionEvent import androidx.core.view.GestureDetectorCompat import app.jerboa.spp.viewmodel.COLOUR_MAP +import app.jerboa.spp.viewmodel.MainMenuViewModel import app.jerboa.spp.viewmodel.PARTICLES_SLIDER_DEFAULT +import app.jerboa.spp.viewmodel.SPPViewModel import app.jerboa.spp.viewmodel.TOY class SPPView ( context: Context, attr: AttributeSet? = null, private val resolution: Pair, - private val onDisplayingMenuChanged: (Boolean) -> Unit, - private val onAchievementStateChanged: (Pair) -> Unit, - private val onToyChanged: (TOY) -> Unit, - private val onRequestReview: () -> Unit, - private val onAdapt: (Float) -> Unit, - private val onUpdateClock: () -> Unit, + private val sppViewModel: SPPViewModel, + private val mainMenuViewModel: MainMenuViewModel, var placingToy: TOY = TOY.ATTRACTOR, var particleNumber: Float = PARTICLES_SLIDER_DEFAULT, - var allowAdapt: Boolean = true, - var colourMap: COLOUR_MAP = COLOUR_MAP.R1 + private var allowAdapt: Boolean = true, + private var colourMap: COLOUR_MAP = COLOUR_MAP.R1 ) : GLSurfaceView(context,attr), GestureDetector.OnGestureListener { private val renderer = SPPRenderer( resolution, - onAchievementStateChanged, - onToyChanged, - onRequestReview, - onAdapt, - onUpdateClock, + sppViewModel, + mainMenuViewModel, particleNumber, allowAdapt, colourMap diff --git a/app/src/main/java/app/jerboa/spp/viewmodel/aboutViewModel.kt b/app/src/main/java/app/jerboa/spp/viewmodel/aboutViewModel.kt new file mode 100644 index 0000000..35a1e1c --- /dev/null +++ b/app/src/main/java/app/jerboa/spp/viewmodel/aboutViewModel.kt @@ -0,0 +1,43 @@ +package app.jerboa.spp.viewmodel + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +enum class SOCIAL {NOTHING, WEB, PLAY, YOUTUBE, GITHUB} + +class AboutViewModel : ViewModel() { + + private val _dismissedTutorial = MutableLiveData(false) + private val _resetTutorial = MutableLiveData(false) + + val dismissedTutorial: MutableLiveData = _dismissedTutorial + val resetTutorial: MutableLiveData = _resetTutorial + + fun onResetTutorial(){ + _resetTutorial.value = true; _dismissedTutorial.value = false + //onDisplayingMenuChanged(false) + } + fun onDismissTutorial(){_dismissedTutorial.value = true; _resetTutorial.value = false} + + + private val _requestingLicenses = MutableLiveData(false) + val requestingLicenses: MutableLiveData = _requestingLicenses + + fun onRequestingLicenses(){ + _requestingLicenses.value = true + } + + private val _displayingAbout = MutableLiveData(false) + val displayingAbout: MutableLiveData = _displayingAbout + + fun onDisplayingAboutChanged(newVal: Boolean){ + _displayingAbout.value = newVal + } + + private val _requestingSocial = MutableLiveData(SOCIAL.NOTHING) + val requestingSocial: MutableLiveData = _requestingSocial + + fun onRequestingSocial(v: SOCIAL){ + _requestingSocial.value = v + } +} \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/viewmodel/mainMenuViewModel.kt b/app/src/main/java/app/jerboa/spp/viewmodel/mainMenuViewModel.kt new file mode 100644 index 0000000..9282d11 --- /dev/null +++ b/app/src/main/java/app/jerboa/spp/viewmodel/mainMenuViewModel.kt @@ -0,0 +1,156 @@ +package app.jerboa.spp.viewmodel + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import java.util.Calendar + +const val MAX_PARTICLES = 500000f +const val PARTICLES_SLIDER_DEFAULT = 100000f/ MAX_PARTICLES +const val MAX_LOG_SPEED = 0.30103f +const val MAX_LOG_FADE = 0.0f +const val MIN_LOG_FADE = -2.0f +const val MIN_LOG_MASS = -3f +const val MAX_LOG_MASS = 0.5f +const val MIN_LOG_AR = 1f +const val MAX_LOG_AR = 6f +const val MAX_LOG_ORBIT = 0.30103f +const val MIN_LOG_ORBIT = -1f +const val MAX_LOG_SPIN = 4.0f +const val MIN_LOG_SPIN = 2f + +enum class COLOUR_MAP { + R1, + R2, + ACE, + C3, + CB1, + CB2, + TRANS, + PRIDE +} + +enum class TOY {ATTRACTOR,REPELLOR,SPINNER,FREEZER,ORBITER, NOTHING} + +enum class PARAM {MASS, SPEED, ATTRACTION, REPULSION, ORBIT, SPIN, PARTICLES, FADE} + + +class MainMenuViewModel: ViewModel() { + private val _colourMap = MutableLiveData(COLOUR_MAP.R1) + val colourMap: MutableLiveData = _colourMap + + fun onSelectColourMap(v: COLOUR_MAP){ + _colourMap.value = v + } + + private val _selectedDefaultColourMap = MutableLiveData(false) + + fun selectDefaultColourMap(){ + + if (_selectedDefaultColourMap.value == false){return} + + val date = Calendar.getInstance() + val month = date.get(Calendar.MONTH) + val day = date.get(Calendar.DAY_OF_MONTH) + + if (month == Calendar.MARCH && day == 31){ + _colourMap.value = COLOUR_MAP.TRANS + } + else if (month == Calendar.JUNE && day == 28){ + _colourMap.value = COLOUR_MAP.PRIDE + } + else if (month == Calendar.APRIL && day == 6){ + _colourMap.value = COLOUR_MAP.ACE + } + + _selectedDefaultColourMap.value = true + } + + private val _toy = MutableLiveData(TOY.ATTRACTOR) // true attractor, false repeller + val toy: MutableLiveData = _toy + fun onToyChanged(newVal: TOY){ + //Log.d("on attractor changed", newVal.toString()) + _toy.value = newVal + } + + // sliders + + private val _particleNumber = MutableLiveData(PARTICLES_SLIDER_DEFAULT) + val particleNumber: MutableLiveData = _particleNumber + + private val _speed = MutableLiveData(1.0f) + val speed: MutableLiveData = _speed + + private val _fade = MutableLiveData(1.0f) + val fade: MutableLiveData = _fade + + private val _attractorStrength = MutableLiveData(50000.0f) + val attractorStrength: MutableLiveData = _attractorStrength + + private val _repellorStrength = MutableLiveData(50000.0f) + val repellorStrength: MutableLiveData = _repellorStrength + + private val _mass = MutableLiveData(0.1f) + val mass: MutableLiveData = _mass + + private val _orbit = MutableLiveData(0.5f) + val orbitStrength: MutableLiveData = _orbit + + private val _spin = MutableLiveData(1500f) + val spinStrength: MutableLiveData = _spin + + fun onParameterChanged(v: Pair){ + when (v.second) { + PARAM.PARTICLES -> { + _particleNumber.value = v.first + } + PARAM.SPEED -> { + _speed.value = v.first + } + PARAM.FADE -> { + _fade.value = v.first + } + PARAM.ATTRACTION -> { + _attractorStrength.value = v.first + } + PARAM.REPULSION -> { + _repellorStrength.value = v.first + } + PARAM.MASS -> { + _mass.value = v.first + } + PARAM.ORBIT -> { + _orbit.value = v.first + } + PARAM.SPIN -> { + _spin.value = v.first + } + } + } + + private val _showToys = MutableLiveData(false) + val showToys: MutableLiveData = _showToys + + fun onShowToysChanged(v: Boolean){ + _showToys.value = v + } + + // ADAPT + + private val _allowAdapt = MutableLiveData(true) + private val _autoAdaptMessage = MutableLiveData(false) + val allowAdapt: MutableLiveData = _allowAdapt + val autoAdaptMessage: MutableLiveData = _autoAdaptMessage + + fun onAdapt(v: Float) { + _particleNumber.postValue(v) + _autoAdaptMessage.postValue(true) + } + + fun onAllowAdaptChanged(){ + _allowAdapt.value = !_allowAdapt.value!! + } + + fun onAdaptMessageShown(){ + _autoAdaptMessage.value = false + } +} \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/viewmodel/menuPromptViewModel.kt b/app/src/main/java/app/jerboa/spp/viewmodel/menuPromptViewModel.kt new file mode 100644 index 0000000..5bc668d --- /dev/null +++ b/app/src/main/java/app/jerboa/spp/viewmodel/menuPromptViewModel.kt @@ -0,0 +1,49 @@ +package app.jerboa.spp.viewmodel + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +enum class MUSIC {FORREST, RAIN, NOTHING} + +class MenuPromptViewModel : ViewModel() { + + private val _displayingMenu = MutableLiveData(false) + val displayingMenu : MutableLiveData = _displayingMenu + + //private val _lastClick = MutableLiveData(0L) + fun onDisplayingMenuChanged(newVal: Boolean){ + _displayingMenu.value = newVal + + if (_displayingMenu.value == true){ + _displayingSound.value = false + } + + //_lastClick.value = System.currentTimeMillis() + + } + + private val _displayingSound = MutableLiveData(false) + val displayingSound: MutableLiveData = _displayingSound + fun onDisplayingMusicChanged(newVal: Boolean){ + _displayingSound.value = newVal + if (_displayingSound.value == true){ + _displayingMenu.value = false + } + } + + private val _playingMusic = MutableLiveData(MUSIC.NOTHING) + val playingMusic: MutableLiveData = _playingMusic + + fun onMusicSelected(v: MUSIC){ + _playingMusic.value = v + } + + private val _paused = MutableLiveData(false) + val paused: MutableLiveData = _paused + + fun onPause() + { + _paused.postValue(!_paused.value!!) + } + +} \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/viewmodel/renderViewModel.kt b/app/src/main/java/app/jerboa/spp/viewmodel/renderViewModel.kt deleted file mode 100644 index 12642cb..0000000 --- a/app/src/main/java/app/jerboa/spp/viewmodel/renderViewModel.kt +++ /dev/null @@ -1,391 +0,0 @@ -package app.jerboa.spp.viewmodel - -import android.media.MediaPlayer -import android.util.Log -import androidx.lifecycle.* -import app.jerboa.spp.incrementable -import java.util.* - -const val MAX_PARTICLES = 500000f -const val PARTICLES_SLIDER_DEFAULT = 100000f/ MAX_PARTICLES -const val MAX_LOG_SPEED = 0.30103f -const val MAX_LOG_FADE = 0.0f -const val MIN_LOG_FADE = -2.0f -const val MIN_LOG_MASS = -3f -const val MAX_LOG_MASS = 0.5f -const val MIN_LOG_AR = 1f -const val MAX_LOG_AR = 6f -const val MAX_LOG_ORBIT = 0.30103f -const val MIN_LOG_ORBIT = -1f -const val MAX_LOG_SPIN = 4.0f -const val MIN_LOG_SPIN = 2f -enum class COLOUR_MAP { - R1, - R2, - ACE, - C3, - CB1, - CB2, - TRANS, - PRIDE -} - -enum class MUSIC {FORREST, RAIN, NOTHING} - -enum class TOY {ATTRACTOR,REPELLOR,SPINNER,FREEZER,ORBITER, NOTHING} - -enum class PARAM {MASS, SPEED, ATTRACTION, REPULSION, ORBIT, SPIN, PARTICLES, FADE} - -enum class SOCIAL {NOTHING, WEB, PLAY, YOUTUBE, GITHUB} - -const val REVIEW_RATE_LIMIT_MILLIS = 1000*60*30 - -class RenderViewModel : ViewModel() { - - // pausing - - private val _paused = MutableLiveData(false) - val paused: MutableLiveData = _paused - - fun onPause() - { - _paused.postValue(!_paused.value!!) - } - - // clock - private val _clockTicking = MutableLiveData(true) - private val _lastClock = MutableLiveData(System.currentTimeMillis()) - private val _playTime = MutableLiveData(0L) - val playTime: MutableLiveData = _playTime - - fun stopClock() { - _clockTicking.postValue(false) - } - - fun startClock() { - if (!_clockTicking.value!!) { - _clockTicking.postValue(true) - _lastClock.postValue(System.currentTimeMillis()) - } - } - - fun onUpdateClock() - { - if (_clockTicking.value!!) { - _playTime.postValue(_playTime.value!! + (System.currentTimeMillis() - _lastClock.value!!)) - } - _lastClock.postValue(System.currentTimeMillis()) - } - - // review api - private val _canReview = MutableLiveData(true) - private val _requestingInAppReview = MutableLiveData(false) - val requestingInAppReview: MutableLiveData = _requestingInAppReview - private val _lastReviewRequestTime = MutableLiveData(System.currentTimeMillis()) - - fun onRequestingInAppReview(){ - Log.d("onRequestingInAppReview","called") - if (System.currentTimeMillis() - _lastReviewRequestTime.value!! > REVIEW_RATE_LIMIT_MILLIS && _canReview.value!!) { - Log.d("onRequestingInAppReview","calling API") - _requestingInAppReview.postValue(true) - _lastReviewRequestTime.postValue(System.currentTimeMillis()) - } - } - - fun onInAppReviewShown(){ - _requestingInAppReview.value = false - _canReview.value = false - } - - private val musicPlayer: MediaPlayer = MediaPlayer() - - private val _achievementStates = MutableLiveData( - mapOf( - "GetLost" to Pair(0,0), - "SuperFan" to Pair(0,0), - "ShowMeWhatYouGot" to Pair(0,0), - "AverageFan" to Pair(0,0), - "AverageEnjoyer" to Pair(0,0), - "StillThere" to Pair(0,0), - "HipToBeSquare" to Pair(0,0), - "CirclesTheWay" to Pair(0,0), - "DoubleTrouble" to Pair(0,0) - ) - ) - - val achievementStates: MutableLiveData>> = _achievementStates - - // TUTORIAL - - private val _dismissedTutorial = MutableLiveData(false) - private val _resetTutorial = MutableLiveData(false) - - val dismissedTutorial: MutableLiveData = _dismissedTutorial - val resetTutorial: MutableLiveData = _resetTutorial - - fun onResetTutorial(){ - _resetTutorial.value = true; _dismissedTutorial.value = false - onDisplayingMenuChanged(false) - } - fun onDismissTutorial(){_dismissedTutorial.value = true; _resetTutorial.value = false} - - private val _dismissedNews = MutableLiveData(false) - val dismissedNews: MutableLiveData = _dismissedNews - fun onDismissNews(){_dismissedNews.value = true} - - // SOCIAL - private val _requestingSocial = MutableLiveData(SOCIAL.NOTHING) - val requestingSocial: MutableLiveData = _requestingSocial - - fun onRequestingSocial(v: SOCIAL){ - _requestingSocial.value = v - } - - // menu displays - - private val _displayingMenu = MutableLiveData(false) - private val _displayingSound = MutableLiveData(false) - private val _displayingAbout = MutableLiveData(false) - - val displayingSound: MutableLiveData = _displayingSound - val displayingMenu : MutableLiveData = _displayingMenu - val displayingAbout: MutableLiveData = _displayingAbout - - private val _lastClick = MutableLiveData(0L) - - fun onDisplayingMenuChanged(newVal: Boolean){ - _displayingMenu.value = !_displayingMenu.value!! - if (_displayingMenu.value == false){ - _displayingAbout.value = false - } - - if (_displayingMenu.value == true){ - _displayingSound.value = false - } - - _lastClick.value = System.currentTimeMillis() - - } - - fun onDisplayingMusicChanged(){ - _displayingSound.value = !_displayingSound.value!! - if (_displayingSound.value == true){ - _displayingMenu.value = false - _displayingAbout.value = false - } - } - - fun onDisplayingAboutChanged(newVal: Boolean){ - _displayingAbout.value = !_displayingAbout.value!! - } - - // MUSIC - - private val _playingMusic = MutableLiveData(MUSIC.NOTHING) - val playingMusic: MutableLiveData = _playingMusic - - fun onMusicSelected(v: MUSIC){ - _playingMusic.value = v - } - // COLOUR - - private val _colourMap = MutableLiveData(COLOUR_MAP.R1) - val colourMap: MutableLiveData = _colourMap - - fun onSelectColourMap(v: COLOUR_MAP){ - _colourMap.value = v - } - - private val _selectedDefaultColourMap = MutableLiveData(false) - - fun selectDefaultColourMap(){ - - if (_selectedDefaultColourMap.value == false){return} - - val date = Calendar.getInstance() - val month = date.get(Calendar.MONTH) - val day = date.get(Calendar.DAY_OF_MONTH) - - if (month == Calendar.MARCH && day == 31){ - _colourMap.value = COLOUR_MAP.TRANS - } - else if (month == Calendar.JUNE && day == 28){ - _colourMap.value = COLOUR_MAP.PRIDE - } - else if (month == Calendar.APRIL && day == 6){ - _colourMap.value = COLOUR_MAP.ACE - } - - _selectedDefaultColourMap.value = true - } - - private val _toy = MutableLiveData(TOY.ATTRACTOR) // true attractor, false repeller - val toy: MutableLiveData = _toy - fun onToyChanged(newVal: TOY){ - //Log.d("on attractor changed", newVal.toString()) - _toy.value = newVal - } - - // PGS - - private val _requestingPlayServices = MutableLiveData(false) - val requestingPlayServices: MutableLiveData = _requestingPlayServices - - fun onRequestPlayServices(){ - _requestingPlayServices.value = true - } - - fun onRequestPGSAndNotInstalled(){ - _promptInstallPGS.value = true - } - - fun onPromptInstallPGS(v: Boolean = false){ - _promptInstallPGS.value = false - if (v) { - _requestingInstallPGS.value = true - } - } - - fun onInstallPGSInitiated(){ - _requestingInstallPGS.value = false - } - - private val _promptInstallPGS = MutableLiveData(false) - val promptInstallPGS: MutableLiveData = _promptInstallPGS - - private val _requestingInstallPGS = MutableLiveData(false) - val requestingInstallPGS: MutableLiveData = _requestingInstallPGS - - private val _requestingLicenses = MutableLiveData(false) - val requestingLicenses: MutableLiveData = _requestingLicenses - - fun onRequestingLicenses(){ - _requestingLicenses.value = true - } - - private val _playSuccess = MutableLiveData(false) - val playSuccess: MutableLiveData = _playSuccess - - fun onPlaySuccess(v: Boolean) - { - _playSuccess.postValue(v) - } - - // sliders - - private val _particleNumber = MutableLiveData(PARTICLES_SLIDER_DEFAULT) - val particleNumber: MutableLiveData = _particleNumber - - private val _speed = MutableLiveData(1.0f) - val speed: MutableLiveData = _speed - - private val _fade = MutableLiveData(1.0f) - val fade: MutableLiveData = _fade - - private val _attractorStrength = MutableLiveData(50000.0f) - val attractorStrength: MutableLiveData = _attractorStrength - - private val _repellorStrength = MutableLiveData(50000.0f) - val repellorStrength: MutableLiveData = _repellorStrength - - private val _mass = MutableLiveData(0.1f) - val mass: MutableLiveData = _mass - - private val _orbit = MutableLiveData(0.5f) - val orbitStrength: MutableLiveData = _orbit - - private val _spin = MutableLiveData(1500f) - val spinStrength: MutableLiveData = _spin - - fun onParameterChanged(v: Pair){ - when (v.second) { - PARAM.PARTICLES -> { - _particleNumber.value = v.first - } - PARAM.SPEED -> { - _speed.value = v.first - } - PARAM.FADE -> { - _fade.value = v.first - } - PARAM.ATTRACTION -> { - _attractorStrength.value = v.first - } - PARAM.REPULSION -> { - _repellorStrength.value = v.first - } - PARAM.MASS -> { - _mass.value = v.first - } - PARAM.ORBIT -> { - _orbit.value = v.first - } - PARAM.SPIN -> { - _spin.value = v.first - } - } - - } - - private val _showToys = MutableLiveData(false) - val showToys: MutableLiveData = _showToys - - fun onShowToysChanged(v: Boolean){ - _showToys.value = v - } - - // ADAPT - - private val _allowAdapt = MutableLiveData(true) - private val _autoAdaptMessage = MutableLiveData(false) - val allowAdapt: MutableLiveData = _allowAdapt - val autoAdaptMessage: MutableLiveData = _autoAdaptMessage - - fun onAdapt(v: Float) { - _particleNumber.postValue(v) - _autoAdaptMessage.postValue(true) - } - - fun onAllowAdaptChanged(){ - _allowAdapt.value = !_allowAdapt.value!! - } - - fun onAdaptMessageShown(){ - _autoAdaptMessage.value = false - } - - fun onAchievementStateChanged(data: Pair){ - //Log.d("achievements", data.toString()) - val ach = data.first - val value = data.second - - val state = _achievementStates.value!!.toMutableMap() - - if (!state.containsKey(ach)){ - Log.e("achievement state does not contain key",ach) - return - } - - if (state[ach]!!.first == state[ach]!!.second){ - return - } - - if (ach in incrementable) { - state[ach] = Pair( - achievementStates.value!![ach]!!.first + value, - achievementStates.value!![ach]!!.second - ) - } - else{ - state[ach] = Pair(1,1) - } - - _achievementStates.postValue(state.toMap()) - } - - fun setAchievementState(states: MutableMap>){ - _achievementStates.value = states - achievementStates.value = states - } - -} \ No newline at end of file diff --git a/app/src/main/java/app/jerboa/spp/viewmodel/sppViewModel.kt b/app/src/main/java/app/jerboa/spp/viewmodel/sppViewModel.kt new file mode 100644 index 0000000..b16bc7a --- /dev/null +++ b/app/src/main/java/app/jerboa/spp/viewmodel/sppViewModel.kt @@ -0,0 +1,151 @@ +package app.jerboa.spp.viewmodel + +import android.media.MediaPlayer +import android.util.Log +import androidx.lifecycle.* +import app.jerboa.spp.incrementable +import java.util.* + +const val REVIEW_RATE_LIMIT_MILLIS = 1000*60*30 + +class SPPViewModel : ViewModel() { + // clock + private val _clockTicking = MutableLiveData(true) + private val _lastClock = MutableLiveData(System.currentTimeMillis()) + private val _playTime = MutableLiveData(0L) + val playTime: MutableLiveData = _playTime + + fun stopClock() { + _clockTicking.postValue(false) + } + + fun startClock() { + if (!_clockTicking.value!!) { + _clockTicking.postValue(true) + _lastClock.postValue(System.currentTimeMillis()) + } + } + + fun onUpdateClock() + { + if (_clockTicking.value!!) { + _playTime.postValue(_playTime.value!! + (System.currentTimeMillis() - _lastClock.value!!)) + } + _lastClock.postValue(System.currentTimeMillis()) + } + + // review api + private val _canReview = MutableLiveData(true) + private val _requestingInAppReview = MutableLiveData(false) + val requestingInAppReview: MutableLiveData = _requestingInAppReview + private val _lastReviewRequestTime = MutableLiveData(System.currentTimeMillis()) + + fun onRequestingInAppReview(){ + Log.d("onRequestingInAppReview","called") + if (System.currentTimeMillis() - _lastReviewRequestTime.value!! > REVIEW_RATE_LIMIT_MILLIS && _canReview.value!!) { + Log.d("onRequestingInAppReview","calling API") + _requestingInAppReview.postValue(true) + _lastReviewRequestTime.postValue(System.currentTimeMillis()) + } + } + + fun onInAppReviewShown(){ + _requestingInAppReview.value = false + _canReview.value = false + } + + private val _achievementStates = MutableLiveData( + mapOf( + "GetLost" to Pair(0,0), + "SuperFan" to Pair(0,0), + "ShowMeWhatYouGot" to Pair(0,0), + "AverageFan" to Pair(0,0), + "AverageEnjoyer" to Pair(0,0), + "StillThere" to Pair(0,0), + "HipToBeSquare" to Pair(0,0), + "CirclesTheWay" to Pair(0,0), + "DoubleTrouble" to Pair(0,0) + ) + ) + + val achievementStates: MutableLiveData>> = _achievementStates + + // TUTORIAL + + private val _dismissedNews = MutableLiveData(false) + val dismissedNews: MutableLiveData = _dismissedNews + fun onDismissNews(){_dismissedNews.value = true} + + // PGS + + private val _requestingPlayServices = MutableLiveData(false) + val requestingPlayServices: MutableLiveData = _requestingPlayServices + + fun onRequestPlayServices(){ + _requestingPlayServices.value = true + } + + fun onRequestPGSAndNotInstalled(){ + _promptInstallPGS.value = true + } + + fun onPromptInstallPGS(v: Boolean = false){ + _promptInstallPGS.value = false + if (v) { + _requestingInstallPGS.value = true + } + } + + fun onInstallPGSInitiated(){ + _requestingInstallPGS.value = false + } + + private val _promptInstallPGS = MutableLiveData(false) + val promptInstallPGS: MutableLiveData = _promptInstallPGS + + private val _requestingInstallPGS = MutableLiveData(false) + val requestingInstallPGS: MutableLiveData = _requestingInstallPGS + + private val _playSuccess = MutableLiveData(false) + val playSuccess: MutableLiveData = _playSuccess + + fun onPlaySuccess(v: Boolean) + { + _playSuccess.postValue(v) + } + + fun onAchievementStateChanged(data: Pair){ + //Log.d("achievements", data.toString()) + val ach = data.first + val value = data.second + + val state = _achievementStates.value!!.toMutableMap() + + if (!state.containsKey(ach)){ + Log.e("achievement state does not contain key",ach) + return + } + + if (state[ach]!!.first == state[ach]!!.second){ + return + } + + if (ach in incrementable) { + state[ach] = Pair( + achievementStates.value!![ach]!!.first + value, + achievementStates.value!![ach]!!.second + ) + } + else{ + state[ach] = Pair(1,1) + } + + _achievementStates.postValue(state.toMap()) + } + + fun setAchievementState(states: MutableMap>){ + _achievementStates.value = states + achievementStates.value = states + } + +} \ No newline at end of file diff --git a/store/icon.png b/store/icon.png index 8da88d8..5053c3f 100644 Binary files a/store/icon.png and b/store/icon.png differ diff --git a/store/icon.svg b/store/icon.svg index 2b8f9d6..b5b987a 100644 --- a/store/icon.svg +++ b/store/icon.svg @@ -9,7 +9,7 @@ id="svg5" inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" sodipodi:docname="icon.svg" - inkscape:export-filename="/home/jerboa/SPP/icon.png" + inkscape:export-filename="/home/jerboa/Games/Android/Particles/store/icon.png" inkscape:export-xdpi="84.89595" inkscape:export-ydpi="84.89595" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" @@ -19,11 +19,11 @@ xmlns:svg="http://www.w3.org/2000/svg">