Bladeren bron

added new flags for new linux-wallpaperengine version

UwU 2 dagen geleden
bovenliggende
commit
06d8c66d3c

+ 2 - 2
src/main/services/lwe.service.ts

@@ -36,7 +36,7 @@ import {
   getDisablePuppetAnimation
 } from './config.service'
 import { DEFAULT_LWE_FPS, DEFAULT_LWE_REPO } from '@shared/constants'
-import { engineFlagArgs } from '@shared/engineFlags'
+import { engineFlagArgs, filterSupportedArgs } from '@shared/engineFlags'
 import { imageAdjustmentArgs, imageAdjustmentLines, type ImageAdjustments } from '@shared/imageAdjustments'
 
 export const ALL_SCREENS: ScreenTarget = '*'
@@ -900,7 +900,7 @@ function buildLweArgs(
   if (getDisablePuppetAnimation()) args.push('--render-debug', 'no-puppet-animation')
   const flags = options.engineFlags ?? {}
   if (flags.disableAnimations && supportsDisableAnimations()) args.push('--disable-animations')
-  args.push(...engineFlagArgs(flags).filter(supportsFlag))
+  args.push(...filterSupportedArgs(engineFlagArgs(flags), supportsFlag))
   if (options.scalingMode) args.push('--scaling', options.scalingMode)
   if (options.zoom !== undefined) args.push('--zoom', String(options.zoom))
   if (options.offsetX !== undefined || options.offsetY !== undefined) {

+ 24 - 1
src/renderer/src/components/common/sidebar/EngineFlagsSection.tsx

@@ -3,7 +3,7 @@ import { useQuery } from '@tanstack/react-query'
 import { ChevronDown, ChevronRight, Gauge, Loader2 } from 'lucide-react'
 import type { EngineFlags, FullscreenPauseMode, WallpaperMeta } from '@shared/types'
 import { hasEngineFlags } from '@shared/engineFlags'
-import { BOOLEAN_FLAGS, FULLSCREEN_PAUSE_OPTIONS } from '../../../constants/engineFlags'
+import { BOOLEAN_FLAGS, CHOICE_FLAGS, FULLSCREEN_PAUSE_OPTIONS } from '../../../constants/engineFlags'
 
 interface Props {
   flags?: EngineFlags
@@ -112,6 +112,29 @@ export default function EngineFlagsSection({ flags = {}, onChange }: Props) {
             </label>
           ))}
 
+          {CHOICE_FLAGS.map(({ key, label, hint, fallback, options }) => (
+            <label key={key} className="flex items-center justify-between gap-2 text-xs text-gray-300" title={hint}>
+              <span>{label}</span>
+              <select
+                value={flags[key] ?? 'inherit'}
+                disabled={busy}
+                onChange={(e) =>
+                  setFlag(key, e.target.value === 'inherit' ? undefined : (e.target.value as EngineFlags[typeof key]))
+                }
+                className={selectClass}
+              >
+                <option value="inherit">
+                  Default ({options.find((o) => o.value === (global[key] ?? fallback))?.label.toLowerCase()})
+                </option>
+                {options.map((o) => (
+                  <option key={o.value} value={o.value}>
+                    {o.label}
+                  </option>
+                ))}
+              </select>
+            </label>
+          ))}
+
           <label className="flex flex-col gap-1 text-xs text-gray-300">
             <span>Fullscreen apps</span>
             <select

+ 23 - 1
src/renderer/src/components/settings/PerformanceSettings.tsx

@@ -2,7 +2,7 @@ import { useState } from 'react'
 import { useQuery, useQueryClient } from '@tanstack/react-query'
 import { Check, Plus, Save, Trash2 } from 'lucide-react'
 import type { EngineFlagPreset, EngineFlags, FullscreenPauseMode } from '@shared/types'
-import { BOOLEAN_FLAGS, FULLSCREEN_PAUSE_OPTIONS } from '../../constants/engineFlags'
+import { BOOLEAN_FLAGS, CHOICE_FLAGS, FULLSCREEN_PAUSE_OPTIONS } from '../../constants/engineFlags'
 
 interface Props {
   defaultFps: number | null
@@ -30,6 +30,12 @@ function describePreset(preset: EngineFlagPreset): string {
   const parts = BOOLEAN_FLAGS.filter((f) => preset.flags[f.key]).map((f) => f.label.toLowerCase())
   const pause = FULLSCREEN_PAUSE_OPTIONS.find((o) => o.value === preset.flags.fullscreenPause)
   if (pause && pause.value !== 'default') parts.push(pause.label.toLowerCase())
+  for (const { key, label, fallback, options } of CHOICE_FLAGS) {
+    const value = preset.flags[key]
+    if (value && value !== fallback) {
+      parts.push(`${label.toLowerCase()} ${options.find((o) => o.value === value)?.label.toLowerCase()}`)
+    }
+  }
   if (preset.fps) parts.push(`${preset.fps} FPS`)
   return parts.length ? parts.join(', ') : 'everything on'
 }
@@ -110,6 +116,22 @@ export default function PerformanceSettings({ defaultFps, onDefaultFpsChanged }:
             ))}
           </select>
         </label>
