UI gradient intensity slider, update wgui Defaults for dashboard, prepend ui-related config entries with ui_

This commit is contained in:
Aleksander
2026-01-17 12:49:43 +01:00
committed by galister
parent dabd122a1d
commit 7b3a2a1e48
18 changed files with 201 additions and 154 deletions

View File

@@ -82,7 +82,8 @@
}, },
"AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen", "AUTOSTART_APPS": "Anwendungen, die beim Start ausgeführt werden sollen",
"HANDSFREE_POINTER": "Freihändige Modus", "HANDSFREE_POINTER": "Freihändige Modus",
"HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt." "HANDSFREE_POINTER_HELP": "Eingabe, die bei Bewegung\nder Controller verwendet wird, wenn diese nicht verfügbar sind.\nLinkes Kneifen greift, rechtes klickt.",
"UI_GRADIENT_INTENSITY": "UI-Verlaufsintensität"
}, },
"HELLO": "Hallo!", "HELLO": "Hallo!",
"AUDIO": { "AUDIO": {

View File

@@ -31,6 +31,7 @@
"APP_SETTINGS": { "APP_SETTINGS": {
"ALLOW_SLIDING": "Stick interaction during grab", "ALLOW_SLIDING": "Stick interaction during grab",
"ANIMATION_SPEED": "UI Animation speed", "ANIMATION_SPEED": "UI Animation speed",
"UI_GRADIENT_INTENSITY": "UI Gradient intensity",
"BLOCK_GAME_INPUT": "Block game input", "BLOCK_GAME_INPUT": "Block game input",
"BLOCK_GAME_INPUT_HELP": "Blocks all input when an overlay is hovered", "BLOCK_GAME_INPUT_HELP": "Blocks all input when an overlay is hovered",
"BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignore watch when blocking input", "BLOCK_GAME_INPUT_IGNORE_WATCH": "Ignore watch when blocking input",

View File

@@ -82,7 +82,8 @@
}, },
"AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio", "AUTOSTART_APPS": "Aplicaciones a ejecutar al inicio",
"HANDSFREE_POINTER": "Modo manos libres", "HANDSFREE_POINTER": "Modo manos libres",
"HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic." "HANDSFREE_POINTER_HELP": "Entrada a utilizar cuando no\nestén disponibles los mandos de movimiento.\nPellizco con la izquierda para agarrar, con la derecha para hacer clic.",
"UI_GRADIENT_INTENSITY": "Intensidad del degradado de la IU"
}, },
"HELLO": "¡Hola!", "HELLO": "¡Hola!",
"AUDIO": { "AUDIO": {

View File

@@ -102,7 +102,8 @@
"XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita", "XWAYLAND_BY_DEFAULT": "Esegui le app in modalità Compatibilità per impostazione predefinita",
"AUTOSTART_APPS": "App da avviare all'avvio", "AUTOSTART_APPS": "App da avviare all'avvio",
"HANDSFREE_POINTER": "Modalità a mani libere", "HANDSFREE_POINTER": "Modalità a mani libere",
"HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare." "HANDSFREE_POINTER_HELP": "Input da usare quando i\ncontroller di movimento non sono disponibili.\nPizzico sinistro per afferrare, destro per cliccare.",
"UI_GRADIENT_INTENSITY": "Intensità gradiente dell'interfaccia utente"
}, },
"APPLICATION_LAUNCHER": "Lanciatore applicazioni", "APPLICATION_LAUNCHER": "Lanciatore applicazioni",
"APPLICATION_STARTED": "Applicazione avviata", "APPLICATION_STARTED": "Applicazione avviata",

View File

