mirror of https://github.com/wayvr-org/wayvr.git
custom palettes
This commit is contained in:
parent
c74c51f7cd
commit
fcc84e56b3
|
|
@ -1,5 +1,4 @@
|
||||||
<layout>
|
<layout>
|
||||||
<!-- id, text -->
|
|
||||||
<template name="ColorPaletteButton">
|
<template name="ColorPaletteButton">
|
||||||
<Button id="${id}" width="350" flex_direction="column" justify_content="space_around" tooltip="${tooltip}" tooltip_side="bottom"
|
<Button id="${id}" width="350" flex_direction="column" justify_content="space_around" tooltip="${tooltip}" tooltip_side="bottom"
|
||||||
color="${background}" hover_color="${background_variant}" border_color="${outline}" hover_border_color="${highlight}" padding="16" margin="4" >
|
color="${background}" hover_color="${background_variant}" border_color="${outline}" hover_border_color="${highlight}" padding="16" margin="4" >
|
||||||
|
|
@ -13,6 +12,13 @@
|
||||||
</Button>
|
</Button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="CustomPaletteButton">
|
||||||
|
<Button id="custom_btn" width="350" flex_direction="column" justify_content="space_around" padding="16" margin="4" >
|
||||||
|
<label translation="APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL" size="16" weight="bold" />
|
||||||
|
<label translation="APP_SETTINGS.COLOR_PALETTE_CUSTOM_URL2" size="14" color="on_background_variant" />
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
|
||||||
<elements>
|
<elements>
|
||||||
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
<div flex_direction="column" gap="8" width="100%" align_items="center">
|
||||||
<div id="list_parent" flex_grow="1" flex_wrap="wrap" flex_direction="row" gap="4" width="100%" justify_content="center"></div>
|
<div id="list_parent" flex_grow="1" flex_wrap="wrap" flex_direction="row" gap="4" width="100%" justify_content="center"></div>
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,9 @@
|
||||||
"COLOR_PALETTE_CURRENT": "Derzeit aktives Thema.",
|
"COLOR_PALETTE_CURRENT": "Derzeit aktives Thema.",
|
||||||
"COLOR_PALETTE_ACTIVATE": "Klicken Sie hier, um dieses Thema zu verwenden.",
|
"COLOR_PALETTE_ACTIVATE": "Klicken Sie hier, um dieses Thema zu verwenden.",
|
||||||
"APPLY_CHANGES_RESTART": "WayVR neu starten, um die Änderungen zu übernehmen?",
|
"APPLY_CHANGES_RESTART": "WayVR neu starten, um die Änderungen zu übernehmen?",
|
||||||
"COLOR_PALETTE_HELP": "Klicken, um Farbpaletten zu durchsuchen.\nUm eigene zu erstellen, besuche die Webseite!"
|
"COLOR_PALETTE_HELP": "Klicken, um Farbpaletten zu durchsuchen.\nUm eigene zu erstellen, besuche die Webseite!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Füge dein eigenes benutzerdefiniertes Thema hinzu!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Klicken Sie hier, um das Web-Handbuch zu öffnen."
|
||||||
},
|
},
|
||||||
"HELLO": "Hallo!",
|
"HELLO": "Hallo!",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,8 @@
|
||||||
"COLOR_PALETTE_HELP": "Click to browse color palettes.\nTo create custom ones, see website!",
|
"COLOR_PALETTE_HELP": "Click to browse color palettes.\nTo create custom ones, see website!",
|
||||||
"COLOR_PALETTES": "Color palettes",
|
"COLOR_PALETTES": "Color palettes",
|
||||||
"COLOR_PALETTE_CURRENT": "Currently active theme.",
|
"COLOR_PALETTE_CURRENT": "Currently active theme.",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Add your own custom theme!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Click to open web manual.",
|
||||||
"COLOR_PALETTE_ACTIVATE": "Click to use this theme.",
|
"COLOR_PALETTE_ACTIVATE": "Click to use this theme.",
|
||||||
"APPLY_CHANGES_RESTART": "Restart WayVR to apply changes?",
|
"APPLY_CHANGES_RESTART": "Restart WayVR to apply changes?",
|
||||||
"CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens",
|
"CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens",
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,9 @@
|
||||||
"COLOR_PALETTE_CURRENT": "Tema actualmente activo.",
|
"COLOR_PALETTE_CURRENT": "Tema actualmente activo.",
|
||||||
"COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.",
|
"COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.",
|
||||||
"APPLY_CHANGES_RESTART": "¿Reiniciar WayVR para aplicar los cambios?",
|
"APPLY_CHANGES_RESTART": "¿Reiniciar WayVR para aplicar los cambios?",
|
||||||
"COLOR_PALETTE_HELP": "Haz clic para explorar paletas de colores.\nPara crear paletas personalizadas, ¡visita el sitio web!"
|
"COLOR_PALETTE_HELP": "Haz clic para explorar paletas de colores.\nPara crear paletas personalizadas, ¡visita el sitio web!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "¡Añade tu propio tema personalizado!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Haz clic para abrir el manual web."
|
||||||
},
|
},
|
||||||
"HELLO": "¡Hola!",
|
"HELLO": "¡Hola!",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,9 @@
|
||||||
"COLOR_PALETTE_CURRENT": "Tema attualmente attivo.",
|
"COLOR_PALETTE_CURRENT": "Tema attualmente attivo.",
|
||||||
"COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.",
|
"COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.",
|
||||||
"APPLY_CHANGES_RESTART": "Riavviare WayVR per applicare le modifiche?",
|
"APPLY_CHANGES_RESTART": "Riavviare WayVR per applicare le modifiche?",
|
||||||
"COLOR_PALETTE_HELP": "Clicca per sfogliare le palette di colori.\nPer crearne di personalizzate, visita il sito web!"
|
"COLOR_PALETTE_HELP": "Clicca per sfogliare le palette di colori.\nPer crearne di personalizzate, visita il sito web!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Aggiungi il tuo tema personalizzato!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Clicca per aprire il manuale web."
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
"APPLICATION_LAUNCHER": "Lanciatore applicazioni",
|
||||||
"APPLICATION_STARTED": "Applicazione avviata",
|
"APPLICATION_STARTED": "Applicazione avviata",
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,9 @@
|
||||||
"COLOR_PALETTE_CURRENT": "現在有効なテーマ。",
|
"COLOR_PALETTE_CURRENT": "現在有効なテーマ。",
|
||||||
"COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用します。",
|
"COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用します。",
|
||||||
"APPLY_CHANGES_RESTART": "変更を適用するためにWayVRを再起動しますか?",
|
"APPLY_CHANGES_RESTART": "変更を適用するためにWayVRを再起動しますか?",
|
||||||
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択してください。\nカスタムパレットの作成については、ウェブサイトを参照してください!"
|
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択してください。\nカスタムパレットの作成については、ウェブサイトを参照してください!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "カスタムテーマを追加しましょう!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "クリックしてウェブマニュアルを開く。"
|
||||||
},
|
},
|
||||||
"HELLO": "こんにちは!",
|
"HELLO": "こんにちは!",
|
||||||
"AUDIO": {
|
"AUDIO": {
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,9 @@
|
||||||
"COLOR_PALETTE_CURRENT": "Obecnie aktywny motyw.",
|
"COLOR_PALETTE_CURRENT": "Obecnie aktywny motyw.",
|
||||||
"COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.",
|
"COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.",
|
||||||
"APPLY_CHANGES_RESTART": "Zrestartować WayVR, aby zastosować zmiany?",
|
"APPLY_CHANGES_RESTART": "Zrestartować WayVR, aby zastosować zmiany?",
|
||||||
"COLOR_PALETTE_HELP": "Kliknij, aby przeglądać palety kolorów.\nAby stworzyć własne, odwiedź stronę internetową!"
|
"COLOR_PALETTE_HELP": "Kliknij, aby przeglądać palety kolorów.\nAby stworzyć własne, odwiedź stronę internetową!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "Dodaj własny motyw!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "Kliknij, aby otworzyć instrukcję internetową."
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
"APPLICATION_LAUNCHER": "Uruchamiacz aplikacji",
|
||||||
"APPLICATIONS": "Aplikacje",
|
"APPLICATIONS": "Aplikacje",
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,9 @@
|
||||||
"COLOR_PALETTE_CURRENT": "当前激活的主题。",
|
"COLOR_PALETTE_CURRENT": "当前激活的主题。",
|
||||||
"COLOR_PALETTE_ACTIVATE": "点击以使用此主题。",
|
"COLOR_PALETTE_ACTIVATE": "点击以使用此主题。",
|
||||||
"APPLY_CHANGES_RESTART": "重启 WayVR 以应用更改吗?",
|
"APPLY_CHANGES_RESTART": "重启 WayVR 以应用更改吗?",
|
||||||
"COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义配色,请参阅网站!"
|
"COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义配色,请参阅网站!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL": "添加自定义主题!",
|
||||||
|
"COLOR_PALETTE_CUSTOM_URL2": "点击打开网页版手册。"
|
||||||
},
|
},
|
||||||
"APPLICATION_LAUNCHER": "应用启动器",
|
"APPLICATION_LAUNCHER": "应用启动器",
|
||||||
"APPLICATION_STARTED": "应用已启动",
|
"APPLICATION_STARTED": "应用已启动",
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,15 @@ use wlx_common::{
|
||||||
audio,
|
audio,
|
||||||
dash_interface::{BoxDashInterface, ConfigChangeKind, RecenterMode},
|
dash_interface::{BoxDashInterface, ConfigChangeKind, RecenterMode},
|
||||||
locale::WayVRLangProvider,
|
locale::WayVRLangProvider,
|
||||||
|
palette::load_palette,
|
||||||
timestep::{self, Timestep},
|
timestep::{self, Timestep},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assets,
|
assets,
|
||||||
tab::{
|
tab::{
|
||||||
Tab, TabType, apps::TabApps, donate::TabDonate, games::TabGames, home::TabHome, monado::TabMonado,
|
apps::TabApps, donate::TabDonate, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings,
|
||||||
settings::TabSettings, welcome::TabWelcome,
|
welcome::TabWelcome, Tab, TabType,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
popup_manager::{MountPopupOnceParams, PopupManager, PopupManagerParams},
|
popup_manager::{MountPopupOnceParams, PopupManager, PopupManagerParams},
|
||||||
|
|
@ -131,6 +132,8 @@ impl<T: 'static> Frontend<T> {
|
||||||
let font_binary_regular = assets.load_from_path_gzip("Quicksand-Regular.ttf.gz")?;
|
let font_binary_regular = assets.load_from_path_gzip("Quicksand-Regular.ttf.gz")?;
|
||||||
let font_binary_light = assets.load_from_path_gzip("Quicksand-Light.ttf.gz")?;
|
let font_binary_light = assets.load_from_path_gzip("Quicksand-Light.ttf.gz")?;
|
||||||
|
|
||||||
|
let palette = load_palette(params.color_palette);
|
||||||
|
|
||||||
let globals = WguiGlobals::new(
|
let globals = WguiGlobals::new(
|
||||||
assets,
|
assets,
|
||||||
params.lang_provider,
|
params.lang_provider,
|
||||||
|
|
@ -141,7 +144,7 @@ impl<T: 'static> Frontend<T> {
|
||||||
family_name_monospace: "",
|
family_name_monospace: "",
|
||||||
},
|
},
|
||||||
PathBuf::new(), //FIXME: pass from somewhere else
|
PathBuf::new(), //FIXME: pass from somewhere else
|
||||||
params.color_palette,
|
palette,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@ use wgui::{
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, WidgetID},
|
layout::{Layout, WidgetID},
|
||||||
|
log::LogErr,
|
||||||
palette::PALETTES,
|
palette::PALETTES,
|
||||||
parser::{Fetchable, ParseDocumentParams, TemplateParams},
|
parser::{Fetchable, ParseDocumentParams, TemplateParams},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
};
|
};
|
||||||
use wlx_common::dash_interface::ConfigChangeKind;
|
use wlx_common::{
|
||||||
|
dash_interface::ConfigChangeKind,
|
||||||
|
palette::{list_palette_files, load_custom_palette},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
frontend::{FrontendTask, FrontendTasks},
|
frontend::{FrontendTask, FrontendTasks},
|
||||||
|
|
@ -22,6 +26,7 @@ use crate::{
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Task {
|
enum Task {
|
||||||
SelectPalette(String),
|
SelectPalette(String),
|
||||||
|
CustomPaletteUrl,
|
||||||
Restart,
|
Restart,
|
||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
@ -66,6 +71,11 @@ impl ViewTrait for View {
|
||||||
|
|
||||||
self.settings_tasks.push(SettingsTask::RestartSoftware);
|
self.settings_tasks.push(SettingsTask::RestartSoftware);
|
||||||
}
|
}
|
||||||
|
Task::CustomPaletteUrl => {
|
||||||
|
self.frontend_tasks.push(FrontendTask::OpenURL(
|
||||||
|
"https://wayvr.org/docs/basics/customization/".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -105,8 +115,67 @@ impl View {
|
||||||
let tasks = Tasks::new();
|
let tasks = Tasks::new();
|
||||||
let popup_dialog = PopupHolder::<views::dialog_box::View>::default();
|
let popup_dialog = PopupHolder::<views::dialog_box::View>::default();
|
||||||
|
|
||||||
|
for (idx, name) in list_palette_files().into_iter().enumerate() {
|
||||||
|
let Ok(palette) = load_custom_palette(&name).log_warn("Could not load custom color palette") else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = format!("profile_custom_{idx}");
|
||||||
|
let is_current = &*params.current_palette == name.as_str();
|
||||||
|
|
||||||
|
let mut cell_params = TemplateParams::new();
|
||||||
|
cell_params.insert("id", &id);
|
||||||
|
|
||||||
|
let display_name = &name[..name.len() - 5];
|
||||||
|
|
||||||
|
if is_current {
|
||||||
|
cell_params.insert_str("text", format!("{display_name} ✅"));
|
||||||
|
cell_params.insert("tooltip", "APP_SETTINGS.COLOR_PALETTE_CURRENT");
|
||||||
|
} else {
|
||||||
|
cell_params.insert("text", display_name);
|
||||||
|
cell_params.insert("tooltip", "APP_SETTINGS.COLOR_PALETTE_ACTIVATE");
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_colors!(
|
||||||
|
cell_params,
|
||||||
|
&palette,
|
||||||
|
"primary" => Primary,
|
||||||
|
"on_primary" => OnPrimary,
|
||||||
|
"secondary" => Secondary,
|
||||||
|
"on_secondary" => OnSecondary,
|
||||||
|
"tertiary" => Tertiary,
|
||||||
|
"on_tertiary" => OnTertiary,
|
||||||
|
"danger" => Danger,
|
||||||
|
"on_danger" => OnDanger,
|
||||||
|
"background" => Background,
|
||||||
|
"on_background" => OnBackground,
|
||||||
|
"background_variant" => BackgroundVariant,
|
||||||
|
"outline" => Outline,
|
||||||
|
"highlight" => Highlight,
|
||||||
|
);
|
||||||
|
|
||||||
|
parser_state.instantiate_template(
|
||||||
|
doc_params,
|
||||||
|
"ColorPaletteButton",
|
||||||
|
params.layout,
|
||||||
|
list_parent,
|
||||||
|
cell_params,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
if !is_current {
|
||||||
|
let btn = parser_state.fetch_component_as::<ComponentButton>(&id)?;
|
||||||
|
let tasks_clone = tasks.clone();
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks_clone.push(Task::SelectPalette(name.to_string()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (idx, (name, palette)) in PALETTES.iter().enumerate() {
|
for (idx, (name, palette)) in PALETTES.iter().enumerate() {
|
||||||
let id = format!("profile_btn_{idx}");
|
let id = format!("profile_builtin_{idx}");
|
||||||
let is_current = &*params.current_palette == *name;
|
let is_current = &*params.current_palette == *name;
|
||||||
|
|
||||||
let mut cell_params = TemplateParams::new();
|
let mut cell_params = TemplateParams::new();
|
||||||
|
|
@ -158,6 +227,22 @@ impl View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser_state.instantiate_template(
|
||||||
|
doc_params,
|
||||||
|
"CustomPaletteButton",
|
||||||
|
params.layout,
|
||||||
|
list_parent,
|
||||||
|
TemplateParams::default(),
|
||||||
|
)?;
|
||||||
|
let btn = parser_state.fetch_component_as::<ComponentButton>("custom_btn")?;
|
||||||
|
let tasks_clone = tasks.clone();
|
||||||
|
btn.on_click(Rc::new({
|
||||||
|
move |_common, _e| {
|
||||||
|
tasks_clone.push(Task::CustomPaletteUrl);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
tasks,
|
tasks,
|
||||||
frontend_tasks: params.frontend_tasks.clone(),
|
frontend_tasks: params.frontend_tasks.clone(),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use wgui::{
|
||||||
font_config::WguiFontConfig,
|
font_config::WguiFontConfig,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
layout::{Layout, LayoutParams, LayoutUpdateParams},
|
layout::{Layout, LayoutParams, LayoutUpdateParams},
|
||||||
|
palette::WguiColorPalette,
|
||||||
parser::{ParseDocumentParams, ParserState},
|
parser::{ParseDocumentParams, ParserState},
|
||||||
};
|
};
|
||||||
use wlx_common::locale::WayVRLangProvider;
|
use wlx_common::locale::WayVRLangProvider;
|
||||||
|
|
@ -37,7 +38,7 @@ impl TestbedAny {
|
||||||
&lang_provider,
|
&lang_provider,
|
||||||
&WguiFontConfig::default(),
|
&WguiFontConfig::default(),
|
||||||
PathBuf::new(), // cwd
|
PathBuf::new(), // cwd
|
||||||
&palette_name,
|
WguiColorPalette::get_builtin(&palette_name),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,16 @@ use glam::Vec2;
|
||||||
use wgui::{
|
use wgui::{
|
||||||
assets::AssetPath,
|
assets::AssetPath,
|
||||||
components::{
|
components::{
|
||||||
Component,
|
|
||||||
button::{ButtonClickCallback, ComponentButton},
|
button::{ButtonClickCallback, ComponentButton},
|
||||||
checkbox::ComponentCheckbox,
|
checkbox::ComponentCheckbox,
|
||||||
|
Component,
|
||||||
},
|
},
|
||||||
drawing::Color,
|
drawing::Color,
|
||||||
font_config::WguiFontConfig,
|
font_config::WguiFontConfig,
|
||||||
globals::WguiGlobals,
|
globals::WguiGlobals,
|
||||||
i18n::Translation,
|
i18n::Translation,
|
||||||
layout::{Layout, LayoutParams, LayoutUpdateParams, Widget},
|
layout::{Layout, LayoutParams, LayoutUpdateParams, Widget},
|
||||||
|
palette::WguiColorPalette,
|
||||||
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
|
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
|
||||||
taffy::{self, prelude::length},
|
taffy::{self, prelude::length},
|
||||||
task::Tasks,
|
task::Tasks,
|
||||||
|
|
@ -93,7 +94,7 @@ impl TestbedGeneric {
|
||||||
&lang_provider,
|
&lang_provider,
|
||||||
&WguiFontConfig::default(),
|
&WguiFontConfig::default(),
|
||||||
PathBuf::new(), // cwd
|
PathBuf::new(), // cwd
|
||||||
&palette_name,
|
WguiColorPalette::get_builtin(&palette_name),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let extra = ParseDocumentExtra {
|
let extra = ParseDocumentExtra {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ use wgui::{
|
||||||
use wlx_capture::pipewire::ScreenCastManager;
|
use wlx_capture::pipewire::ScreenCastManager;
|
||||||
use wlx_common::config::PwTokenMap;
|
use wlx_common::config::PwTokenMap;
|
||||||
use wlx_common::locale::WayVRLangProvider;
|
use wlx_common::locale::WayVRLangProvider;
|
||||||
|
use wlx_common::palette::load_palette;
|
||||||
use wlx_common::{
|
use wlx_common::{
|
||||||
audio,
|
audio,
|
||||||
config::GeneralConfig,
|
config::GeneralConfig,
|
||||||
|
|
@ -167,6 +168,8 @@ impl AppState {
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
let palette = load_palette(&*session.config.color_palette);
|
||||||
|
|
||||||
let mut app_state = Self {
|
let mut app_state = Self {
|
||||||
tasks,
|
tasks,
|
||||||
gfx,
|
gfx,
|
||||||
|
|
@ -184,7 +187,7 @@ impl AppState {
|
||||||
&lang_provider,
|
&lang_provider,
|
||||||
&WguiFontConfig::default(),
|
&WguiFontConfig::default(),
|
||||||
get_config_file_path(&theme_path),
|
get_config_file_path(&theme_path),
|
||||||
&session.config.color_palette,
|
palette,
|
||||||
)?,
|
)?,
|
||||||
wgui_theme: Rc::new(theme),
|
wgui_theme: Rc::new(theme),
|
||||||
dbus,
|
dbus,
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ impl WguiGlobals {
|
||||||
lang_provider: &dyn LangProvider,
|
lang_provider: &dyn LangProvider,
|
||||||
font_config: &WguiFontConfig,
|
font_config: &WguiFontConfig,
|
||||||
asset_folder: PathBuf,
|
asset_folder: PathBuf,
|
||||||
color_palette: &str,
|
palette: WguiColorPalette,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
let i18n_builtin = I18n::new(assets_builtin.as_mut(), lang_provider)?;
|
let i18n_builtin = I18n::new(assets_builtin.as_mut(), lang_provider)?;
|
||||||
let assets_internal = Box::new(assets_internal::AssetInternal {});
|
let assets_internal = Box::new(assets_internal::AssetInternal {});
|
||||||
|
|
@ -49,7 +49,7 @@ impl WguiGlobals {
|
||||||
font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()),
|
font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()),
|
||||||
i18n_builtin,
|
i18n_builtin,
|
||||||
custom_glyph_cache: CustomGlyphCache::new(),
|
custom_glyph_cache: CustomGlyphCache::new(),
|
||||||
palette: WguiColorPalette::from_name(color_palette),
|
palette,
|
||||||
}))))
|
}))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ pub struct WguiColorPalette {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WguiColorPalette {
|
impl WguiColorPalette {
|
||||||
pub fn from_name(palette_name: &str) -> Self {
|
pub fn get_builtin(palette_name: &str) -> Self {
|
||||||
for (name, palette) in PALETTES {
|
for (name, palette) in PALETTES {
|
||||||
if *name == palette_name {
|
if *name == palette_name {
|
||||||
// just clone here, makes it easier for future customization
|
// just clone here, makes it easier for future customization
|
||||||
|
|
@ -25,6 +25,10 @@ impl WguiColorPalette {
|
||||||
return DEFAULT.clone();
|
return DEFAULT.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const fn from_inner(colors: [drawing::Color; WguiColorName::COUNT]) -> Self {
|
||||||
|
Self { colors }
|
||||||
|
}
|
||||||
|
|
||||||
fn apply_modifier(color: WguiColor, modifier: &str) -> Option<WguiColor> {
|
fn apply_modifier(color: WguiColor, modifier: &str) -> Option<WguiColor> {
|
||||||
match modifier {
|
match modifier {
|
||||||
"transparent" => Some(color.with_alpha(0.0)),
|
"transparent" => Some(color.with_alpha(0.0)),
|
||||||
|
|
@ -82,8 +86,8 @@ const fn hex(hex: &str) -> drawing::Color {
|
||||||
|
|
||||||
pub static PALETTES: &[(&'static str, &WguiColorPalette)] = &[
|
pub static PALETTES: &[(&'static str, &WguiColorPalette)] = &[
|
||||||
("Default", DEFAULT),
|
("Default", DEFAULT),
|
||||||
("Ayu", AYU),
|
("Ayu Dusk", AYU),
|
||||||
("Catppuccin", CATTPUCCIN),
|
("Catppuccin", CATPPUCCIN),
|
||||||
("Cyberpunk", CYBERPUNK),
|
("Cyberpunk", CYBERPUNK),
|
||||||
("Dracula", DRACULA),
|
("Dracula", DRACULA),
|
||||||
("Eldritch", ELDRITCH),
|
("Eldritch", ELDRITCH),
|
||||||
|
|
@ -93,21 +97,21 @@ pub static PALETTES: &[(&'static str, &WguiColorPalette)] = &[
|
||||||
("Monochrome", MONOCHROME),
|
("Monochrome", MONOCHROME),
|
||||||
("Nord", NORD),
|
("Nord", NORD),
|
||||||
("Osaka Jade", OSAKA_JADE),
|
("Osaka Jade", OSAKA_JADE),
|
||||||
("Rosepine", ROSEPINE),
|
("Rosé Pine", ROSEPINE),
|
||||||
("Solarized Night", SOLARIZED_NIGHT),
|
("Solarized Night", SOLARIZED_NIGHT),
|
||||||
("Tokyo Night", TOKYO_NIGHT),
|
("Tokyo Night", TOKYO_NIGHT),
|
||||||
("Ayu Light", AYU_LIGHT),
|
("Ayu Day", AYU_LIGHT),
|
||||||
("Catppuccin Light", CATTPUCCIN_LIGHT),
|
("Catppuccin Latte", CATPPUCCIN_LATTE),
|
||||||
("Cyberpunk Light", CYBERPUNK_LIGHT),
|
("Cyberpunk Light", CYBERPUNK_LIGHT),
|
||||||
("Dracula Light", DRACULA_LIGHT),
|
("Alucard", DRACULA_LIGHT),
|
||||||
("Eldritch Light", ELDRITCH_LIGHT),
|
("Eldritch Dusk", ELDRITCH_LIGHT),
|
||||||
("Everforest Light", EVERFOREST_LIGHT),
|
("Everforest Light", EVERFOREST_LIGHT),
|
||||||
("Gruvbox Light", GRUVBOX_LIGHT),
|
("Gruvbox Light", GRUVBOX_LIGHT),
|
||||||
("Kanagawa Light", KANAGAWA_LIGHT),
|
("Kanagawa Lotus", KANAGAWA_LIGHT),
|
||||||
("Monochrome Light", MONOCHROME_LIGHT),
|
("Monochrome Light", MONOCHROME_LIGHT),
|
||||||
("Nord Light", NORD_LIGHT),
|
("Nord Light", NORD_LIGHT),
|
||||||
("Osaka Jade Light", OSAKA_JADE_LIGHT),
|
("Osaka Jade Light", OSAKA_JADE_LIGHT),
|
||||||
("Rosepine Light", ROSEPINE_LIGHT),
|
("Rosé Pine Dawn", ROSEPINE_LIGHT),
|
||||||
("Solarized Day", SOLARIZED_DAY),
|
("Solarized Day", SOLARIZED_DAY),
|
||||||
("Tokyo Day", TOKYO_DAY),
|
("Tokyo Day", TOKYO_DAY),
|
||||||
];
|
];
|
||||||
|
|
@ -178,7 +182,7 @@ static AYU_LIGHT: &WguiColorPalette = &WguiColorPalette {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
static CATTPUCCIN: &WguiColorPalette = &WguiColorPalette {
|
static CATPPUCCIN: &WguiColorPalette = &WguiColorPalette {
|
||||||
colors: [
|
colors: [
|
||||||
hex("#cba6f7"), // Primary
|
hex("#cba6f7"), // Primary
|
||||||
hex("#11111b"), // OnPrimary
|
hex("#11111b"), // OnPrimary
|
||||||
|
|
@ -200,13 +204,13 @@ static CATTPUCCIN: &WguiColorPalette = &WguiColorPalette {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
static CATTPUCCIN_LIGHT: &WguiColorPalette = &WguiColorPalette {
|
static CATPPUCCIN_LATTE: &WguiColorPalette = &WguiColorPalette {
|
||||||
colors: [
|
colors: [
|
||||||
hex("#8839EF"), // Primary
|
hex("#8839EF"), // Primary
|
||||||
hex("#EFF1F5"), // OnPrimary
|
hex("#EFF1F5"), // OnPrimary
|
||||||
hex("#FE640B"), // Secondary
|
hex("#FE640B"), // Secondary
|
||||||
hex("#EFF1F5"), // OnSecondary
|
hex("#EFF1F5"), // OnSecondary
|
||||||
hex("#40A02B"), // Tertiary
|
hex("#179299"), // Tertiary
|
||||||
hex("#EFF1F5"), // OnTertiary
|
hex("#EFF1F5"), // OnTertiary
|
||||||
hex("#D20F39"), // Danger
|
hex("#D20F39"), // Danger
|
||||||
hex("#DCE0E8"), // OnDanger
|
hex("#DCE0E8"), // OnDanger
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ pub fn get_skymaps_root() -> PathBuf {
|
||||||
get_config_root().join("skymaps")
|
get_config_root().join("skymaps")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_palettes_root() -> PathBuf {
|
||||||
|
get_config_root().join("palettes")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_skymaps_uuids() -> anyhow::Result<Vec<String>> {
|
pub fn get_skymaps_uuids() -> anyhow::Result<Vec<String>> {
|
||||||
let data = std::fs::read_to_string(get_skymaps_root().join("skymaps.txt"))?;
|
let data = std::fs::read_to_string(get_skymaps_root().join("skymaps.txt"))?;
|
||||||
Ok(data.lines().filter(|line| !line.is_empty()).map(String::from).collect())
|
Ok(data.lines().filter(|line| !line.is_empty()).map(String::from).collect())
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,6 @@ pub mod openxr_actions;
|
||||||
pub mod openxr_bindings_schema;
|
pub mod openxr_bindings_schema;
|
||||||
pub mod openxr_controller_profiles;
|
pub mod openxr_controller_profiles;
|
||||||
pub mod overlays;
|
pub mod overlays;
|
||||||
|
pub mod palette;
|
||||||
pub mod timestep;
|
pub mod timestep;
|
||||||
pub mod windowing;
|
pub mod windowing;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
use std::{fs::File, io::BufReader};
|
||||||
|
|
||||||
|
use serde::{de::Error as _, Deserialize, Deserializer};
|
||||||
|
use wgui::{
|
||||||
|
drawing,
|
||||||
|
log::LogErr,
|
||||||
|
palette::{WguiColorPalette, PALETTES},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::config_io;
|
||||||
|
|
||||||
|
pub fn load_palette(want_palette: &str) -> WguiColorPalette {
|
||||||
|
if is_custom_palette(want_palette) {
|
||||||
|
if let Ok(palette) = load_custom_palette(want_palette).log_warn("Could not load custom color palette") {
|
||||||
|
return palette;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (name, palette) in PALETTES {
|
||||||
|
if *name == want_palette {
|
||||||
|
return (*palette).clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::warn!("No color palette found with name: {want_palette}")
|
||||||
|
}
|
||||||
|
PALETTES[0].1.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_custom_palette(name: &str) -> bool {
|
||||||
|
name
|
||||||
|
.as_bytes()
|
||||||
|
.get(name.len().saturating_sub(5)..)
|
||||||
|
.is_some_and(|suffix| suffix.eq_ignore_ascii_case(b".json"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn list_palette_files() -> Vec<String> {
|
||||||
|
let path = config_io::get_palettes_root();
|
||||||
|
let Ok(entries) = std::fs::read_dir(path) else {
|
||||||
|
return Vec::new();
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut files: Vec<_> = entries
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.filter_map(|entry| {
|
||||||
|
let path = entry.path();
|
||||||
|
|
||||||
|
if !path.is_file() || !path.extension()?.to_str()?.eq_ignore_ascii_case("json") {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(path.file_name()?.to_str()?.to_owned())
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
files.sort_unstable();
|
||||||
|
files
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_custom_palette(name: &str) -> anyhow::Result<WguiColorPalette> {
|
||||||
|
let path = config_io::get_palettes_root().join(name);
|
||||||
|
let file = File::open(path)?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
let scp = serde_json::from_reader::<_, SerializedWguiColorPalette>(reader)?;
|
||||||
|
Ok(scp.into_palette())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_color<'de, D>(deserializer: D) -> Result<drawing::Color, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let value = String::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
drawing::Color::from_hex(&value).ok_or_else(|| D::Error::custom(format!("invalid hexadecimal color: {value:?}")))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct SerializedWguiColorPalette {
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
primary: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_primary: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
secondary: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_secondary: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
tertiary: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_tertiary: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
danger: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_danger: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
background: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_background: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
background_variant: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_background_variant: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
background_contrast: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
on_background_contrast: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
outline: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
shadow: drawing::Color,
|
||||||
|
|
||||||
|
#[serde(deserialize_with = "deserialize_color")]
|
||||||
|
highlight: drawing::Color,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerializedWguiColorPalette {
|
||||||
|
pub fn into_palette(&self) -> WguiColorPalette {
|
||||||
|
// order must stay the same as per WguiColorName
|
||||||
|
WguiColorPalette::from_inner([
|
||||||
|
self.primary,
|
||||||
|
self.on_primary,
|
||||||
|
self.secondary,
|
||||||
|
self.on_secondary,
|
||||||
|
self.tertiary,
|
||||||
|
self.on_tertiary,
|
||||||
|
self.danger,
|
||||||
|
self.on_danger,
|
||||||
|
self.background,
|
||||||
|
self.on_background,
|
||||||
|
self.background_variant,
|
||||||
|
self.on_background_variant,
|
||||||
|
self.background_contrast,
|
||||||
|
self.on_background_contrast,
|
||||||
|
self.outline,
|
||||||
|
self.shadow,
|
||||||
|
self.highlight,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue