Kawarp Shader <3

This commit is contained in:
meowarex
2026-08-14 06:21:00 +00:00
parent 625d012e17
commit 526e424621
35 changed files with 3051 additions and 327 deletions
+2 -2
View File
@@ -31,8 +31,8 @@ android {
defaultConfig {
minSdk = 24
targetSdk = 36
versionCode = 53
versionName = "1.0.1"
versionCode = 62
versionName = "1.7.7"
vectorDrawables {
useSupportLibrary = true
+188 -30
View File
@@ -14,17 +14,16 @@
"DebugMenuUnlock"
],
"disables": [
"LyricsDisableCover",
"LyricsReplaceLyricsButton",
"LyricsReplaceShareButton",
"LyricsRlApi",
"LyricsKeepControlsVisible",
"PlayerBackdrop",
"QualityBadgeColors",
"PlayerMovePlayingFrom",
"PlayerOneHanded",
"LyricsProgressPill",
"MiniPlayerRedesign"
"LyricsDisableCover",
"LyricsReplaceLyricsButton",
"LyricsReplaceShareButton",
"LyricsKeepControlsVisible"
]
},
{
@@ -119,36 +118,29 @@
"order": 30,
"fileNames": [],
"title": "Player Backdrop",
"description": "Lets you fully adjust how the player backdrop blur looks and behaves",
"description": "Swap the player backdrop for the Kawarp shader, or fine-tune TIDAL's own blurred cover",
"default": true,
"defaultVariantIndex": 2,
"defaultVariantIndex": 1,
"variants": [
{
"title": "Static",
"fileNames": [
"player-backdrop-static.patch"
],
"extensionFiles": [
"radiant/BackdropFx.smali"
]
},
{
"title": "Animated",
"fileNames": [
"player-backdrop-animated.patch"
],
"extensionFiles": [
"radiant/BackdropFx.smali"
]
},
{
"title": "Playback",
"title": "Tidal",
"fileNames": [
"player-backdrop-playback.patch"
],
"extensionFiles": [
"radiant/BackdropFx.smali"
]
},
{
"title": "Radiant",
"fileNames": [
"player-backdrop-kawarp.patch"
],
"extensionFiles": [
"radiant/Kawarp.smali",
"dev/kawarp/KawarpEngine.smali"
],
"minSdk": 33
}
],
"advancedOptions": [
@@ -166,7 +158,8 @@
"encode": {
"kind": "int",
"scale": 1.0
}
},
"requiresVariant": 0
},
{
"type": "slider",
@@ -182,7 +175,8 @@
"encode": {
"kind": "floatBits",
"scale": 0.02
}
},
"requiresVariant": 0
},
{
"type": "slider",
@@ -198,7 +192,8 @@
"encode": {
"kind": "floatBits",
"scale": 0.02
}
},
"requiresVariant": 0
},
{
"type": "slider",
@@ -214,7 +209,170 @@
"encode": {
"kind": "floatBits",
"scale": 0.02
}
},
"requiresVariant": 0
},
{
"type": "toggle",
"key": "kawarp_reactive",
"title": "Playback Reactive",
"description": "Cover shader reacts to playback state by freezing/resuming",
"default": true,
"token": "RL_KW_REACTIVE",
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_blur",
"title": "Blur Passes",
"description": "Kawase blur passes, higher is softer but costs more GPU",
"default": 5,
"min": 1,
"max": 40,
"steps": 38,
"displayAsPercent": false,
"token": "RL_KW_BLUR",
"encode": {
"kind": "int",
"scale": 1.0
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_warp",
"title": "Warp Intensity",
"description": "Strength of the fluidity effect",
"default": 100,
"min": 0,
"max": 100,
"steps": 19,
"displayAsPercent": true,
"token": "RL_KW_WARP",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_speed",
"title": "Animation Speed",
"description": "How fast the backdrop flows",
"default": 175,
"min": 0,
"max": 500,
"steps": 19,
"displayAsPercent": true,
"token": "RL_KW_SPEED",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_scale",
"title": "Backdrop Scale",
"description": "Zoom level of the effect",
"default": 100,
"min": 10,
"max": 400,
"steps": 12,
"displayAsPercent": true,
"token": "RL_KW_SCALE",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_contrast",
"title": "Contrast",
"description": "Contrast of the backdrop",
"default": 125,
"min": 0,
"max": 300,
"steps": 11,
"displayAsPercent": true,
"token": "RL_KW_CONTRAST",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_saturation",
"title": "Saturation",
"description": "Colour intensity of the backdrop",
"default": 125,
"min": 0,
"max": 400,
"steps": 15,
"displayAsPercent": true,
"token": "RL_KW_SAT",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_brightness",
"title": "Brightness",
"description": "The value of Brightness applied to the backdrop",
"default": 100,
"min": 0,
"max": 200,
"steps": 19,
"displayAsPercent": true,
"token": "RL_KW_BRIGHT",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_darken",
"title": "Auto Darken Bright Covers",
"description": "Prevents bright covers from making text unreadable",
"default": 80,
"min": 0,
"max": 100,
"steps": 19,
"displayAsPercent": true,
"token": "RL_KW_DARKEN",
"encode": {
"kind": "floatBits",
"scale": 0.01
},
"requiresVariant": 1
},
{
"type": "slider",
"key": "kawarp_dither",
"title": "Dithering",
"description": "Breaks up color banding in smooth gradients",
"default": 15,
"min": 0,
"max": 100,
"steps": 19,
"displayAsPercent": false,
"token": "RL_KW_DITHER",
"encode": {
"kind": "floatBits",
"scale": 0.001
},
"requiresVariant": 1
},
{
"type": "toggle",
@@ -37,6 +37,7 @@ import com.meowarex.rlmobile.ui.legacy.components.ResetToDefaultButton
import com.meowarex.rlmobile.ui.screens.patchopts.OptionLock
import com.meowarex.rlmobile.ui.screens.patchopts.OptionSpec
import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionState
import com.meowarex.rlmobile.ui.screens.patchopts.hiddenForVariant
import com.meowarex.rlmobile.ui.screens.patchopts.optionLock
import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec
import kotlinx.coroutines.launch
@@ -109,6 +110,8 @@ fun PatchAdvancedOptionsSheet(
when {
option is OptionSpec.Toggle && option.inline -> false
option is OptionSpec.Toggle && option.requiresOption in parentKeys -> false
// Options belonging to another variant are hidden, not greyed out.
option.hiddenForVariant(selectedVariant) -> false
else -> true
}
}
@@ -1,6 +1,7 @@
package com.meowarex.rlmobile.ui.screens.patchopts
import android.content.Context
import android.os.Build
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import kotlinx.serialization.SerialName
@@ -49,7 +50,13 @@ data class VariantSpec(
val fileNames: List<String> = emptyList(),
val extensionFiles: List<String> = emptyList(),
val enabled: Boolean = true,
)
/**
* Hidden from the picker on devices below this API level (AGSL needs 33)
*/
val minSdk: Int = 0,
) {
val supportedHere: Boolean get() = Build.VERSION.SDK_INT >= minSdk
}
/** A single advanced option. Discriminated by `"type"` in JSON. */
@Serializable
@@ -101,6 +108,8 @@ sealed interface OptionSpec {
val token: String? = null,
/** How the chosen value becomes the smali literal that replaces the token. */
val encode: SmaliEncode? = null,
/** Hidden unless this variant index is the selected one. */
val requiresVariant: Int? = null,
) : OptionSpec {
val valueRange: ClosedFloatingPointRange<Float> get() = min..max
}
@@ -187,7 +196,9 @@ fun PatchSpec.effectiveVariants(isOptionOn: (OptionSpec.Toggle) -> Boolean): Lis
}
}
return variants.mapIndexedNotNull { index, variant ->
if (index in hidden) null
// Everything downstream (variantIndex -> resolveVariantIndex) picks from this list, so
// dropping an unsupported variant here also keeps the patcher from ever applying it.
if (index in hidden || !variant.supportedHere) null
else EffectiveVariant(index, relabel[index] ?: variant.title, variant.enabled)
}
}
@@ -206,6 +217,20 @@ fun PatchSpec.resolveVariantIndex(stored: Int, isOptionOn: (OptionSpec.Toggle) -
?: visible.first().originalIndex
}
/**
* The variant this option belongs to
*/
val OptionSpec.variantGate: Int?
get() = when (this) {
is OptionSpec.Toggle -> requiresVariant
is OptionSpec.Slider -> requiresVariant
is OptionSpec.Choice -> null
is OptionSpec.Color -> null
}
fun OptionSpec.hiddenForVariant(selectedVariant: Int): Boolean =
variantGate.let { it != null && it != selectedVariant }
sealed interface OptionLock {
data object Free : OptionLock
data class NeedsVariant(val title: String) : OptionLock
@@ -43,6 +43,7 @@ import com.meowarex.rlmobile.ui.components.ResetToDefaultButton
import com.meowarex.rlmobile.ui.screens.patchopts.OptionLock
import com.meowarex.rlmobile.ui.screens.patchopts.OptionSpec
import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionState
import com.meowarex.rlmobile.ui.screens.patchopts.hiddenForVariant
import com.meowarex.rlmobile.ui.screens.patchopts.optionLock
import com.meowarex.rlmobile.ui.screens.patchopts.PatchSpec
import kotlinx.coroutines.launch
@@ -115,6 +116,8 @@ fun PatchAdvancedOptionsSheet(
when {
option is OptionSpec.Toggle && option.inline -> false
option is OptionSpec.Toggle && option.requiresOption in parentKeys -> false
// Options belonging to another variant are hidden, not greyed out.
option.hiddenForVariant(selectedVariant) -> false
else -> true
}
}