@@ -82,7 +82,8 @@
}, },
"AUTOSTART_APPS": "起動時に実行するアプリ", "AUTOSTART_APPS": "起動時に実行するアプリ",
"HANDSFREE_POINTER": "ハンズフリーモード", "HANDSFREE_POINTER": "ハンズフリーモード",
"HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。" "HANDSFREE_POINTER_HELP": "モーションコントローラーが利用できない場合の入力方法。\n左手のピンチは掴み、右手のピンチはクリックです。",
"UI_GRADIENT_INTENSITY": "UIグラデーションの強さ"
}, },
"HELLO": "こんにちは!", "HELLO": "こんにちは!",
"AUDIO": { "AUDIO": {

View File

@@ -77,7 +77,8 @@
}, },
"AUTOSTART_APPS": "Aplikacje do uruchomienia przy starcie", "AUTOSTART_APPS": "Aplikacje do uruchomienia przy starcie",
"HANDSFREE_POINTER": "Tryb bez użycia rąk", "HANDSFREE_POINTER": "Tryb bez użycia rąk",
"HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie." "HANDSFREE_POINTER_HELP": "Wejście do użycia, gdy kontrolery ruchu\nsą niedostępne. Lewy szczyptak to chwyt,\nprawy to kliknięcie.",
"UI_GRADIENT_INTENSITY": "Intensywność gradientu UI"
}, },
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji", "APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
"APPLICATIONS": "Aplikacje", "APPLICATIONS": "Aplikacje",

View File

@@ -102,7 +102,8 @@
"XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用", "XWAYLAND_BY_DEFAULT": "默认以兼容模式运行应用",
"AUTOSTART_APPS": "开机启动应用", "AUTOSTART_APPS": "开机启动应用",
"HANDSFREE_POINTER": "免提模式", "HANDSFREE_POINTER": "免提模式",
"HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取右手为点击。" "HANDSFREE_POINTER_HELP": "当运动控制器不可用时使用的输入。\n左手捏合为抓取右手为点击。",
"UI_GRADIENT_INTENSITY": "UI 渐变强度"
}, },
"APPLICATION_LAUNCHER": "应用启动器", "APPLICATION_LAUNCHER": "应用启动器",
"APPLICATION_STARTED": "应用已启动", "APPLICATION_STARTED": "应用已启动",

View File

