Skip to content

Commit

Permalink
Animate foil in/out
Browse files Browse the repository at this point in the history
  • Loading branch information
rock3r committed Oct 10, 2023
1 parent fdcfa5b commit 3ff07e5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import org.jetbrains.skia.RuntimeShaderBuilder

@Language("GLSL") // Technically, SkSL
private const val FOIL_SHADER_CODE = """
const float STRENGTH = 0.4; // 0.0 = no effect, 1.0 = full effect
const float SATURATION = 0.9; // Color saturation (0.0 = grayscale, 1.0 = full color)
const float LIGHTNESS = 0.65; // Color lightness (0.0 = black, 1.0 = white)
uniform shader content; // Input texture (the application canvas)
uniform vec2 resolution; // Size of the canvas
uniform vec2 offset; // Additional offset of the effect
uniform float intensity; // 0.0 = no effect, 1.0 = full effect
// From https://www.ryanjuckett.com/photoshop-blend-modes-in-hlsl/
vec3 BlendMode_Screen(vec3 base, vec3 blend) {
Expand Down Expand Up @@ -64,7 +64,7 @@ vec4 rainbowEffect(vec2 uv, vec2 coord, vec2 offset) {
}
vec3 rainbow = BlendMode_Screen(srcColor.rgb, rainbowPrime + m);
return mix(srcColor, vec4(rainbow, srcColor.a), STRENGTH);
return mix(srcColor, vec4(rainbow, srcColor.a), intensity);
}
vec4 chromaticAberration(vec2 coord, vec2 offset) {
Expand All @@ -85,10 +85,11 @@ vec4 main(float2 fragCoord) {
private val runtimeEffect = RuntimeEffect.makeForShader(FOIL_SHADER_CODE)
private val shaderBuilder = RuntimeShaderBuilder(runtimeEffect)

internal fun Modifier.holoFoil(offset: Float) =
internal fun Modifier.holoFoil(offset: Float, intensity: Float = 1f) =
graphicsLayer {
shaderBuilder.uniform("resolution", size.width, size.height)
shaderBuilder.uniform("offset", 0f, offset)
shaderBuilder.uniform("intensity", intensity * .65f)

renderEffect =
ImageFilter.makeRuntimeShader(
Expand All @@ -97,9 +98,9 @@ internal fun Modifier.holoFoil(offset: Float) =
inputs = arrayOf(null),
).asComposeRenderEffect()

rotationX = offset * 4f
rotationY = offset * 10f
rotationZ = offset * -3f
scaleX = .9f
scaleY = .9f
rotationX = offset * 4f * intensity
rotationY = offset * 10f * intensity
rotationZ = offset * -3f * intensity
scaleX = 1f - .1f * intensity
scaleY = 1f - .1f * intensity
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.jetbrains.jewel.samples.ideplugin.releasessample
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
Expand Down Expand Up @@ -38,6 +39,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand Down Expand Up @@ -67,6 +69,8 @@ import com.intellij.ui.NewUI
import com.intellij.ui.RelativeFont
import com.intellij.util.ui.JBFont
import com.intellij.util.ui.JBUI
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.datetime.toJavaLocalDate
import org.jetbrains.jewel.HorizontalSplitLayout
Expand Down Expand Up @@ -475,17 +479,27 @@ private fun ReleaseImage(imagePath: String) {
tween(durationMillis = 2.seconds.inWholeMilliseconds.toInt(), easing = FastOutSlowInEasing),
repeatMode = RepeatMode.Reverse,
),
"holoFoil offset",
)

var isHovered by remember { mutableStateOf(false) }
var applyModifier by remember { mutableStateOf(false) }
val intensity by animateFloatAsState(if (isHovered) 1f else 0f, animationSpec = tween(300))

val scope = rememberCoroutineScope()

Image(
painter = painter,
contentDescription = null,
modifier = Modifier.fillMaxWidth()
.sizeIn(maxHeight = 200.dp)
.onHover { isHovered = it }
.thenIf(isHovered) { holoFoil(offset) },
.sizeIn(minHeight = 150.dp, maxHeight = 250.dp)
.onHover { newIsHovered ->
scope.launch {
isHovered = newIsHovered
if (!newIsHovered) delay(300)
applyModifier = newIsHovered
}
}
.thenIf(applyModifier) { holoFoil(offset, intensity) },
contentScale = ContentScale.Fit,
)
}
Expand Down

0 comments on commit 3ff07e5

Please sign in to comment.