Skip to content

Commit

Permalink
Add particles sizes slider
Browse files Browse the repository at this point in the history
Refactor sliders

Adds play controller to vertical menu
  • Loading branch information
Jerboa-app committed Aug 17, 2024
1 parent 1b89d9d commit e41c5d6
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 117 deletions.
19 changes: 19 additions & 0 deletions app/src/main/java/app/jerboa/spp/composable/menuPrompt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.animation.fadeOut
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
Expand All @@ -21,19 +22,22 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import app.jerboa.spp.viewmodel.AboutViewModel
import app.jerboa.spp.viewmodel.MenuPromptViewModel
import app.jerboa.spp.viewmodel.SPPViewModel

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun menuPrompt(
menuPromptViewModel: MenuPromptViewModel,
aboutViewModel: AboutViewModel,
sppViewModel: SPPViewModel,
images: Map<String,Int>,
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 playSuccess: Boolean by sppViewModel.playSuccess.observeAsState(initial = false)

val fadePromptAlpha: Float by animateFloatAsState(
targetValue = if (!displayingMenu) 0.33f else 1.0f,
Expand Down Expand Up @@ -139,6 +143,21 @@ fun menuPrompt(
}
)
)
IconButton(onClick = { sppViewModel.onRequestPlayServices() }) {
Image(
modifier = Modifier
.size(menuItemHeight.dp)
.alpha(
if (playSuccess) {
0.66f
} else {
1f
}
),
painter = painterResource(id = images["play-controller"]!!),
contentDescription = "play"
)
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/app/jerboa/spp/composable/screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ fun screen(
val spin: Float by toyMenuViewModel.spinStrength.observeAsState(1500f)
val mass: Float by toyMenuViewModel.mass.observeAsState(0.1f)
val fade: Float by toyMenuViewModel.fade.observeAsState(initial = 1.0f)
val scale: Float by toyMenuViewModel.scale.observeAsState(initial = 3f)
val showToys: Boolean by toyMenuViewModel.showToys.observeAsState(initial = false)

val promptPGS: Boolean by sppViewModel.promptInstallPGS.observeAsState(initial = false)
Expand All @@ -81,8 +82,6 @@ fun screen(
bottomBar = {
toyMenu(
toyMenuViewModel,
sppViewModel,
aboutViewModel,
displayingToyMenu,
width75Percent,
height10Percent,
Expand Down Expand Up @@ -152,6 +151,7 @@ fun screen(
view.setOrbit(orbit)
view.setSpin(spin)
view.setFade(fade)
view.setScale(scale)
view.showToys(showToys)
if (clear) { view.clearToys(); menuPromptViewModel.onClear(false); }
}
Expand All @@ -169,6 +169,7 @@ fun screen(
menuPrompt(
menuPromptViewModel,
aboutViewModel,
sppViewModel,
images,
menuItemHeight
)
Expand Down
156 changes: 50 additions & 106 deletions app/src/main/java/app/jerboa/spp/composable/toyMenu.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package app.jerboa.spp.composable

import android.util.Log
import androidx.compose.animation.*
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
Expand Down Expand Up @@ -31,11 +32,13 @@ import app.jerboa.spp.viewmodel.MAX_LOG_ORBIT
import app.jerboa.spp.viewmodel.MAX_LOG_SPEED
import app.jerboa.spp.viewmodel.MAX_LOG_SPIN
import app.jerboa.spp.viewmodel.MAX_PARTICLES
import app.jerboa.spp.viewmodel.MAX_SCALE
import app.jerboa.spp.viewmodel.MIN_LOG_AR
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.MIN_SCALE
import app.jerboa.spp.viewmodel.ToyMenuViewModel
import app.jerboa.spp.viewmodel.PARAM
import app.jerboa.spp.viewmodel.PARTICLES_SLIDER_DEFAULT
Expand Down Expand Up @@ -69,32 +72,31 @@ fun label(
}

@Composable
fun logSlider(
fun slider(
v: Float,
min: Float,
max: Float,
name: String,
onChange: (Float) -> Unit,
width75Percent: Double
width75Percent: Double,
label: (Float) -> String = {v: Float -> "${round(10.0f.pow(v) * 100.0f) / 100.0f}"},
postValue: (Float) -> Float = {v: Float -> 10.0f.pow(v)},
steps: Int = 100
) {

var sliderValue by remember {
mutableFloatStateOf(log10(v))
mutableFloatStateOf(v)
}

label(text = "$name " + "${round(10.0f.pow(sliderValue) * 100.0f) / 100.0f}")
label(text = "$name " + label(sliderValue))
Slider(
value = sliderValue,
onValueChange = { sliderValue = it },
onValueChangeFinished = {
onChange(
10.0f.pow(
sliderValue
)
)
onChange(postValue(sliderValue))
},
valueRange = min..max,
steps = 100,
steps = steps,
modifier = Modifier
.width(width75Percent.dp * 0.75f)
.background(color = Color(1, 1, 1, 1))
Expand All @@ -104,16 +106,13 @@ fun logSlider(
@Composable
fun toyMenu(
toyMenuViewModel: ToyMenuViewModel,
sppViewModel: SPPViewModel,
aboutViewModel: AboutViewModel,
displayingMenu: Boolean,
width75Percent: Double,
height10Percent: Double,
menuItemHeight: Double,
images: Map<String,Int>
) {

val playSuccess: Boolean by sppViewModel.playSuccess.observeAsState(initial = false)
val particleNumber: Float by toyMenuViewModel.particleNumber.observeAsState(initial = PARTICLES_SLIDER_DEFAULT)
val speed: Float by toyMenuViewModel.speed.observeAsState(initial = 1.0f)
val attraction: Float by toyMenuViewModel.attractorStrength.observeAsState(50000f)
Expand All @@ -122,16 +121,9 @@ fun toyMenu(
val spin: Float by toyMenuViewModel.spinStrength.observeAsState(1500f)
val mass: Float by toyMenuViewModel.mass.observeAsState(0.1f)
val fade: Float by toyMenuViewModel.fade.observeAsState(initial = 1.0f)
val scale: Float by toyMenuViewModel.scale.observeAsState(initial = 3.0f)
val showToys: Boolean by toyMenuViewModel.showToys.observeAsState(initial = false)

var particleSliderValue by remember {
mutableFloatStateOf(log10(particleNumber))
}

var fadeSliderValue by remember {
mutableFloatStateOf(log10(fade))
}

var showToysValue by remember {
mutableStateOf(showToys)
}
Expand All @@ -156,47 +148,6 @@ fun toyMenu(
modifier = Modifier.fillMaxWidth(),
) {
colourMapMenu(images, menuItemHeight) { toyMenuViewModel.onSelectColourMap(it) }

Box(
modifier = Modifier
.fillMaxWidth()
.height((menuItemHeight).dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
IconButton(onClick = { sppViewModel.onRequestPlayServices() }) {
Image(
modifier = Modifier
.fillMaxHeight()
.size(menuItemHeight.dp)
.alpha(
if (playSuccess) {
0.66f
} else {
1f
}
),
painter = painterResource(id = images["play-controller"]!!),
contentDescription = "play"
)
}
IconButton(onClick = { aboutViewModel.onDisplayingAboutChanged(true) }) {
Image(
modifier = Modifier
.fillMaxHeight()
.size(menuItemHeight.dp)
.padding(2.dp),
painter = painterResource(id = images["about"]!!),
contentDescription = "Image"
)
}
}
}
Box(
Modifier
.width(width75Percent.dp)
Expand Down Expand Up @@ -280,70 +231,63 @@ fun toyMenu(
.verticalScroll(scroll)
.verticalScrollBar(scroll, false)
) {
label(text = "Particles " + ceil(particleNumber * MAX_PARTICLES).toInt())
Slider(
value = particleSliderValue,
onValueChange = { particleSliderValue = it },
onValueChangeFinished = {
toyMenuViewModel.onParameterChanged(
Pair(
10.0f.pow(
particleSliderValue
),
PARAM.PARTICLES
)
)
},
valueRange = -3.0f..0.0f,
steps = 100,
modifier = Modifier
.width(width75Percent.dp * 0.75f)
.background(color = Color(1, 1, 1, 1))
slider(
log10(particleNumber),
-6.0f,
0.0f,
"Particles",
{toyMenuViewModel.onParameterChanged(Pair(it, PARAM.PARTICLES))},
width75Percent,
label = {v: Float -> "${ceil(10.0f.pow(v) * MAX_PARTICLES).toInt()}"}
)
Spacer(modifier = Modifier.size(8.dp))
slider(
scale,
MIN_SCALE,
MAX_SCALE,
"Size",
{toyMenuViewModel.onParameterChanged(Pair(it, PARAM.SCALE))},
width75Percent,
label = {v: Float -> "$v"},
postValue = {v: Float -> v}
)
Spacer(modifier = Modifier.size(8.dp))
logSlider(speed, -3.0f, MAX_LOG_SPEED, "Speed", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.SPEED))}, width75Percent)
slider(log10(speed), -3.0f, MAX_LOG_SPEED, "Speed", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.SPEED))}, width75Percent)
Spacer(modifier = Modifier.size(8.dp))
logSlider(
attraction,
slider(
log10(attraction),
MIN_LOG_AR,
MAX_LOG_AR,
"Attraction",
{toyMenuViewModel.onParameterChanged(Pair(it, PARAM.ATTRACTION))},
width75Percent
)
Spacer(modifier = Modifier.size(8.dp))
logSlider(
repulsion,
slider(
log10(repulsion),
MIN_LOG_AR,
MAX_LOG_AR,
"Repulsion",
{toyMenuViewModel.onParameterChanged(Pair(it, PARAM.REPULSION))},
width75Percent
)
Spacer(modifier = Modifier.size(8.dp))
logSlider(orbit, MIN_LOG_ORBIT, MAX_LOG_ORBIT, "Orbit", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.ORBIT))}, width75Percent)
slider(log10(orbit), MIN_LOG_ORBIT, MAX_LOG_ORBIT, "Orbit", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.ORBIT))}, width75Percent)
Spacer(modifier = Modifier.size(8.dp))
logSlider(spin, MIN_LOG_SPIN, MAX_LOG_SPIN, "Spin", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.SPIN))}, width75Percent)
slider(log10(spin), MIN_LOG_SPIN, MAX_LOG_SPIN, "Spin", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.SPIN))}, width75Percent)
Spacer(modifier = Modifier.size(8.dp))
logSlider(mass, MIN_LOG_MASS, MAX_LOG_MASS, "Mass", {toyMenuViewModel.onParameterChanged(Pair(it, PARAM.MASS))}, width75Percent)
slider(log10(mass), MIN_LOG_MASS, MAX_LOG_MASS, "Mass", {toyMenuViewModel.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 = {
toyMenuViewModel.onParameterChanged(
Pair(
10.0f.pow((1.0f - fadeSliderValue) * (MAX_LOG_FADE - MIN_LOG_FADE) + MIN_LOG_FADE),
PARAM.FADE
)
)
},
valueRange = 0.0f..1.0f,
steps = 100,
modifier = Modifier
.width(width75Percent.dp * 0.75f)
.background(color = Color(1, 1, 1, 1))
Log.d("fade", "$fade")
slider(
fade,
10.0f.pow(MIN_LOG_FADE),
10.0f.pow(MAX_LOG_FADE),
"Tracing",
{toyMenuViewModel.onParameterChanged(Pair(it, PARAM.FADE))},
width75Percent,
postValue = {v: Float -> v},
label = {v: Float -> "${(v-10.0f.pow(MIN_LOG_FADE))/(10.0f.pow(MAX_LOG_FADE)-10.0f.pow(MIN_LOG_FADE))}"}
)
Spacer(modifier = Modifier.size(8.dp))
label(text = "Show Toys")
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/app/jerboa/spp/data/fade.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ data class FadeShaderData(
"uniform float fadeRate;\n"+
"out vec4 colour;\n"+
"void main(void){\n"+
" colour = vec4(0.0,0.0,0.0,fadeRate);\n"+
" colour = vec4(0.0,0.0,0.0,1.0-fadeRate);\n"+
"}")
: ShaderData(vertexShader,fragmentShader)
6 changes: 3 additions & 3 deletions app/src/main/java/app/jerboa/spp/data/particleShaders.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ data class ParticleDrawShaderData(
"out vec4 colour;\n"+
"void main(void){\n"+
"vec2 circCoord = 2.0 * gl_PointCoord - 1.0;"+
//"float dd = length(circCoord);\n"+
//"float alpha = 1.0-smoothstep(0.9,1.1,dd);\n"+
"colour = vec4(o_colour.rgb,transitionAlpha);\n"+
"float dd = length(circCoord);\n"+
"float alpha = 1.0-smoothstep(0.9,1.1,dd);\n"+
"colour = vec4(o_colour.rgb,alpha*transitionAlpha);\n"+
"if (colour.a == 0.0){discard;}}")
: ShaderData(vertexShader,fragmentShader)

Expand Down
4 changes: 3 additions & 1 deletion app/src/main/java/app/jerboa/spp/ui/view/SPPRenderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class SPPRenderer(
private var generatedParticles = 0
private var generating: Boolean = false
// particle scale, gl_PointSize
private val scale = 3f
private var scale = 3f
private val projection: FloatArray = FloatArray(16){0f}
private val invProjection: FloatArray = FloatArray(16){0f}

Expand Down Expand Up @@ -302,6 +302,8 @@ class SPPRenderer(
fun setOrbit(v: Float) { orbitStrength = v }
fun setShowToys(v: Boolean){ showToys = v }

fun setScale(s: Float) { scale = s; recompileDrawShader = true }

fun clearToys() {
attractors.clear()
repellors.clear()
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/app/jerboa/spp/ui/view/SPPView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class SPPView (
fun setOrbit(v: Float) { renderer.setOrbit(v) }
fun showToys(v: Boolean){ renderer.setShowToys(v) }
fun clearToys() { renderer.clearToys() }
fun setScale(s: Float) { renderer.setScale(s) }

override fun onResume() {
super.onResume()
Expand Down
Loading

0 comments on commit e41c5d6

Please sign in to comment.