@@ -97,11 +97,12 @@ pub enum FrontendTask {
RecenterPlayspace, RecenterPlayspace,
PushToast(Translation), PushToast(Translation),
PlaySound(SoundType), PlaySound(SoundType),
UpdateWguiDefaultsFromConfig,
HideDashboard, HideDashboard,
} }
impl<T: 'static> Frontend<T> { impl<T: 'static> Frontend<T> {
pub fn new(params: InitParams<T>, data: &mut T) -> anyhow::Result<Frontend<T>> { pub fn new(mut params: InitParams<T>, data: &mut T) -> anyhow::Result<Frontend<T>> {
let mut assets = Box::new(assets::Asset {}); let mut assets = Box::new(assets::Asset {});
let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?; let font_binary_bold = assets.load_from_path_gzip("Quicksand-Bold.ttf.gz")?;
@@ -120,6 +121,8 @@ impl<T: 'static> Frontend<T> {
PathBuf::new(), //FIXME: pass from somewhere else PathBuf::new(), //FIXME: pass from somewhere else
)?; )?;
Frontend::update_defaults_from_config(&globals, &mut params.interface, data);
let (layout, state) = wgui::parser::new_layout_from_assets( let (layout, state) = wgui::parser::new_layout_from_assets(
&ParseDocumentParams { &ParseDocumentParams {
globals: globals.clone(), globals: globals.clone(),
@@ -166,8 +169,9 @@ impl<T: 'static> Frontend<T> {
}; };
// init some things first // init some things first
frontend.update_background(data)?; frontend.tasks.push(FrontendTask::RefreshBackground);
frontend.update_time(data)?; frontend.tasks.push(FrontendTask::RefreshClock);
frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig);
Frontend::register_widgets(&mut frontend)?; Frontend::register_widgets(&mut frontend)?;
@@ -178,6 +182,16 @@ impl<T: 'static> Frontend<T> {
self.sounds_to_play.push(sound_type); self.sounds_to_play.push(sound_type);
} }
fn update_defaults_from_config(globals: &WguiGlobals, interface: &mut BoxDashInterface<T>, data: &mut T) {
let config = interface.general_config(data);
let mut globals = globals.get();
let defaults = &mut globals.defaults;
defaults.animation_mult = 1.0 / config.ui_animation_speed;
defaults.gradient_intensity = config.ui_gradient_intensity;
}
fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> { fn play_sound(&mut self, audio_system: &mut audio::AudioSystem, sound_type: SoundType) -> anyhow::Result<()> {
let mut assets = self.globals.assets_builtin(); let mut assets = self.globals.assets_builtin();
@@ -192,7 +206,7 @@ impl<T: 'static> Frontend<T> {
Err(_) => assets.load_from_path(path)?.into(), Err(_) => assets.load_from_path(path)?.into(),
}; };
let sample = audio::AudioSample::from_mp3(&*sound_bytes)?; let sample = audio::AudioSample::from_mp3(&sound_bytes)?;
audio_system.play_sample(&sample); audio_system.play_sample(&sample);
Ok(()) Ok(())
} }
@@ -307,6 +321,8 @@ impl<T: 'static> Frontend<T> {
} }
fn update_background(&mut self, data: &mut T) -> anyhow::Result<()> { fn update_background(&mut self, data: &mut T) -> anyhow::Result<()> {
self.layout.mark_redraw();
let Some(mut rect) = self let Some(mut rect) = self
.layout .layout
.state .state
@@ -341,6 +357,9 @@ impl<T: 'static> Frontend<T> {
FrontendTask::PushToast(content) => self.toast_manager.push(content), FrontendTask::PushToast(content) => self.toast_manager.push(content),
FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type), FrontendTask::PlaySound(sound_type) => self.queue_play_sound(sound_type),
FrontendTask::HideDashboard => self.action_hide_dashboard(params.data), FrontendTask::HideDashboard => self.action_hide_dashboard(params.data),
FrontendTask::UpdateWguiDefaultsFromConfig => {
Frontend::update_defaults_from_config(&self.globals, &mut self.interface, params.data)
}
}; };
Ok(()) Ok(())
} }

View File

