From 103adf5827d65ea5b00a94ff4423b976fb5794b0 Mon Sep 17 00:00:00 2001 From: Thomas Mello Date: Wed, 17 Sep 2025 02:13:04 +0300 Subject: [PATCH 1/3] feat(gui): expose projection gain as a GUI setting --- docs/adding-gui-settings.md | 23 ++++++++++++++ src/clipper/argparser.py | 10 ++++++ src/clipper/gui/settings_manager.py | 4 +++ .../src/components/LiftGammaGainWheels.vue | 31 ++++++++++++++++++- src/gui-frontend/src/types/settings.ts | 3 ++ .../src/utils/colorFilterBuild.ts | 11 ++++++- src/gui-frontend/src/utils/lgg.ts | 24 +++++++------- 7 files changed, 92 insertions(+), 14 deletions(-) diff --git a/docs/adding-gui-settings.md b/docs/adding-gui-settings.md index e967cf6..a99bcf3 100644 --- a/docs/adding-gui-settings.md +++ b/docs/adding-gui-settings.md @@ -239,6 +239,29 @@ Settings flow through the system in this order: ### Testing After adding a setting: 1. Test CLI usage: `python -m clipper.yt_clipper --your-setting 50 markup.json` +2. For GUI-only tuning parameters (no CLI args) like `lgg_projection_gain` (an intensity multiplier for Lift/Gamma/Gain color wheel hue projection), ensure: + - Added to schema with empty `cli_args` list so it persists + - Added to `GeneralSettings` dataclass (`lgg_projection_gain: float = 1.5`) + - Consumed in frontend logic (e.g., passed into `buildLggFilterFromWheels`) + - UI control updates backend via `update_general_settings` API + +Example schema entry (general section): +```python +"lgg_projection_gain": { + "type": "number", + "description": "Intensity multiplier for Lift/Gamma/Gain color wheel hue projection (0.5-2.0)", + "min": 0.5, + "max": 2.0, + "default": 1.5, + "cli_args": [], +}, +``` + +Frontend usage snippet: +```ts +const projectionGain = settingsStore.generalSettings?.lgg_projection_gain ?? 1.5 +buildLggFilterFromWheels(wheelsInput, globalGamma, projectionGain) +``` 2. Test GUI usage: Verify setting appears in Settings Panel and persists when saved 3. Test processing: Ensure setting affects video output as expected 4. Test validation: Verify min/max ranges work in both CLI and GUI diff --git a/src/clipper/argparser.py b/src/clipper/argparser.py index ad1ac15..5668f31 100644 --- a/src/clipper/argparser.py +++ b/src/clipper/argparser.py @@ -678,6 +678,16 @@ def getSettingsSchema() -> Dict[str, Any]: "default": 5000, "cli_args": ["--cache-max-size-mb"], }, + # Color Grading / UI tuning (GUI only for now) + "lgg_projection_gain": { + "type": "number", + "description": "Intensity multiplier for Lift/Gamma/Gain color wheel hue projection (0.5-2.0)", + "min": 0.5, + "max": 2.0, + "default": 1.5, + # Intentionally no cli_args yet; internal GUI tuning parameter + "cli_args": [], + }, }, "video": { "video_title": { diff --git a/src/clipper/gui/settings_manager.py b/src/clipper/gui/settings_manager.py index 1ff3858..a2e7a2d 100644 --- a/src/clipper/gui/settings_manager.py +++ b/src/clipper/gui/settings_manager.py @@ -66,6 +66,10 @@ class GeneralSettings: cache_folder_path: str = "" cache_max_size_mb: int = 5000 + # === COLOR GRADING / UI TUNING === + # Multiplier applied to LGG color wheel hue projection (was hardcoded 1.5) + lgg_projection_gain: float = 1.5 + # === WINDOW OPTIONS === window_width: int = 1000 # Default window width window_height: int = 800 # Default window height diff --git a/src/gui-frontend/src/components/LiftGammaGainWheels.vue b/src/gui-frontend/src/components/LiftGammaGainWheels.vue index 288e346..eaeedd2 100644 --- a/src/gui-frontend/src/components/LiftGammaGainWheels.vue +++ b/src/gui-frontend/src/components/LiftGammaGainWheels.vue @@ -81,6 +81,18 @@ +
+
Projection Gain
+ +
Global Gamma
@@ -94,6 +106,7 @@ import { RefreshLeft } from '@element-plus/icons-vue' import ColorWheel from './common/ColorWheel.vue' import { buildLggFilterFromWheels } from '@/utils/lgg' import type { LggWheelState } from '@/types/colorGrading' +import { useSettingsStore } from '@/stores/settings' interface Emits { (e: 'wheel-state-changed', state: LggWheelState, filter: string): void @@ -118,6 +131,9 @@ const liftAmount = ref(props.wheelState.lift.amount) const midAmount = ref(props.wheelState.mid.amount) const gainAmount = ref(props.wheelState.gain.amount) const globalGamma = ref(props.wheelState.globalGamma) +// Projection gain comes from settings (persisted). Keep a local ref for immediate UI responsiveness. +const settingsStore = useSettingsStore() +const projectionGainLocal = ref(settingsStore.generalSettings?.lgg_projection_gain ?? 1.5) const wheelSize = 140 function buildState(): LggWheelState { @@ -135,7 +151,8 @@ function computeFilter(): string { mid: { hex: midHex.value, strength: midSat.value, neutral: midAmount.value }, gain: { hex: gainHex.value, strength: gainSat.value, neutral: gainAmount.value } }, - globalGamma.value + globalGamma.value, + projectionGainLocal.value ) } function emitChange() { @@ -201,6 +218,18 @@ function onVectorMid(payload: { hex: string; sat: number }) { function onVectorGain(payload: { hex: string; sat: number }) { gainSat.value = payload.sat } + +async function onProjectionGainCommit() { + // Persist to backend settings then emit change to rebuild filter + try { + if (settingsStore.generalSettings) { + await settingsStore.updateGeneralSettings({ lgg_projection_gain: projectionGainLocal.value }) + } + } catch (e) { + console.error('Failed updating projection gain setting', e) + } + emitChange() +}