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>
|
||||
<!-- id, text -->
|
||||
<template name="ColorPaletteButton">
|
||||
<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" >
|
||||
|
|
@ -13,6 +12,13 @@
|
|||
</Button>
|
||||
</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>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -190,7 +190,9 @@
|
|||
"COLOR_PALETTE_CURRENT": "Derzeit aktives Thema.",
|
||||
"COLOR_PALETTE_ACTIVATE": "Klicken Sie hier, um dieses Thema zu verwenden.",
|
||||
"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!",
|
||||
"AUDIO": {
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@
|
|||
"COLOR_PALETTE_HELP": "Click to browse color palettes.\nTo create custom ones, see website!",
|
||||
"COLOR_PALETTES": "Color palettes",
|
||||
"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.",
|
||||
"APPLY_CHANGES_RESTART": "Restart WayVR to apply changes?",
|
||||
"CLEAR_PIPEWIRE_TOKENS": "Clear PipeWire tokens",
|
||||
|
|
|
|||
|
|
@ -190,7 +190,9 @@
|
|||
"COLOR_PALETTE_CURRENT": "Tema actualmente activo.",
|
||||
"COLOR_PALETTE_ACTIVATE": "Haz clic para usar este tema.",
|
||||
"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!",
|
||||
"AUDIO": {
|
||||
|
|
|
|||
|
|
@ -211,7 +211,9 @@
|
|||
"COLOR_PALETTE_CURRENT": "Tema attualmente attivo.",
|
||||
"COLOR_PALETTE_ACTIVATE": "Clicca per usare questo tema.",
|
||||
"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_STARTED": "Applicazione avviata",
|
||||
|
|
|
|||
|
|
@ -190,7 +190,9 @@
|
|||
"COLOR_PALETTE_CURRENT": "現在有効なテーマ。",
|
||||
"COLOR_PALETTE_ACTIVATE": "クリックしてこのテーマを適用します。",
|
||||
"APPLY_CHANGES_RESTART": "変更を適用するためにWayVRを再起動しますか?",
|
||||
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択してください。\nカスタムパレットの作成については、ウェブサイトを参照してください!"
|
||||
"COLOR_PALETTE_HELP": "クリックしてカラーパレットを選択してください。\nカスタムパレットの作成については、ウェブサイトを参照してください!",
|
||||
"COLOR_PALETTE_CUSTOM_URL": "カスタムテーマを追加しましょう!",
|
||||
"COLOR_PALETTE_CUSTOM_URL2": "クリックしてウェブマニュアルを開く。"
|
||||
},
|
||||
"HELLO": "こんにちは!",
|
||||
"AUDIO": {
|
||||
|
|
|
|||
|
|
@ -185,7 +185,9 @@
|
|||
"COLOR_PALETTE_CURRENT": "Obecnie aktywny motyw.",
|
||||
"COLOR_PALETTE_ACTIVATE": "Kliknij, aby użyć tego motywu.",
|
||||
"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",
|
||||
"APPLICATIONS": "Aplikacje",
|
||||
|
|
|
|||
|
|
@ -211,7 +211,9 @@
|
|||
"COLOR_PALETTE_CURRENT": "当前激活的主题。",
|
||||
"COLOR_PALETTE_ACTIVATE": "点击以使用此主题。",
|
||||
"APPLY_CHANGES_RESTART": "重启 WayVR 以应用更改吗?",
|
||||
"COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义配色,请参阅网站!"
|
||||
"COLOR_PALETTE_HELP": "点击浏览配色方案。\n如需创建自定义配色,请参阅网站!",
|
||||
"COLOR_PALETTE_CUSTOM_URL": "添加自定义主题!",
|
||||
"COLOR_PALETTE_CUSTOM_URL2": "点击打开网页版手册。"
|
||||
},
|
||||
"APPLICATION_LAUNCHER": "应用启动器",
|
||||
"APPLICATION_STARTED": "应用已启动",
|
||||
|
|
|
|||
|
|
@ -24,14 +24,15 @@ use wlx_common::{
|
|||
audio,
|
||||
dash_interface::{BoxDashInterface, ConfigChangeKind, RecenterMode},
|
||||
locale::WayVRLangProvider,
|
||||
palette::load_palette,
|
||||
timestep::{self, Timestep},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
assets,
|
||||
tab::{
|
||||
Tab, TabType, apps::TabApps, donate::TabDonate, games::TabGames, home::TabHome, monado::TabMonado,
|
||||
settings::TabSettings, welcome::TabWelcome,
|
||||
apps::TabApps, donate::TabDonate, games::TabGames, home::TabHome, monado::TabMonado, settings::TabSettings,
|
||||
welcome::TabWelcome, Tab, TabType,
|
||||
},
|
||||
util::{
|
||||
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_light = assets.load_from_path_gzip("Quicksand-Light.ttf.gz")?;
|
||||
|
||||
let palette = load_palette(params.color_palette);
|
||||
|
||||
let globals = WguiGlobals::new(
|
||||
assets,
|
||||
params.lang_provider,
|
||||
|
|
@ -141,7 +144,7 @@ impl<T: 'static> Frontend<T> {
|
|||
family_name_monospace: "",
|
||||
},
|
||||
PathBuf::new(), //FIXME: pass from somewhere else
|
||||
params.color_palette,
|
||||
palette,
|
||||
)?;
|
||||
|
||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||
|
|
|
|||
|
|
@ -6,11 +6,15 @@ use wgui::{
|
|||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID},
|
||||
log::LogErr,
|
||||
palette::PALETTES,
|
||||
parser::{Fetchable, ParseDocumentParams, TemplateParams},
|
||||
task::Tasks,
|
||||
};
|
||||
use wlx_common::dash_interface::ConfigChangeKind;
|
||||
use wlx_common::{
|
||||
dash_interface::ConfigChangeKind,
|
||||
palette::{list_palette_files, load_custom_palette},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
frontend::{FrontendTask, FrontendTasks},
|
||||
|
|
@ -22,6 +26,7 @@ use crate::{
|
|||
#[derive(Clone)]
|
||||
enum Task {
|
||||
SelectPalette(String),
|
||||
CustomPaletteUrl,
|
||||
Restart,
|
||||
Cancel,
|
||||
}
|
||||
|
|
@ -66,6 +71,11 @@ impl ViewTrait for View {
|
|||
|
||||
self.settings_tasks.push(SettingsTask::RestartSoftware);
|
||||
}
|
||||
Task::CustomPaletteUrl => {
|
||||
self.frontend_tasks.push(FrontendTask::OpenURL(
|
||||
"https://wayvr.org/docs/basics/customization/".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -105,8 +115,67 @@ impl View {
|
|||
let tasks = Tasks::new();
|
||||
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() {
|
||||
let id = format!("profile_btn_{idx}");
|
||||
let id = format!("profile_builtin_{idx}");
|
||||
let is_current = &*params.current_palette == *name;
|
||||
|
||||
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 {
|
||||
tasks,
|
||||
frontend_tasks: params.frontend_tasks.clone(),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use wgui::{
|
|||
font_config::WguiFontConfig,
|
||||
globals::WguiGlobals,
|
||||
layout::{Layout, LayoutParams, LayoutUpdateParams},
|
||||
palette::WguiColorPalette,
|
||||
parser::{ParseDocumentParams, ParserState},
|
||||
};
|
||||
use wlx_common::locale::WayVRLangProvider;
|
||||
|
|
@ -37,7 +38,7 @@ impl TestbedAny {
|
|||
&lang_provider,
|
||||
&WguiFontConfig::default(),
|
||||
PathBuf::new(), // cwd
|
||||
&palette_name,
|
||||
WguiColorPalette::get_builtin(&palette_name),
|
||||
)?;
|
||||
|
||||
let (layout, state) = wgui::parser::new_layout_from_assets(
|
||||
|
|
|
|||
|
|
@ -8,15 +8,16 @@ use glam::Vec2;
|
|||
use wgui::{
|
||||
assets::AssetPath,
|
||||
components::{
|
||||
Component,
|
||||
button::{ButtonClickCallback, ComponentButton},
|
||||
checkbox::ComponentCheckbox,
|
||||
Component,
|
||||
},
|
||||
drawing::Color,
|
||||
font_config::WguiFontConfig,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, LayoutParams, LayoutUpdateParams, Widget},
|
||||
palette::WguiColorPalette,
|
||||
parser::{Fetchable, ParseDocumentExtra, ParseDocumentParams, ParserState},
|
||||
taffy::{self, prelude::length},
|
||||
task::Tasks,
|
||||
|
|
@ -93,7 +94,7 @@ impl TestbedGeneric {
|
|||
&lang_provider,
|
||||
&WguiFontConfig::default(),
|
||||
PathBuf::new(), // cwd
|
||||
&palette_name,
|
||||
WguiColorPalette::get_builtin(&palette_name),
|
||||
)?;
|
||||
|
||||
let extra = ParseDocumentExtra {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use wgui::{
|
|||
use wlx_capture::pipewire::ScreenCastManager;
|
||||
use wlx_common::config::PwTokenMap;
|
||||
use wlx_common::locale::WayVRLangProvider;
|
||||
use wlx_common::palette::load_palette;
|
||||
use wlx_common::{
|
||||
audio,
|
||||
config::GeneralConfig,
|
||||
|
|
@ -167,6 +168,8 @@ impl AppState {
|
|||
)
|
||||
.ok();
|
||||
|
||||
let palette = load_palette(&*session.config.color_palette);
|
||||
|
||||
let mut app_state = Self {
|
||||
tasks,
|
||||
gfx,
|
||||
|
|
@ -184,7 +187,7 @@ impl AppState {
|
|||
&lang_provider,
|
||||
&WguiFontConfig::default(),
|
||||
get_config_file_path(&theme_path),
|
||||
&session.config.color_palette,
|
||||
palette,
|
||||
)?,
|
||||
wgui_theme: Rc::new(theme),
|
||||
dbus,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ impl WguiGlobals {
|
|||
lang_provider: &dyn LangProvider,
|
||||
font_config: &WguiFontConfig,
|
||||
asset_folder: PathBuf,
|
||||
color_palette: &str,
|
||||
palette: WguiColorPalette,
|
||||
) -> anyhow::Result<Self> {
|
||||
let i18n_builtin = I18n::new(assets_builtin.as_mut(), lang_provider)?;
|
||||
let assets_internal = Box::new(assets_internal::AssetInternal {});
|
||||
|
|
@ -49,7 +49,7 @@ impl WguiGlobals {
|
|||
font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()),
|
||||
i18n_builtin,
|
||||
custom_glyph_cache: CustomGlyphCache::new(),
|
||||
palette: WguiColorPalette::from_name(color_palette),
|
||||
palette,
|
||||
}))))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ pub struct WguiColorPalette {
|
|||
}
|
||||
|
||||
impl WguiColorPalette {
|
||||
pub fn from_name(palette_name: &str) -> Self {
|
||||
pub fn get_builtin(palette_name: &str) -> Self {
|
||||
for (name, palette) in PALETTES {
|
||||
if *name == palette_name {
|
||||
// just clone here, makes it easier for future customization
|
||||
|
|
@ -25,6 +25,10 @@ impl WguiColorPalette {
|
|||
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> {
|
||||
match modifier {
|
||||
"transparent" => Some(color.with_alpha(0.0)),
|
||||
|
|
@ -82,8 +86,8 @@ const fn hex(hex: &str) -> drawing::Color {
|
|||
|
||||
pub static PALETTES: &[(&'static str, &WguiColorPalette)] = &[
|
||||
("Default", DEFAULT),
|
||||
("Ayu", AYU),
|
||||
("Catppuccin", CATTPUCCIN),
|
||||
("Ayu Dusk", AYU),
|
||||
("Catppuccin", CATPPUCCIN),
|
||||
("Cyberpunk", CYBERPUNK),
|
||||
("Dracula", DRACULA),
|
||||
("Eldritch", ELDRITCH),
|
||||
|
|
@ -93,21 +97,21 @@ pub static PALETTES: &[(&'static str, &WguiColorPalette)] = &[
|
|||
("Monochrome", MONOCHROME),
|
||||
("Nord", NORD),
|
||||
("Osaka Jade", OSAKA_JADE),
|
||||
("Rosepine", ROSEPINE),
|
||||
("Rosé Pine", ROSEPINE),
|
||||
("Solarized Night", SOLARIZED_NIGHT),
|
||||
("Tokyo Night", TOKYO_NIGHT),
|
||||
("Ayu Light", AYU_LIGHT),
|
||||
("Catppuccin Light", CATTPUCCIN_LIGHT),
|
||||
("Ayu Day", AYU_LIGHT),
|
||||
("Catppuccin Latte", CATPPUCCIN_LATTE),
|
||||
("Cyberpunk Light", CYBERPUNK_LIGHT),
|
||||
("Dracula Light", DRACULA_LIGHT),
|
||||
("Eldritch Light", ELDRITCH_LIGHT),
|
||||
("Alucard", DRACULA_LIGHT),
|
||||
("Eldritch Dusk", ELDRITCH_LIGHT),
|
||||
("Everforest Light", EVERFOREST_LIGHT),
|
||||
("Gruvbox Light", GRUVBOX_LIGHT),
|
||||
("Kanagawa Light", KANAGAWA_LIGHT),
|
||||
("Kanagawa Lotus", KANAGAWA_LIGHT),
|
||||
("Monochrome Light", MONOCHROME_LIGHT),
|
||||
("Nord Light", NORD_LIGHT),
|
||||
("Osaka Jade Light", OSAKA_JADE_LIGHT),
|
||||
("Rosepine Light", ROSEPINE_LIGHT),
|
||||
("Rosé Pine Dawn", ROSEPINE_LIGHT),
|
||||
("Solarized Day", SOLARIZED_DAY),
|
||||
("Tokyo Day", TOKYO_DAY),
|
||||
];
|
||||
|
|
@ -178,7 +182,7 @@ static AYU_LIGHT: &WguiColorPalette = &WguiColorPalette {
|
|||
],
|
||||
};
|
||||
|
||||
static CATTPUCCIN: &WguiColorPalette = &WguiColorPalette {
|
||||
static CATPPUCCIN: &WguiColorPalette = &WguiColorPalette {
|
||||
colors: [
|
||||
hex("#cba6f7"), // Primary
|
||||
hex("#11111b"), // OnPrimary
|
||||
|
|
@ -200,13 +204,13 @@ static CATTPUCCIN: &WguiColorPalette = &WguiColorPalette {
|
|||
],
|
||||
};
|
||||
|
||||
static CATTPUCCIN_LIGHT: &WguiColorPalette = &WguiColorPalette {
|
||||
static CATPPUCCIN_LATTE: &WguiColorPalette = &WguiColorPalette {
|
||||
colors: [
|
||||
hex("#8839EF"), // Primary
|
||||
hex("#EFF1F5"), // OnPrimary
|
||||
hex("#FE640B"), // Secondary
|
||||
hex("#EFF1F5"), // OnSecondary
|
||||
hex("#40A02B"), // Tertiary
|
||||
hex("#179299"), // Tertiary
|
||||
hex("#EFF1F5"), // OnTertiary
|
||||
hex("#D20F39"), // Danger
|
||||
hex("#DCE0E8"), // OnDanger
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ pub fn get_skymaps_root() -> PathBuf {
|
|||
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>> {
|
||||
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())
|
||||
|
|
|
|||
|
|
@ -15,5 +15,6 @@ pub mod openxr_actions;
|
|||
pub mod openxr_bindings_schema;
|
||||
pub mod openxr_controller_profiles;
|
||||
pub mod overlays;
|
||||
pub mod palette;
|
||||
pub mod timestep;
|
||||
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