+        {CHOICE_FLAGS.map(({ key, label, hint, fallback, options }) => (
+          <label key={key} className="flex items-center gap-3 text-sm text-gray-300" title={hint}>
+            <span>{label}</span>
+            <select
+              value={flags[key] ?? fallback}
+              onChange={(e) => saveFlags({ ...flags, [key]: e.target.value })}
+              className="rounded-lg bg-white/5 px-2 py-1.5 text-sm text-gray-200 outline-none"
+            >
+              {options.map((o) => (
+                <option key={o.value} value={o.value}>
+                  {o.label}
+                </option>
+              ))}
+            </select>
+          </label>
+        ))}
       </div>
 
       <p className="mt-4 text-xs font-medium text-gray-400">Presets</p>

+ 44 - 1
src/renderer/src/constants/engineFlags.ts

@@ -1,6 +1,7 @@
 import type { EngineFlags, FullscreenPauseMode } from '@shared/types'
 
-type BooleanFlag = Exclude<keyof EngineFlags, 'fullscreenPause'>
+type ChoiceFlag = 'postProcessing' | 'volumetrics' | 'shadows'
+type BooleanFlag = Exclude<keyof EngineFlags, 'fullscreenPause' | ChoiceFlag>
 
 export const BOOLEAN_FLAGS: { key: BooleanFlag; label: string; hint: string }[] = [
   { key: 'disableParticles', label: 'Disable particles', hint: 'Skips particle systems (fog, sparks, rain), usually the biggest GPU cost' },
@@ -21,3 +22,45 @@ export const FULLSCREEN_PAUSE_OPTIONS: { value: FullscreenPauseMode; label: stri
   { value: 'active-only', label: 'Pause only for the focused fullscreen app' },
   { value: 'off', label: 'Never pause' }
 ]
+
+const LIGHTING_QUALITY = [
+  { value: 'disabled', label: 'Off' },
+  { value: 'low', label: 'Low' },
+  { value: 'medium', label: 'Medium' },
+  { value: 'high', label: 'High' },
+  { value: 'ultra', label: 'Ultra' }
+]
+
+/** Quality settings mirroring Wallpaper Engine's own, `fallback` is what the engine uses when none is given */
+export const CHOICE_FLAGS: {
+  key: ChoiceFlag
+  label: string
+  hint: string
+  fallback: string
+  options: { value: string; label: string }[]
+}[] = [
+  {
+    key: 'postProcessing',
+    label: 'Post processing',
+    hint: 'Ultra renders scenes that enable HDR bloom in HDR, with a softer, wider glow',
+    fallback: 'enabled',
+    options: [
+      { value: 'enabled', label: 'Enabled' },
+      { value: 'ultra', label: 'Ultra' }
+    ]
+  },
+  {
+    key: 'volumetrics',
+    label: 'Volumetric lighting',
+    hint: 'Glow around lights that cast volumetrics; higher levels take more samples at a higher resolution',
+    fallback: 'medium',
+    options: LIGHTING_QUALITY
+  },
+  {
+    key: 'shadows',
+    label: 'Shadows',
+    hint: 'Shadow quality; for now it only changes how finely shadow casting lights sample their volumetrics',
+    fallback: 'medium',
+    options: LIGHTING_QUALITY
+  }
+]

+ 19 - 1
src/shared/engineFlags.test.ts

@@ -1,5 +1,5 @@
 import { describe, expect, it } from 'vitest'
-import { engineFlagArgs, hasEngineFlags, resolveEngineFlags } from './engineFlags'
+import { engineFlagArgs, filterSupportedArgs, hasEngineFlags, resolveEngineFlags } from './engineFlags'
 
 describe('resolveEngineFlags', () => {
   it('lets a wallpaper override the global flags, unset ones fall through', () => {
@@ -19,6 +19,15 @@ describe('engineFlagArgs', () => {
     expect(engineFlagArgs({ fullscreenPause: 'off' })).toEqual(['--no-fullscreen-pause'])
     expect(engineFlagArgs({ fullscreenPause: 'default' })).toEqual([])
     expect(engineFlagArgs({ hdr: true })).toEqual(['--hdr'])
+    expect(engineFlagArgs({ postProcessing: 'ultra', volumetrics: 'high', shadows: 'disabled' })).toEqual([
+      '--post-processing',
+      'ultra',
+      '--volumetrics',
+      'high',
+      '--shadows',
+      'disabled'
+    ])
+    expect(engineFlagArgs({ postProcessing: 'enabled', volumetrics: 'medium', shadows: 'medium' })).toEqual([])
   })
 
   it('leaves disableAnimations to the caller, it needs its own capability probe', () => {
@@ -26,6 +35,15 @@ describe('engineFlagArgs', () => {
   })
 })
 
+describe('filterSupportedArgs', () => {
+  it('drops unknown options along with their values', () => {
+    const supported = new Set(['--hdr', '--shadows'])
+    expect(
+      filterSupportedArgs(['--volumetrics', 'high', '--hdr', '--shadows', 'low'], (flag) => supported.has(flag))
+    ).toEqual(['--hdr', '--shadows', 'low'])
+  })
+})
+
 describe('hasEngineFlags', () => {
   it('is false for nothing or only unset values', () => {
     expect(hasEngineFlags(undefined)).toBe(false)

+ 22 - 2
src/shared/engineFlags.ts

@@ -11,7 +11,9 @@ export const BUILT_IN_PRESETS: EngineFlagPreset[] = [
       disableMouse: true,
       noAudioProcessing: true,
       fullscreenPause: 'default',
-      automute: true
+      automute: true,
+      volumetrics: 'disabled',
+      shadows: 'disabled'
     }
   },
   {
@@ -26,7 +28,10 @@ export const BUILT_IN_PRESETS: EngineFlagPreset[] = [
       noAudioProcessing: false,
       fullscreenPause: 'default',
       automute: false,
-      silent: false
+      silent: false,
+      postProcessing: 'ultra',
+      volumetrics: 'ultra',
+      shadows: 'ultra'
     }
   },
   {
@@ -55,9 +60,24 @@ export function engineFlagArgs(flags: EngineFlags): string[] {
   if (flags.automute) args.push('--automute')
   if (flags.silent) args.push('--silent')
   if (flags.hdr) args.push('--hdr')
+  // the engine's defaults are left out so they don't count as a different launch
+  if (flags.postProcessing && flags.postProcessing !== 'enabled') args.push('--post-processing', flags.postProcessing)
+  if (flags.volumetrics && flags.volumetrics !== 'medium') args.push('--volumetrics', flags.volumetrics)
+  if (flags.shadows && flags.shadows !== 'medium') args.push('--shadows', flags.shadows)
   return args
 }
 
+/** Drops options the engine doesn't know, together with their values */
+export function filterSupportedArgs(args: string[], supports: (flag: string) => boolean): string[] {
+  const kept: string[] = []
+  let keep = false
+  for (const arg of args) {
+    if (arg.startsWith('--')) keep = supports(arg)
+    if (keep) kept.push(arg)
+  }
+  return kept
+}
+
 export function hasEngineFlags(flags: EngineFlags | undefined): boolean {
   return !!flags && Object.values(flags).some((v) => v !== undefined)
 }

+ 9 - 0
src/shared/types.ts

@@ -128,6 +128,12 @@ export interface WallpaperMeta {
 
 export type FullscreenPauseMode = 'default' | 'off' | 'active-only'
 
+/** Wallpaper Engine's post processing setting, "ultra" turns on HDR rendering for scenes that ask for it */
+export type PostProcessingQuality = 'enabled' | 'ultra'
+
+/** Wallpaper Engine's volumetrics/shadow quality settings */
+export type LightingQuality = 'disabled' | 'low' | 'medium' | 'high' | 'ultra'
+
 /** linux-wallpaperengine flags that only take effect on a fresh launch */
 export interface EngineFlags {
   disableParticles?: boolean
@@ -138,6 +144,9 @@ export interface EngineFlags {
   automute?: boolean
   silent?: boolean
   hdr?: boolean
+  postProcessing?: PostProcessingQuality
+  volumetrics?: LightingQuality
+  shadows?: LightingQuality
 }
 
 export interface EngineFlagPreset {