mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-14 12:35:21 +00:00
formula dev tools: add pattern + bg-lightness controls for dark/black
LIGHT had three pattern/background controls — Pattern depth, Pattern chroma, BG Lightness — that DARK and BLACK didn't expose. Without them the founder couldn't tune the wallpaper pattern's brightness/saturation or nudge the background's lightness independently of the bubble cluster in those themes. Add the same three sliders to DARK and BLACK. generateSchemeDark / generateSchemeBlack gain three new optional params that pass through generateDarkFromSlots: - patternDepth: when set, replaces the slot's hard-coded lightnessMult (and patternIntensity multiplier) directly, matching LIGHT's semantic of "multiplier on effStep". - patternChroma: when set, overrides the pattern slot's chroma — taking precedence over BLACK's max-pin behaviour so the user can pull it back from the gamut edge. - bgLOffset: nudges only the background slot's L (other slots stay at their formula-computed L), mirroring LIGHT. null defaults preserve the existing behaviour, so nothing changes for callers that don't pass the new params. Defaults derivation in FormulaDevTools picks up patternDepth and patternChroma from the preset's stored tint slot (same shape as LIGHT, with the sign of the depth swapped because dark themes have the pattern brighter than the bg, not darker). bgLOffset stays at its existing 0f fallback. Slider ranges: BLACK pattern depth uses 0..15 because the default lightnessMult for BLACK pattern is 9.0 — the LIGHT/DARK 0..10 wouldn't give meaningful headroom. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+20
-5
@@ -309,25 +309,32 @@ fun generateSchemeDark(
|
||||
step: Float = 0.038f,
|
||||
mutedChroma: Float = 0.020f,
|
||||
colorChroma: Float = 0.063f,
|
||||
patternDepth: Float? = null,
|
||||
patternChroma: Float? = null,
|
||||
bgLOffset: Float = 0f,
|
||||
saturationScale: Float = 1f,
|
||||
contrastScale: Float = 1f,
|
||||
patternIntensity: Float = 1f,
|
||||
): FormulaResult = generateDarkFromSlots(hue, bgL, step, mutedChroma, colorChroma, DARK_SLOTS, false, saturationScale, contrastScale, patternIntensity)
|
||||
): FormulaResult = generateDarkFromSlots(hue, bgL, step, mutedChroma, colorChroma, DARK_SLOTS, false, patternDepth, patternChroma, bgLOffset, saturationScale, contrastScale, patternIntensity)
|
||||
|
||||
fun generateSchemeBlack(
|
||||
hue: Float,
|
||||
step: Float = 0.04f,
|
||||
colorChroma: Float = 0.0522f,
|
||||
patternDepth: Float? = null,
|
||||
patternChroma: Float? = null,
|
||||
bgLOffset: Float = 0f,
|
||||
saturationScale: Float = 1f,
|
||||
contrastScale: Float = 1f,
|
||||
patternIntensity: Float = 1f,
|
||||
): FormulaResult = generateDarkFromSlots(hue, 0f, step, 0f, colorChroma, BLACK_SLOTS, true, saturationScale, contrastScale, patternIntensity)
|
||||
): FormulaResult = generateDarkFromSlots(hue, 0f, step, 0f, colorChroma, BLACK_SLOTS, true, patternDepth, patternChroma, bgLOffset, saturationScale, contrastScale, patternIntensity)
|
||||
|
||||
private fun generateDarkFromSlots(
|
||||
hue: Float, bgL: Float, step: Float,
|
||||
mutedChroma: Float, colorChroma: Float,
|
||||
slotDefs: Map<String, DarkSlotDef>,
|
||||
patternPinsToP3: Boolean,
|
||||
patternDepth: Float?, patternChroma: Float?, bgLOffset: Float,
|
||||
saturationScale: Float, contrastScale: Float, patternIntensity: Float,
|
||||
): FormulaResult {
|
||||
val effStep = step * contrastScale
|
||||
@@ -345,12 +352,20 @@ private fun generateDarkFromSlots(
|
||||
var lMult = def.lightnessMult
|
||||
var baseC = baselineC[name]!!
|
||||
if (name == "pattern") {
|
||||
lMult *= patternIntensity
|
||||
baseC = bgCAnchor + (baseC - bgCAnchor) * patternIntensity
|
||||
// patternDepth slider overrides slot's lightnessMult (and patternIntensity)
|
||||
// directly; same semantic as LIGHT's patternDepth — multiplier on effStep.
|
||||
lMult = patternDepth ?: (lMult * patternIntensity)
|
||||
baseC = patternChroma ?: (bgCAnchor + (baseC - bgCAnchor) * patternIntensity)
|
||||
}
|
||||
val L = bgL + lMult * effStep
|
||||
// bgLOffset nudges only the background slot, leaving bubbles/pattern at their
|
||||
// formula-computed L (mirrors LIGHT's bgLOffset behaviour).
|
||||
val L = if (name == "background") (bgL + bgLOffset).coerceIn(0f, 1f)
|
||||
else bgL + lMult * effStep
|
||||
val C = when {
|
||||
name == "background" -> bgCAnchor
|
||||
// patternChroma slider takes precedence over BLACK's max-pin behavior so
|
||||
// the user can dial it back from the gamut edge.
|
||||
name == "pattern" && patternChroma != null -> patternChroma
|
||||
name == "pattern" && patternPinsToP3 -> maxChroma(L, hue)
|
||||
else -> bgCAnchor + (baseC - bgCAnchor) * saturationScale
|
||||
}.let { min(it, maxChroma(L, hue)) }
|
||||
|
||||
+14
@@ -784,6 +784,8 @@ object AppearanceScope {
|
||||
"hue" to bg.H.let { if (isBlack) sm.H else it },
|
||||
"bgL" to bg.L, "step" to step,
|
||||
"mutedChroma" to mutedC, "colorChroma" to sm.C,
|
||||
"patternDepth" to if (step > 0f) (tint.L - bg.L) / step else 0f,
|
||||
"patternChroma" to tint.C,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -816,10 +818,16 @@ object AppearanceScope {
|
||||
)
|
||||
DefaultTheme.BLACK -> generateSchemeBlack(
|
||||
hue.floatValue, step.floatValue, colorChroma.floatValue,
|
||||
patternDepth = patternDepth.floatValue,
|
||||
patternChroma = patternChromaVal.floatValue,
|
||||
bgLOffset = bgLOffset.floatValue,
|
||||
)
|
||||
else -> generateSchemeDark(
|
||||
hue.floatValue, bgL.floatValue, step.floatValue,
|
||||
mutedChroma.floatValue, colorChroma.floatValue,
|
||||
patternDepth = patternDepth.floatValue,
|
||||
patternChroma = patternChromaVal.floatValue,
|
||||
bgLOffset = bgLOffset.floatValue,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -859,15 +867,21 @@ object AppearanceScope {
|
||||
}
|
||||
DefaultTheme.BLACK -> {
|
||||
FormulaSlider("Hue", hue, 0f..360f)
|
||||
FormulaSlider("BG Lightness", bgLOffset, -0.05f..0.05f)
|
||||
FormulaSlider("Contrast", step, 0.01f..0.10f)
|
||||
FormulaSlider("Accent chroma", colorChroma, 0f..0.20f)
|
||||
FormulaSlider("Pattern depth", patternDepth, 0f..15f)
|
||||
FormulaSlider("Pattern chroma", patternChromaVal, 0f..0.15f)
|
||||
}
|
||||
else -> {
|
||||
FormulaSlider("Hue", hue, 0f..360f)
|
||||
FormulaSlider("Lightness", bgL, 0.05f..0.30f)
|
||||
FormulaSlider("BG Lightness", bgLOffset, -0.05f..0.05f)
|
||||
FormulaSlider("Contrast", step, 0.01f..0.10f)
|
||||
FormulaSlider("Accent chroma", colorChroma, 0f..0.20f)
|
||||
FormulaSlider("Secondary chroma", mutedChroma, 0f..0.05f)
|
||||
FormulaSlider("Pattern depth", patternDepth, 0f..10f)
|
||||
FormulaSlider("Pattern chroma", patternChromaVal, 0f..0.15f)
|
||||
}
|
||||
}
|
||||
SectionItemView({
|
||||
|
||||
Reference in New Issue
Block a user