@@ -55,6 +55,7 @@ enum Task {
UpdateBool(SettingType, bool), UpdateBool(SettingType, bool),
UpdateFloat(SettingType, f32), UpdateFloat(SettingType, f32),
UpdateInt(SettingType, i32), UpdateInt(SettingType, i32),
SettingUpdated(SettingType),
OpenContextMenu(Vec2, Vec<context_menu::Cell>), OpenContextMenu(Vec2, Vec<context_menu::Cell>),
ClearPipewireTokens, ClearPipewireTokens,
ClearSavedState, ClearSavedState,
@@ -87,6 +88,7 @@ impl<T> Tab<T> for TabSettings<T> {
self.set_tab(frontend, data, tab)?; self.set_tab(frontend, data, tab)?;
} }
Task::UpdateBool(setting, n) => { Task::UpdateBool(setting, n) => {
self.tasks.push(Task::SettingUpdated(setting));
if let Some(task) = setting.get_frontend_task() { if let Some(task) = setting.get_frontend_task() {
frontend.tasks.push(task) frontend.tasks.push(task)
} }
@@ -95,6 +97,7 @@ impl<T> Tab<T> for TabSettings<T> {
changed = true; changed = true;
} }
Task::UpdateFloat(setting, n) => { Task::UpdateFloat(setting, n) => {
self.tasks.push(Task::SettingUpdated(setting));
if let Some(task) = setting.get_frontend_task() { if let Some(task) = setting.get_frontend_task() {
frontend.tasks.push(task) frontend.tasks.push(task)
} }
@@ -103,6 +106,7 @@ impl<T> Tab<T> for TabSettings<T> {
changed = true; changed = true;
} }
Task::UpdateInt(setting, n) => { Task::UpdateInt(setting, n) => {
self.tasks.push(Task::SettingUpdated(setting));
if let Some(task) = setting.get_frontend_task() { if let Some(task) = setting.get_frontend_task() {
frontend.tasks.push(task) frontend.tasks.push(task)
} }
@@ -146,6 +150,12 @@ impl<T> Tab<T> for TabSettings<T> {
changed = true; changed = true;
} }
} }
Task::SettingUpdated(setting) => match setting {
SettingType::UiAnimationSpeed | SettingType::UiGradientIntensity | SettingType::UiRoundMultiplier => {
frontend.tasks.push(FrontendTask::UpdateWguiDefaultsFromConfig);
}
_ => { /* do nothing */ }
},
} }
} }
@@ -190,8 +200,9 @@ impl<T> Tab<T> for TabSettings<T> {
#[allow(clippy::enum_variant_names)] #[allow(clippy::enum_variant_names)]
#[derive(Clone, Copy, AsRefStr, EnumString)] #[derive(Clone, Copy, AsRefStr, EnumString)]
enum SettingType { enum SettingType {
AnimationSpeed, UiAnimationSpeed,
RoundMultiplier, UiGradientIntensity,
UiRoundMultiplier,
InvertScrollDirectionX, InvertScrollDirectionX,
InvertScrollDirectionY, InvertScrollDirectionY,
ScrollSpeed, ScrollSpeed,
@@ -259,8 +270,9 @@ impl SettingType {
pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 { pub fn mut_f32(self, config: &mut GeneralConfig) -> &mut f32 {
match self { match self {
Self::AnimationSpeed => &mut config.animation_speed, Self::UiAnimationSpeed => &mut config.ui_animation_speed,
Self::RoundMultiplier => &mut config.round_multiplier, Self::UiGradientIntensity => &mut config.ui_gradient_intensity,
Self::UiRoundMultiplier => &mut config.ui_round_multiplier,
Self::ScrollSpeed => &mut config.scroll_speed, Self::ScrollSpeed => &mut config.scroll_speed,
Self::LongPressDuration => &mut config.long_press_duration, Self::LongPressDuration => &mut config.long_press_duration,
Self::XrClickSensitivity => &mut config.xr_click_sensitivity, Self::XrClickSensitivity => &mut config.xr_click_sensitivity,
@@ -324,8 +336,9 @@ impl SettingType {
/// Ok is translation, Err is raw text /// Ok is translation, Err is raw text
fn get_translation(self) -> Result<&'static str, &'static str> { fn get_translation(self) -> Result<&'static str, &'static str> {
match self { match self {
Self::AnimationSpeed => Ok("APP_SETTINGS.ANIMATION_SPEED"), Self::UiAnimationSpeed => Ok("APP_SETTINGS.ANIMATION_SPEED"),
Self::RoundMultiplier => Ok("APP_SETTINGS.ROUND_MULTIPLIER"), Self::UiGradientIntensity => Ok("APP_SETTINGS.UI_GRADIENT_INTENSITY"),
Self::UiRoundMultiplier => Ok("APP_SETTINGS.ROUND_MULTIPLIER"),
Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"), Self::InvertScrollDirectionX => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_X"),
Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"), Self::InvertScrollDirectionY => Ok("APP_SETTINGS.INVERT_SCROLL_DIRECTION_Y"),
Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"), Self::ScrollSpeed => Ok("APP_SETTINGS.SCROLL_SPEED"),
@@ -385,8 +398,8 @@ impl SettingType {
//TODO: incorporate this //TODO: incorporate this
fn requires_restart(self) -> bool { fn requires_restart(self) -> bool {
match self { match self {
Self::AnimationSpeed Self::UiAnimationSpeed
| Self::RoundMultiplier | Self::UiRoundMultiplier
| Self::UprightScreenFix | Self::UprightScreenFix
| Self::DoubleCursorFix | Self::DoubleCursorFix
| Self::UseSkybox | Self::UseSkybox
@@ -692,8 +705,9 @@ impl<T> TabSettings<T> {
checkbox!(mp, c, SettingType::OpaqueBackground); checkbox!(mp, c, SettingType::OpaqueBackground);
checkbox!(mp, c, SettingType::HideUsername); checkbox!(mp, c, SettingType::HideUsername);
checkbox!(mp, c, SettingType::HideGrabHelp); checkbox!(mp, c, SettingType::HideGrabHelp);
slider_f32!(mp, c, SettingType::AnimationSpeed, 0.5, 5.0, 0.1); // min, max, step slider_f32!(mp, c, SettingType::UiAnimationSpeed, 0.5, 5.0, 0.1); // min, max, step
slider_f32!(mp, c, SettingType::RoundMultiplier, 0.5, 5.0, 0.1); slider_f32!(mp, c, SettingType::UiGradientIntensity, 0.0, 1.0, 0.05); // min, max, step
slider_f32!(mp, c, SettingType::UiRoundMultiplier, 0.5, 5.0, 0.1);
checkbox!(mp, c, SettingType::SetsOnWatch); checkbox!(mp, c, SettingType::SetsOnWatch);
checkbox!(mp, c, SettingType::UseSkybox); checkbox!(mp, c, SettingType::UseSkybox);
checkbox!(mp, c, SettingType::UsePassthrough); checkbox!(mp, c, SettingType::UsePassthrough);

View File

@@ -135,9 +135,6 @@ async function run() {
llm_translated_json = JSON.parse((await fsp.readFile(translated_json_path)).toString()); llm_translated_json = JSON.parse((await fsp.readFile(translated_json_path)).toString());
} }
let human = 0;
let llm = 0;
let total_count = 0; let total_count = 0;
await loop_object(orig_english_json, "", async () => { await loop_object(orig_english_json, "", async () => {
total_count += 1; total_count += 1;
@@ -153,17 +150,14 @@ async function run() {
await loop_object(orig_english_json, "", async (key, english_translation) => { await loop_object(orig_english_json, "", async (key, english_translation) => {
if (key_exists(orig_translated_json, key)) { if (key_exists(orig_translated_json, key)) {
human += 1;
return; return;
} }
if (key_exists(llm_translated_json, key)) { if (key_exists(llm_translated_json, key)) {
llm += 1;
return; return;
} }
console.log("Translating", key, "..."); console.log("Translating", key, "...");
llm++;
const prompt = gen_prompt(description_txt, template, key, english_translation); const prompt = gen_prompt(description_txt, template, key, english_translation);
@@ -186,7 +180,7 @@ async function run() {
fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2)); fsp.writeFile(translated_json_path, JSON.stringify(llm_translated_json, undefined, 2));
}); });
console.log("\"" + template_name + "\" translation finished,", human, "were already human translated,", llm, "llm-translated (" + Math.round((llm / total_count) * 100.0) + "% machine-translated)"); console.log("Translation", template_name, "finished");
} }
run().catch((e) => { run().catch((e) => {

View File

@@ -1,4 +1,13 @@
#!/bin/bash #!/bin/bash
# Do not run this script if you dont have at least 32GiB of system memory,
# unless you have enabled the mmap option in the Ollama startup settings.
# Submitting PRs that lack translated strings is okay if you dont meet the
# system requirements to run this script, or if you simply prefer not to; we are
# regularly updating the missing translation strings anyway.
#
# Base language: English (en.json)
set -e set -e
cd "$(dirname "$0")" cd "$(dirname "$0")"

View File

@@ -104,8 +104,9 @@ pub fn load_general_config() -> GeneralConfig {
#[derive(Serialize)] #[derive(Serialize)]
pub struct AutoSettings { pub struct AutoSettings {
pub animation_speed: f32, pub ui_animation_speed: f32,
pub round_multiplier: f32, pub ui_round_multiplier: f32,
pub ui_gradient_intensity: f32,
pub click_freeze_time_ms: i32, pub click_freeze_time_ms: i32,
pub invert_scroll_direction_x: bool, pub invert_scroll_direction_x: bool,
pub invert_scroll_direction_y: bool, pub invert_scroll_direction_y: bool,
@@ -151,8 +152,9 @@ fn get_settings_path() -> PathBuf {
pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> { pub fn save_settings(config: &GeneralConfig) -> anyhow::Result<()> {
let conf = AutoSettings { let conf = AutoSettings {
animation_speed: config.animation_speed, ui_animation_speed: config.ui_animation_speed,
round_multiplier: config.round_multiplier, ui_round_multiplier: config.ui_round_multiplier,
ui_gradient_intensity: config.ui_gradient_intensity,
click_freeze_time_ms: config.click_freeze_time_ms, click_freeze_time_ms: config.click_freeze_time_ms,
invert_scroll_direction_x: config.invert_scroll_direction_x, invert_scroll_direction_x: config.invert_scroll_direction_x,
invert_scroll_direction_y: config.invert_scroll_direction_y, invert_scroll_direction_y: config.invert_scroll_direction_y,

View File

@@ -141,7 +141,7 @@
## Set whether notifications should be shown at all ## Set whether notifications should be shown at all
#notifications_enabled: true #notifications_enabled: true
## Set whether notfications should make a sound ## Set whether notifications should make a sound
#notifications_sound_enabled: true #notifications_sound_enabled: true
## Toggle keyboard click sound ## Toggle keyboard click sound

View File

@@ -128,8 +128,8 @@ impl AppState {
apply_color(&mut defaults.bg_color, &session.config.color_background); apply_color(&mut defaults.bg_color, &session.config.color_background);
} }
defaults.animation_mult = 1. / session.config.animation_speed; defaults.animation_mult = 1. / session.config.ui_animation_speed;
defaults.rounding_mult = session.config.round_multiplier; defaults.rounding_mult = session.config.ui_round_multiplier;
let dbus = DbusConnector::default(); let dbus = DbusConnector::default();

View File

@@ -9,7 +9,6 @@ use slotmap::{DenseSlotMap, new_key_type};
use crate::{ use crate::{
animation::{self, Animation}, animation::{self, Animation},
components::Component,
globals, globals,
i18n::I18n, i18n::I18n,
layout::{LayoutState, LayoutTask, WidgetID}, layout::{LayoutState, LayoutTask, WidgetID},

View File

@@ -1,5 +1,4 @@
use crate::{ use crate::{
assets::AssetPath,
layout::WidgetID, layout::WidgetID,
parser::{ parser::{
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal, AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,

View File

@@ -1,5 +1,4 @@
use crate::{ use crate::{
assets::AssetPath,
layout::WidgetID, layout::WidgetID,
parser::{ parser::{
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal, AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,

View File

@@ -148,10 +148,15 @@ pub struct GeneralConfig {
pub color_background: Option<String>, pub color_background: Option<String>,
#[serde(default = "def_one")] #[serde(default = "def_one")]
pub animation_speed: f32, #[serde(alias = "ui_animation_speed", alias = "animation_speed" /* old name */)]
pub ui_animation_speed: f32,
#[serde(default = "def_one")] #[serde(default = "def_one")]
pub round_multiplier: f32, #[serde(alias = "ui_round_multiplier", alias = "round_multiplier" /* old name */)]
pub ui_round_multiplier: f32,
#[serde(default = "def_point3")]
pub ui_gradient_intensity: f32,
pub default_keymap: Option<String>, pub default_keymap: Option<String>,