wgui: Color palette (wip)

(uidev & dash-frontend compilable)
This commit is contained in:
Aleksander 2026-07-10 22:09:09 +02:00
parent b83c54334f
commit a00f2ab8db
57 changed files with 549 additions and 338 deletions

2
Cargo.lock generated
View File

@ -6603,6 +6603,7 @@ dependencies = [
"image",
"log",
"lru",
"num_enum",
"ouroboros",
"parking_lot",
"regex",
@ -6613,6 +6614,7 @@ dependencies = [
"serde_json",
"slotmap",
"smallvec",
"strum",
"taffy",
"vulkano",
"vulkano-shaders",

View File

@ -1,6 +1,4 @@
<layout>
<include src="theme.xml" />
<theme>
<var key="side_size" value="48" />
<var key="top_size" value="40" />
@ -39,7 +37,7 @@
<rectangle
width="100%"
round="100%"
color="~color_menu_dark"
color="background"
flex_direction="column"
justify_content="center"
align_items="center"
@ -65,13 +63,13 @@
<div position="relative" width="100%" height="~top_size" min_height="~top_size" max_height="~top_size" justify_content="end">
<!-- Title bar -->
<div width="100%" align_items="center" justify_content="center">
<rectangle min_width="300" height="100%" consume_mouse_events="1" round="100%" color="~color_top_panel" align_items="center" justify_content="center" gap="8">
<rectangle min_width="300" height="100%" consume_mouse_events="1" round="100%" color="background" align_items="center" justify_content="center" gap="8">
<sprite id="sprite_titlebar_icon" width="24" height="24" />
<label id="label_titlebar_title" weight="bold" size="16" text="Title" />
</rectangle>
</div>
<!-- Close button -->
<Button position="absolute" id="btn_close" color="~color_top_panel" round="100%" width="~top_size" height="~top_size" tooltip="CLOSE_WINDOW" tooltip_side="left">
<Button position="absolute" id="btn_close" color="background" round="100%" width="~top_size" height="~top_size" tooltip="CLOSE_WINDOW" tooltip_side="left">
<sprite src_builtin="dashboard/close.svg" width="32" height="32" />
</Button>
</div>
@ -120,7 +118,7 @@
flex_direction="row"
align_items="center"
justify_content="space_between"
color="~color_bottom_panel"
color="background_variant"
>
<!-- left gradient -->
<div position="absolute" width="100%" height="100%" justify_content="start">

View File

@ -1,6 +1,4 @@
<layout>
<include src="theme.xml" />
<macro name="dropdown_button"
flex_direction="row"
border="2"
@ -19,7 +17,7 @@
<div padding_top="4" padding_bottom="4">
<rectangle width="2" height="100%" color="#FFFFFF1A" />
</div>
<sprite margin_left="-4" width="30" height="30" color="~color_text" src_builtin="dashboard/down.svg" />
<sprite margin_left="-4" width="30" height="30" color="on_background_variant" src_builtin="dashboard/down.svg" />
</div>
</Button>
</template>

View File

@ -1,6 +1,4 @@
<layout>
<include src="theme.xml" />
<macro name="group_box"
flex_direction="column"
align_items="baseline"
@ -19,4 +17,4 @@
</div>
<rectangle color="#FFFFFF44" width="100%" height="2" />
</template>
</layout>
</layout>

View File

@ -1,7 +1,5 @@
<layout>
<include src="theme.xml" />
<macro name="home_button" round="8" color="#00000033" border_color="#FFFFFF77" hover_color="~color_accent" hover_border_color="#FFFFFF" />
<macro name="home_button" round="8" color="#00000033" border_color="#FFFFFF77" hover_color="primary" hover_border_color="#FFFFFF" />
<template name="MenuButton">
<Button

View File

@ -1,5 +1,4 @@
<layout>
<include src="../theme.xml" />
<include src="../t_group_box.xml" />
<!-- tooltip, src, src_ext, name -->
@ -21,7 +20,7 @@
<template name="CategoryText">
<rectangle width="100%" flex_direction="column" round="8" border="2" gradient="vertical" color2="#4477FF09" color="#5588FF10" border_color="#FFFFFF00">
<label margin="8" text="${text}" weight="bold" size="22" />
<rectangle height="2" color="~color_accent" margin_left="4" margin_right="4" />
<rectangle height="2" color="primary" margin_left="4" margin_right="4" />
</rectangle>
</template>

View File

@ -6,7 +6,7 @@
<div macro="video_overlay_content">
<PageTitle icon="dashboard/click.svg" translation="WELCOME.LASER_COLORS"/>
<div position="relative" flex_direction="row" gap="16" margin="16" align_self="end" justify_self="end" align_items="center">
<rectangle flex_direction="column" gap="8" padding="8" round="4" border_color="~color_accent" border="2" >
<rectangle flex_direction="column" gap="8" padding="8" round="4" border_color="primary" border="2" >
<label size="12" weight="bold" color="#00FFFF" translation="WELCOME.REGULAR_MODE_BLUE_LASER"/>
<label size="12" weight="bold" color="#FFAA00" translation="WELCOME.RIGHT_CLICK_MODE_ORANGE_LASER"/>
<label size="12" weight="bold" color="#FF88FF" translation="WELCOME.MIDDLE_CLICK_MODE_PURPLE_LASER"/>

View File

@ -5,22 +5,22 @@
<div flex_direction="row" align_items="center">
<image src_builtin="dashboard/check_3d.png" width="256" height="256"/>
<div flex_direction="column" gap="16" max_width="480">
<TextDescBig translation="WELCOME.ALL_SET" color="#AAFFAA"/>
<TextDescBig translation="WELCOME.ALL_SET" color="tertiary"/>
<rectangle color="#AAFFAA33" width="100%" min_height="2"/>
<label size="16" wrap="1" translation="WELCOME.BASICS"/>
<label size="16" wrap="1" translation="WELCOME.FEATURES_DOCUMENTATION"/>
<Button id="btn_wayvr_org" align_self="baseline" min_height="32">
<sprite src_builtin="dashboard/globe.svg" width="24" height="24" color="~color_accent" margin="8"/>
<sprite src_builtin="dashboard/globe.svg" width="24" height="24" color="primary" margin="8"/>
<label size="18" weight="bold" text="wayvr.org" margin_right="8" />
</Button>
<rectangle color="#FFFFFF33" width="100%" min_height="2"/>
<Button id="btn_home_screen" min_height="48">
<sprite src_builtin="dashboard/check.svg" width="32" height="32" color="~color_accent" margin="8"/>
<label size="20" weight="bold" translation="WELCOME.FINISH_TUTORIAL" margin_right="8" />
<Button id="btn_home_screen" min_height="48" >
<sprite src_builtin="dashboard/check.svg" width="32" height="32" margin="8"/>
<label color="on_background_variant" size="20" weight="bold" translation="WELCOME.FINISH_TUTORIAL" margin_right="8" />
</Button>
</div>
</div>

View File

@ -1,8 +0,0 @@
<layout>
<theme>
<var key="color_menu_dark" value="#0A0A0ACC" />
<var key="color_accent" value="#008cff" />
<var key="color_top_panel" value="#00000099" />
<var key="color_bottom_panel" value="#141e28" />
</theme>
</layout>

View File

@ -58,7 +58,7 @@
sprite_src_builtin="dashboard/magic_wand.svg"
min_width="32"
tooltip="AUDIO.AUTO_SWITCH_TO_VR_AUDIO"
color="~color_accent"
color="primary"
tooltip_side="right" />
<BottomButton id="btn_sinks" src_builtin="dashboard/volume.svg" translation="AUDIO.SPEAKERS" />

View File

@ -15,7 +15,7 @@
<!-- top row -->
<div flex_direction="row" gap="8" align_items="center">
<sprite src_builtin="dashboard/controller.svg" width="24" height="24"/>
<label translation="${translation}" color="~color_accent" weight="bold" size="14" />
<label translation="${translation}" color="primary" weight="bold" size="14" />
</div>
<!-- filled-in at runtime -->
</rectangle>

View File

@ -10,7 +10,7 @@
<div id="content" flex_direction="column" gap="8" width="100%">
<label translation="DOWNLOADING_FILE" size="24" weight="bold"/>
<Separator/>
<label id="label_target_path" color="~color_text_translucent" />
<label id="label_target_path" color="on_background" />
<div gap="8" align_items="center">
<div id="loading_parent"/>

View File

@ -1,6 +1,4 @@
<layout>
<include src="../theme.xml" />
<elements>
<div
consume_mouse_events="1"

View File

@ -20,7 +20,7 @@
<div id="resolution_buttons" gap="8" flex_direction="row">
<!-- filled-in at runtime -->
</div>
<image id="image" width="400" height="200" round="8" border="2" border_color="~color_accent"/>
<image id="image" width="400" height="200" round="8" border="2" border_color="primary"/>
<label id="label_author" weight="bold"/>
<label id="label_description" wrap="1"/>
<Separator/>

View File

@ -305,4 +305,4 @@
"REMOVE_FROM_FAVOURITES": "从收藏中移除",
"EMPTY": "空",
"PINNED_APPS": "已固定应用程序"
}
}

View File

@ -352,8 +352,8 @@ impl<T: 'static> Frontend<T> {
(0.8666, 0.9333)
};
rect.params.color.a = alpha1;
rect.params.color2.a = alpha2;
rect.params.color = rect.params.color.with_alpha(alpha1);
rect.params.color2 = rect.params.color2.with_alpha(alpha2);
Ok(())
}

View File

@ -3,8 +3,8 @@ use std::{marker::PhantomData, rc::Rc, str::FromStr};
use strum::{AsRefStr, EnumProperty, EnumString};
use wgui::{
assets::AssetPath,
color::WguiColorName,
components::tabs::ComponentTabs,
drawing,
event::StyleSetRequest,
globals::WguiGlobals,
i18n::Translation,
@ -597,7 +597,7 @@ fn mount_requires_restart(layout: &mut Layout, parent: WidgetID) -> anyhow::Resu
content,
style: TextStyle {
wrap: false,
color: Some(drawing::Color::new(1.0, 0.5, 0.5, 1.0)),
color: Some(WguiColorName::Danger.into()),
weight: Some(FontWeight::Bold),
size: Some(10.0),
..Default::default()

View File

@ -1,10 +1,9 @@
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
use glam::{Mat4, Vec3};
use std::{cell::RefCell, collections::VecDeque, rc::Rc};
use wgui::{
animation::{Animation, AnimationEasing},
color::{WguiColor, WguiColorName},
components::tooltip::{TOOLTIP_BORDER_COLOR, TOOLTIP_COLOR},
drawing::Color,
i18n::Translation,
layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
renderer_vk::{
@ -78,8 +77,8 @@ impl ToastManager {
let (rect, _) = layout.add_child(
root.id,
WidgetRectangle::create(WidgetRectangleParams {
color: TOOLTIP_COLOR,
border_color: TOOLTIP_BORDER_COLOR,
color: TOOLTIP_COLOR.into(),
border_color: TOOLTIP_BORDER_COLOR.into(),
border: 2.0,
round: WLength::Percent(1.0),
..Default::default()
@ -132,11 +131,15 @@ impl ToastManager {
}
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
rect.params.color.a = opacity;
rect.params.border_color.a = opacity;
rect.params.color = rect.params.color.with_alpha(opacity);
rect.params.border_color = rect.params.border_color.with_alpha(opacity);
let mut label = common.state.widgets.get_as::<WidgetLabel>(label.id).unwrap();
label.set_color(common, Color::new(1.0, 1.0, 1.0, opacity), true);
label.set_color(
common,
WguiColor::from(WguiColorName::BackgroundVariant).with_alpha(opacity),
true,
);
common.alterables.mark_redraw();
}),
));

View File

@ -2,8 +2,8 @@ use glam::{Mat4, Vec2};
use wgui::{
animation::{Animation, AnimationEasing},
assets::AssetPath,
color::WguiColorName,
components::{self, button::ButtonClickCallback},
drawing,
i18n::Translation,
layout::{Layout, LayoutTask, WidgetID},
parser::{Fetchable, ParseDocumentParams},
@ -70,7 +70,7 @@ pub fn create_label_error(layout: &mut Layout, parent: WidgetID, content: String
content: Translation::from_raw_text_string(content),
style: TextStyle {
wrap: true,
color: Some(drawing::Color::new(1.0, 0.5, 0.0, 1.0)),
color: Some(WguiColorName::Danger.into()),
weight: Some(FontWeight::Bold),
..Default::default()
},

View File

@ -2,6 +2,7 @@ use std::rc::Rc;
use wgui::{
assets::AssetPath,
color::{WguiColor, WguiColorName},
components::{
self,
button::{ButtonClickCallback, ComponentButton},
@ -110,11 +111,13 @@ struct MultiSelectorParams<'a> {
}
fn mount_multi_selector(params: MultiSelectorParams) -> anyhow::Result<()> {
let accent_color = params.ess.layout.state.theme.accent_color;
for cell in params.cells {
let highlighted = cell.key == params.def_cell;
let color = if highlighted { Some(accent_color) } else { None };
let color = if highlighted {
Some(WguiColor::from(WguiColorName::Primary))
} else {
None
};
// button
let (_, button) = components::button::construct(
@ -664,11 +667,11 @@ impl View {
let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| {
let color = if num == btn_num {
com.state.theme.accent_color
WguiColorName::Primary
} else {
com.state.theme.button_color
WguiColorName::BackgroundVariant
};
btn.set_color(&mut com, color);
btn.set_color(&mut com, color.into());
};
perform(0, &self.btn_sinks);

View File

@ -173,9 +173,9 @@ impl View {
let (widget_button, button) = components::button::construct(
params.ess,
components::button::Params {
color: Some(drawing::Color::new(1.0, 1.0, 1.0, 0.0)),
border_color: Some(BORDER_COLOR_DEFAULT),
hover_border_color: Some(BORDER_COLOR_HOVERED),
color: Some(drawing::Color::new(1.0, 1.0, 1.0, 0.0).into()),
border_color: Some(BORDER_COLOR_DEFAULT.into()),
hover_border_color: Some(BORDER_COLOR_HOVERED.into()),
round: WLength::Units(12.0),
border: 2.0,
tooltip: Some(TooltipInfo {
@ -214,8 +214,8 @@ impl View {
let rect_gradient = |color: drawing::Color, color2: drawing::Color| {
rectangle::WidgetRectangle::create(rectangle::WidgetRectangleParams {
color,
color2,
color: color.into(),
color2: color2.into(),
round: WLength::Units(12.0),
gradient: GradientMode::Vertical,
..Default::default()

View File

@ -11,8 +11,8 @@ use crate::{
use anyhow::Context;
use wgui::{
assets::AssetPath,
color::WguiColorName,
components::button::ComponentButton,
drawing::Color,
globals::WguiGlobals,
i18n::Translation,
layout::{Layout, WidgetID},
@ -86,7 +86,7 @@ fn mount_resolution_button(
let button = data.fetch_component_as::<ComponentButton>("button")?;
if already_downloaded {
button.set_color(&mut layout.common(), Color::new(0.0, 0.4, 0.0, 1.0)); // green
button.set_color(&mut layout.common(), WguiColorName::Tertiary.into()); // green
}
tasks.handle_button(&button, Task::ResolutionClicked(res));
Ok(())

View File

@ -116,9 +116,9 @@ impl TestbedGeneric {
color = color.mult_rgb(mult_f32);
let mut rect = par.get_widget_as::<WidgetRectangle>().unwrap();
rect.params.color = color;
rect.params.color = color.into();
})),
dev_mode: false,
..Default::default()
};
let (layout, parser_state) = wgui::parser::new_layout_from_assets(

6
wayvr/run Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
cargo run --profile=plain -- --show --replace

View File

@ -8,7 +8,7 @@ use wgui::{
event::{self, EventCallback},
i18n::Translation,
layout::Layout,
parser::{CustomAttribsInfoOwned, ParserState, parse_color_hex},
parser::{CustomAttribsInfoOwned, ParserState},
widget::{EventResult, label::WidgetLabel},
};
@ -46,15 +46,15 @@ pub(super) fn setup_custom_label<S: 'static>(
let state = BatteryLabelState {
low_color: attribs
.get_value("_low_color")
.and_then(parse_color_hex)
.and_then(drawing::Color::from_hex)
.unwrap_or(BAT_LOW),
normal_color: attribs
.get_value("_normal_color")
.and_then(parse_color_hex)
.and_then(drawing::Color::from_hex)
.unwrap_or(BAT_NORMAL),
charging_color: attribs
.get_value("_charging_color")
.and_then(parse_color_hex)
.and_then(drawing::Color::from_hex)
.unwrap_or(BAT_CHARGING),
low_threshold: attribs
.get_value("_low_threshold")

View File

@ -21,6 +21,7 @@ use wgui::{
button::ComponentButton, checkbox::ComponentCheckbox, radio_group::ComponentRadioGroup,
slider::ComponentSlider,
},
drawing,
event::{
DeviceBitmask, Event as WguiEvent, EventCallback, EventListenerID, EventListenerKind,
InternalStateChangeEvent, MouseButtonEvent, MouseButtonIndex, MouseLeaveEvent,
@ -29,9 +30,7 @@ use wgui::{
gfx::cmd::WGfxClearMode,
i18n::Translation,
layout::{Layout, LayoutParams, LayoutUpdateParams, WidgetID},
parser::{
self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState, parse_color_hex,
},
parser::{self, CustomAttribsInfoOwned, Fetchable, ParseDocumentExtra, ParserState},
renderer_vk::{context::Context as WguiContext, text::custom_glyph::CustomGlyphData},
widget::{
EventResult, image::WidgetImage, label::WidgetLabel, rectangle::WidgetRectangle,
@ -532,7 +531,7 @@ pub fn apply_custom_command<T>(
}
}
ModifyPanelCommand::SetColor(color) => {
let color = parse_color_hex(color)
let color = drawing::Color::from_hex(color)
.context("Invalid color format, must be a html hex color!")?;
if let Ok(pair) = panel.parser_state.fetch_widget(com.state, element) {

View File

@ -9,7 +9,7 @@ use std::sync::Arc;
use wgui::log::LogErr;
use wgui::theme::WguiTheme;
use wgui::{
drawing, font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals, parser::parse_color_hex,
drawing, font_config::WguiFontConfig, gfx::WGfx, globals::WguiGlobals,
renderer_vk::context::SharedContext as WSharedContext,
};
#[cfg(feature = "pipewire")]
@ -150,7 +150,7 @@ impl AppState {
{
#[allow(clippy::ref_option)]
fn apply_color(default: &mut drawing::Color, value: &Option<String>) {
if let Some(parsed) = value.as_ref().and_then(|c| parse_color_hex(c)) {
if let Some(parsed) = value.as_ref().and_then(|c| drawing::Color::from_hex(c)) {
*default = parsed;
}
}

View File

@ -17,6 +17,7 @@ rust-embed.workspace = true
serde_json.workspace = true
slotmap.workspace = true
smallvec.workspace = true
strum.workspace = true
vulkano.workspace = true
vulkano-shaders.workspace = true
@ -35,6 +36,7 @@ image = {
]
}
lru = "0.18.0"
num_enum = "0.7.6" # for converting integers into Option enums (search for TryFromPrimitive in the codebase)
ouroboros = "0.18.5"
parking_lot = "0.12.5"
resvg = { version = "0.47.0", default-features = false }

View File

@ -5,11 +5,11 @@
</template>
<template name="Separator">
<rectangle width="100%" height="2" color="~color_accent" />
<rectangle width="100%" height="2" color="primary" />
</template>
<elements>
<rectangle consume_mouse_events="1" color="#000000fa" round="8" border="2" border_color="~color_accent" gap="4" padding="8" id="buttons" flex_direction="column">
<rectangle consume_mouse_events="1" color="#000000fa" round="8" border="2" border_color="primary" gap="4" padding="8" id="buttons" flex_direction="column">
</rectangle>
</elements>

226
wgui/src/color.rs Normal file
View File

@ -0,0 +1,226 @@
use crate::drawing;
use num_enum::TryFromPrimitive;
use strum::EnumCount;
// Primary: button color
// OnPrimary: text color placed on the Primary-colored button
#[derive(Debug, Copy, Clone, TryFromPrimitive, EnumCount)]
#[repr(u8)]
pub enum WguiColorName {
Primary,
OnPrimary,
Secondary,
OnSecondary,
Tertiary,
OnTertiary,
Danger,
OnDanger,
Background,
OnBackground,
Outline,
BackgroundVariant,
OnBackgroundVariant,
}
pub struct WguiColorPalette {
colors: Vec<(drawing::Color, &'static str)>,
}
#[derive(Clone, Copy, Debug)]
pub struct WguiNamedColor {
name: WguiColorName,
rgb_multiplier: f32,
rgb_addition: f32,
alpha: f32,
}
#[derive(Clone, Copy, Debug)]
pub enum WguiColor {
Raw(drawing::Color),
Named(WguiNamedColor),
}
impl WguiColorPalette {
pub fn new() -> WguiColorPalette {
let mut colors = Vec::<(drawing::Color, &'static str)>::new();
colors.resize(WguiColorName::COUNT, Default::default());
// default theme
colors[WguiColorName::Primary as usize] = (drawing::Color::from_hex("#21adff").unwrap(), "primary");
colors[WguiColorName::OnPrimary as usize] = (drawing::Color::from_hex("#eaf7ff").unwrap(), "on_primary");
colors[WguiColorName::Secondary as usize] = (drawing::Color::from_hex("#424b56").unwrap(), "secondary");
colors[WguiColorName::OnSecondary as usize] = (drawing::Color::from_hex("#d2e6ff").unwrap(), "on_secondary");
colors[WguiColorName::Tertiary as usize] = (drawing::Color::from_hex("#1aedcd").unwrap(), "tertiary");
colors[WguiColorName::OnTertiary as usize] = (drawing::Color::from_hex("#d1fff8").unwrap(), "on_tertiary");
colors[WguiColorName::Danger as usize] = (drawing::Color::from_hex("#ea0c76").unwrap(), "danger");
colors[WguiColorName::OnDanger as usize] = (drawing::Color::from_hex("#ffebf5").unwrap(), "on_danger");
colors[WguiColorName::Background as usize] = (drawing::Color::from_hex("#00121a").unwrap(), "background");
colors[WguiColorName::OnBackground as usize] = (drawing::Color::from_hex("#e4f5f6").unwrap(), "on_background");
colors[WguiColorName::Outline as usize] = (drawing::Color::from_hex("#204353").unwrap(), "outline");
colors[WguiColorName::BackgroundVariant as usize] =
(drawing::Color::from_hex("#031e2a").unwrap(), "background_variant");
colors[WguiColorName::OnBackgroundVariant as usize] =
(drawing::Color::from_hex("#e2fdff").unwrap(), "on_background_variant");
WguiColorPalette { colors }
}
pub fn find(&self, in_name: &str) -> Option<WguiColor> {
for (idx, (_, name)) in self.colors.iter().enumerate() {
if in_name == *name {
return Some(
WguiColorName::try_from(idx as u8)
.unwrap() /* this never fails */
.into(),
);
}
}
None
}
}
impl Default for WguiColorPalette {
fn default() -> Self {
Self::new()
}
}
impl WguiColor {
pub fn resolve(&self, palette: &WguiColorPalette) -> drawing::Color {
match &self {
WguiColor::Raw(color) => *color,
WguiColor::Named(color) => color.resolve(palette),
}
}
#[must_use]
pub const fn mult_rgb(&self, mult: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(color.mult_rgb(mult)),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier * mult,
rgb_addition: color.rgb_addition,
alpha: color.alpha,
}),
}
}
#[must_use]
pub const fn add_rgb(&self, addition: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(color.add_rgb(addition)),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier,
rgb_addition: color.rgb_addition + addition,
alpha: color.alpha,
}),
}
}
#[must_use]
pub const fn add_alpha(&self, alpha: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(drawing::Color {
r: color.r,
g: color.g,
b: color.b,
a: color.a + alpha,
}),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier,
rgb_addition: color.rgb_addition,
alpha: color.alpha + alpha,
}),
}
}
#[must_use]
pub const fn with_alpha(&self, alpha: f32) -> WguiColor {
match self {
WguiColor::Raw(color) => WguiColor::Raw(color.with_alpha(alpha)),
WguiColor::Named(color) => WguiColor::Named(WguiNamedColor {
name: color.name,
rgb_multiplier: color.rgb_multiplier,
rgb_addition: color.rgb_addition,
alpha,
}),
}
}
// returns named colors if val is 0 or 1, raw otherwise
#[must_use]
pub fn lerp(&self, palette: &WguiColorPalette, other: &WguiColor, val: f32) -> WguiColor {
if val <= 0.0 {
*self
} else if val >= 1.0 {
*other
} else {
let c1 = self.resolve(palette);
let c2 = other.resolve(palette);
c1.lerp(&c2, val).into()
}
}
}
impl WguiColorName {
pub const fn to_wgui_color(&self) -> WguiColor {
WguiColor::Named(WguiNamedColor {
name: *self,
alpha: 1.0,
rgb_multiplier: 1.0,
rgb_addition: 0.0,
})
}
}
impl From<WguiColorName> for WguiColor {
fn from(name: WguiColorName) -> Self {
name.to_wgui_color()
}
}
impl From<drawing::Color> for WguiColor {
fn from(color: drawing::Color) -> Self {
WguiColor::Raw(color)
}
}
impl Default for WguiColor {
fn default() -> Self {
Self::Raw(Default::default())
}
}
impl WguiNamedColor {
pub fn resolve(&self, palette: &WguiColorPalette) -> drawing::Color {
let idx = self.name as usize;
if idx >= palette.colors.len() {
// unlikely
debug_assert!(false);
return drawing::Color::new(1.0, 0.0, 1.0, 1.0); // Magenta
}
let (mut color, _) = palette.colors[idx];
if self.alpha != 1.0 {
color.a *= self.alpha;
}
if self.rgb_multiplier != 1.0 {
color.r *= self.rgb_multiplier;
color.g *= self.rgb_multiplier;
color.b *= self.rgb_multiplier;
}
if self.rgb_addition != 0.0 {
color.r += self.rgb_addition;
color.g += self.rgb_addition;
color.b += self.rgb_addition;
}
color
}
}

View File

@ -134,10 +134,10 @@ pub fn construct(
root.id,
WidgetRectangle::create(WidgetRectangleParams {
border: 2.0,
border_color: drawing::Color::new(1.0, 1.0, 1.0, 0.5),
border_color: drawing::Color::new(1.0, 1.0, 1.0, 0.5).into(),
round: WLength::Units(3.0),
gradient: GradientMode::Vertical,
color: drawing::Color::new(0.0, 0.0, 0.0, 0.6),
color: drawing::Color::new(0.0, 0.0, 0.0, 0.6).into(),
..Default::default()
}),
taffy::Style {

View File

@ -1,11 +1,12 @@
use crate::{
animation::{Animation, AnimationEasing},
assets::AssetPath,
color::{WguiColor, WguiColorName},
components::{
self, Component, ComponentBase, ComponentTrait, RefreshData,
tooltip::{ComponentTooltip, TooltipTrait},
},
drawing::{self, Boundary, Color},
drawing::{self, Boundary},
event::{CallbackDataCommon, EventListenerCollection, EventListenerID, EventListenerKind},
i18n::Translation,
layout::{WidgetID, WidgetPair},
@ -33,11 +34,11 @@ use taffy::{AlignItems, JustifyContent, prelude::length};
pub struct Params<'a> {
pub text: Option<Translation>, // if unset, label will not be populated
pub sprite_src: Option<AssetPath<'a>>,
pub color: Option<drawing::Color>,
pub color: Option<WguiColor>,
pub border: f32,
pub border_color: Option<drawing::Color>,
pub hover_border_color: Option<drawing::Color>,
pub hover_color: Option<drawing::Color>,
pub border_color: Option<WguiColor>,
pub hover_border_color: Option<WguiColor>,
pub hover_color: Option<WguiColor>,
pub round: WLength,
pub style: taffy::Style,
pub text_style: TextStyle,
@ -77,10 +78,10 @@ pub struct ButtonClickEvent {
pub type ButtonClickCallback = Rc<dyn Fn(&mut CallbackDataCommon, ButtonClickEvent) -> anyhow::Result<()>>;
pub struct Colors {
pub color: drawing::Color,
pub border_color: drawing::Color,
pub hover_color: drawing::Color,
pub hover_border_color: drawing::Color,
pub color: WguiColor,
pub border_color: WguiColor,
pub hover_color: WguiColor,
pub hover_border_color: WguiColor,
}
struct State {
@ -136,12 +137,8 @@ impl ComponentTrait for ComponentButton {
}
}
fn get_color2(color: &drawing::Color, gradient_intensity: f32) -> drawing::Color {
color.lerp(&Color::new(0.0, 0.0, 0.0, color.a), gradient_intensity)
}
fn get_hover_color(color: &drawing::Color) -> drawing::Color {
Color::new(color.r + 0.25, color.g + 0.25, color.g + 0.25, color.a + 0.15)
fn get_color2(color: &WguiColor, gradient_intensity: f32) -> WguiColor {
color.mult_rgb(1.0 - gradient_intensity)
}
impl ComponentButton {
@ -161,18 +158,17 @@ impl ComponentButton {
label.set_text(common, text);
}
pub fn set_color(&self, common: &mut CallbackDataCommon, color: Color) {
pub fn set_color(&self, common: &mut CallbackDataCommon, color: WguiColor) {
let gradient_intensity = common.state.theme.gradient_intensity;
let Some(mut rect) = common.state.widgets.get_as::<WidgetRectangle>(self.data.id_rect) else {
return;
};
rect.params.color = color;
rect.params.color2 = get_color2(&color, gradient_intensity);
let mut state = self.state.borrow_mut();
state.colors.color = color;
state.colors.hover_color = get_hover_color(&color);
rect.params.color = color;
rect.params.color2 = get_color2(&color, gradient_intensity);
}
pub fn get_time_since_last_pressed(&self) -> Duration {
@ -220,10 +216,15 @@ impl ComponentButton {
let state = state.borrow();
let colors = &state.colors;
let bgcolor = colors.color.lerp(&colors.hover_color, mult * 0.5);
rect.params.color = bgcolor;
rect.params.color2 = get_color2(&bgcolor, gradient_intensity);
rect.params.border_color = colors.border_color.lerp(&colors.hover_border_color, mult);
{
let globals = common.globals();
let palette = &globals.palette;
let bgcolor = colors.color.lerp(palette, &colors.hover_color, mult * 0.5);
rect.params.color = bgcolor;
rect.params.color2 = get_color2(&bgcolor, gradient_intensity);
rect.params.border_color = colors.border_color.lerp(palette, &colors.hover_border_color, mult);
}
common.alterables.mark_redraw();
}),
);
@ -245,13 +246,18 @@ fn anim_hover(
) {
let mult = pos * if pressed { 1.5 } else { 1.0 };
let globals = common.globals();
let (init_border_color, init_color) = if sticky_down {
(colors.hover_border_color, colors.color.lerp(&colors.hover_color, 0.5))
(
colors.hover_border_color,
colors.color.lerp(&globals.palette, &colors.hover_color, 0.5),
)
} else {
(colors.border_color, colors.color)
};
let bgcolor = init_color.lerp(&colors.hover_color, mult);
let bgcolor = init_color.lerp(&globals.palette, &colors.hover_color, mult);
let gradient_intensity = common.state.theme.gradient_intensity;
@ -263,7 +269,7 @@ fn anim_hover(
rect.params.color = bgcolor;
rect.params.color2 = get_color2(&bgcolor, gradient_intensity);
rect.params.border_color = init_border_color.lerp(&colors.hover_border_color, mult);
rect.params.border_color = init_border_color.lerp(&globals.palette, &colors.hover_border_color, mult);
}
fn anim_hover_create(state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bool, anim_mult: f32) -> Animation {
@ -446,25 +452,26 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
style.overflow.x = taffy::Overflow::Hidden;
style.overflow.y = taffy::Overflow::Hidden;
let globals = ess.layout.state.globals.get();
// update colors to default ones if they are not specified
let color = params.color.unwrap_or(theme.button_color);
let color = params.color.unwrap_or_else(|| WguiColorName::BackgroundVariant.into());
let border_color = params
.border_color
.unwrap_or_else(|| Color::new(color.r, color.g, color.b, color.a + 0.25));
.unwrap_or_else(|| WguiColor::from(WguiColorName::Outline));
let hover_color = params.hover_color.unwrap_or_else(|| get_hover_color(&color));
let hover_color = params
.hover_color
.unwrap_or_else(|| color.add_rgb(0.25).add_alpha(0.15));
let hover_border_color = params
.hover_border_color
.unwrap_or_else(|| Color::new(color.r + 0.5, color.g + 0.5, color.g + 0.5, color.a + 0.5));
.unwrap_or_else(|| border_color.add_rgb(0.5).add_alpha(0.5));
let gradient_intensity = theme.gradient_intensity;
let light_text = {
let mult = if theme.dark_mode { color.a } else { 1.0 - color.a };
(color.r + color.g + color.b) * mult < 1.5
};
drop(globals);
let (root, _) = ess.layout.add_child(
ess.parent,
@ -515,11 +522,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
content,
style: TextStyle {
weight: Some(FontWeight::Bold),
color: Some(if light_text {
Color::new(1.0, 1.0, 1.0, 1.0)
} else {
Color::new(0.0, 0.0, 0.0, 1.0)
}),
..params.text_style
},
},

View File

@ -9,12 +9,13 @@ use taffy::{
use crate::{
animation::{Animation, AnimationEasing},
color::{WguiColor, WguiColorName},
components::{
Component, ComponentBase, ComponentTrait, RefreshData,
radio_group::ComponentRadioGroup,
tooltip::{self, ComponentTooltip, TooltipTrait},
},
drawing::Color,
drawing,
event::{CallbackDataCommon, EventListenerCollection, EventListenerID, EventListenerKind},
i18n::Translation,
layout::{self, WidgetID, WidgetPair},
@ -31,7 +32,7 @@ use crate::{
pub struct Params {
pub text: Translation,
pub style: taffy::Style,
pub color_checked: Option<Color>,
pub color_checked: Option<WguiColor>,
pub box_size: f32,
pub checked: bool,
pub radio_group: Option<Rc<ComponentRadioGroup>>,
@ -87,7 +88,7 @@ struct Data {
value: Option<Rc<str>>, // arbitrary value assigned to the element
radio_group: Option<Weak<ComponentRadioGroup>>,
color_checked: Color,
color_checked: WguiColor,
}
pub struct ComponentCheckbox {
@ -96,7 +97,7 @@ pub struct ComponentCheckbox {
state: Rc<RefCell<State>>,
}
const COLOR_UNCHECKED: Color = Color::new(0.0, 0.0, 0.0, 0.0);
const COLOR_UNCHECKED: drawing::Color = drawing::Color::new(0.0, 0.0, 0.0, 0.0);
impl ComponentTrait for ComponentCheckbox {
fn base(&self) -> &ComponentBase {
@ -114,7 +115,11 @@ impl ComponentTrait for ComponentCheckbox {
fn set_box_checked(widgets: &layout::WidgetMap, data: &Data, checked: bool) {
widgets.call(data.id_inner_box, |rect: &mut WidgetRectangle| {
rect.params.color = if checked { data.color_checked } else { COLOR_UNCHECKED }
rect.params.color = if checked {
data.color_checked
} else {
COLOR_UNCHECKED.into()
}
});
}
@ -159,13 +164,13 @@ impl ComponentCheckbox {
}
fn anim_hover(rect: &mut WidgetRectangle, pos: f32, pressed: bool) {
let brightness = pos * if pressed { 0.6 } else { 0.4 };
let mut brightness = pos * if pressed { 0.6 } else { 0.4 };
rect.params.border = 2.0;
rect.params.color.a = brightness;
rect.params.border_color.a = rect.params.color.a;
rect.params.color = rect.params.color.with_alpha(brightness);
if pressed {
rect.params.border_color.a += 0.4;
brightness += 0.4;
}
rect.params.border_color = rect.params.border_color.with_alpha(brightness);
}
fn anim_hover_in(state: Rc<RefCell<State>>, widget_id: WidgetID, anim_mult: f32) -> Animation {
@ -329,7 +334,6 @@ fn register_event_mouse_release(
pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Result<(WidgetPair, Rc<ComponentCheckbox>)> {
let mut style = params.style;
let theme = &ess.layout.state.theme;
// force-override style
style.flex_wrap = taffy::FlexWrap::NoWrap;
@ -358,13 +362,12 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
(WLength::Units(5.0), WLength::Units(8.0))
};
let color_checked = params.color_checked.unwrap_or(theme.accent_color);
let color_checked = params.color_checked.unwrap_or(WguiColorName::Primary.into());
let (root, _) = ess.layout.add_child(
ess.parent,
WidgetRectangle::create(WidgetRectangleParams {
color: Color::new(1.0, 1.0, 1.0, 0.0),
border_color: Color::new(1.0, 1.0, 1.0, 0.0),
color: WguiColor::from(WguiColorName::OnPrimary).with_alpha(0.0),
round: round_5,
..Default::default()
}),
@ -382,9 +385,9 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
id_container,
WidgetRectangle::create(WidgetRectangleParams {
border: 2.0,
border_color: Color::new(1.0, 1.0, 1.0, 1.0),
border_color: WguiColorName::OnPrimary.into(),
round: round_8,
color: Color::new(1.0, 1.0, 1.0, 0.0),
color: WguiColor::from(WguiColorName::OnPrimary).with_alpha(0.0),
..Default::default()
}),
taffy::Style {
@ -400,7 +403,11 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
outer_box.id,
WidgetRectangle::create(WidgetRectangleParams {
round: round_5,
color: if params.checked { color_checked } else { COLOR_UNCHECKED },
color: if params.checked {
color_checked
} else {
COLOR_UNCHECKED.into()
},
..Default::default()
}),
taffy::Style {

View File

@ -96,7 +96,10 @@ impl ComponentTrait for ComponentColorSelector {
Translation::from_raw_text_string(state.color.to_hex_rgb()),
);
self.data.button.set_color(&mut data.layout.common(), state.color);
self
.data
.button
.set_color(&mut data.layout.common(), state.color.into());
}
}
@ -210,7 +213,7 @@ impl ComponentColorSelector {
.widgets
.get_as::<WidgetRectangle>(popup_state.id_rect_color)
{
rect.set_color(common, new_color);
rect.set_color(common, new_color.into());
}
set_color_internal(&mut state, common, new_color);
})
@ -240,10 +243,10 @@ pub fn construct(
let (widget_button, button) = button::construct(
ess,
button::Params {
color: Some(params.color),
color: Some(params.color.into()),
round: WLength::Percent(1.0),
border: 2.0,
border_color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)),
border_color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0).into()),
style,
..Default::default()
},

View File

@ -8,8 +8,9 @@ use taffy::prelude::{auto, length, percent};
use crate::{
animation::{Animation, AnimationEasing},
color::{WguiColor, WguiColorName},
components::{Component, ComponentBase, ComponentTrait, FocusChangeData, RefreshData},
drawing::{self, Color},
drawing::Color,
event::{self, CallbackDataCommon, CallbackMetadata, EventListenerCollection, EventListenerKind, StyleSetRequest},
i18n::Translation,
layout::{WidgetID, WidgetPair},
@ -55,7 +56,7 @@ pub struct ComponentEditBox {
fn anim_bottom_rect(
common: &mut CallbackDataCommon,
accent_color: drawing::Color,
accent_color: WguiColor,
id_rect: WidgetID,
anim_mult: f32,
focused: bool,
@ -69,10 +70,12 @@ fn anim_bottom_rect(
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
let pos_bidir = if focused { data.pos } else { 1.0 - data.pos };
rect.set_color(
common,
accent_color.lerp(&drawing::Color::new(1.0, 1.0, 1.0, 1.0), pos_bidir),
let color_lerped = accent_color.lerp(
&common.globals().palette,
&WguiColorName::OnBackgroundVariant.into(),
pos_bidir,
);
rect.set_color(common, color_lerped);
common.alterables.set_style(
data.widget_id,
@ -100,9 +103,9 @@ fn anim_bottom_rect(
fn refresh_all(common: &mut CallbackDataCommon, data: &Data, state: &mut State) -> Option<()> {
let theme = &common.state.theme;
let editbox_color = theme.editbox_color;
let editbox_color = WguiColor::from(WguiColorName::BackgroundVariant);
let accent_color = WguiColor::from(WguiColorName::Primary);
let anim_mult = theme.animation_mult;
let accent_color = theme.accent_color;
let (rect_color, border_color) = if state.focused {
(editbox_color.add_rgb(0.15), editbox_color.add_rgb(0.15 + 0.25))
@ -271,7 +274,7 @@ pub fn construct(
ess: &mut ConstructEssentials,
mut params: Params,
) -> anyhow::Result<(WidgetPair, Rc<ComponentEditBox>)> {
let text_color = ess.layout.state.theme.text_color;
let text_color = WguiColor::from(WguiColorName::OnBackgroundVariant);
if params.style.size.width.is_auto() {
params.style.size.width = length(128.0);

View File

@ -5,11 +5,11 @@ use taffy::prelude::{length, percent};
use crate::{
animation::{Animation, AnimationEasing},
color::{WguiColor, WguiColorName, WguiColorPalette},
components::{
Component, ComponentBase, ComponentTrait, RefreshData,
tooltip::{self, ComponentTooltip, TooltipTrait},
},
drawing::{self},
event::{
self, CallbackDataCommon, CallbackMetadata, DeviceBitmask, EventAlterables, EventListenerCollection,
EventListenerKind, StyleSetRequest,
@ -346,12 +346,12 @@ impl State {
}
}
const BODY_COLOR: drawing::Color = drawing::Color::new(0.6, 0.65, 0.7, 0.1);
const BODY_BORDER_COLOR: drawing::Color = drawing::Color::new(0.4, 0.45, 0.5, 0.6);
const HANDLE_BORDER_COLOR: drawing::Color = drawing::Color::new(0.85, 0.85, 0.85, 1.0);
const HANDLE_BORDER_COLOR_HOVERED: drawing::Color = drawing::Color::new(0.0, 0.0, 0.0, 1.0);
const HANDLE_COLOR: drawing::Color = drawing::Color::new(1.0, 1.0, 1.0, 1.0);
const HANDLE_COLOR_HOVERED: drawing::Color = drawing::Color::new(0.9, 0.9, 0.9, 1.0);
const BODY_COLOR: WguiColor = WguiColorName::BackgroundVariant.to_wgui_color();
const BODY_BORDER_COLOR: WguiColor = WguiColorName::Outline.to_wgui_color();
const HANDLE_COLOR: WguiColorName = WguiColorName::Secondary;
const HANDLE_COLOR_HOVERED: WguiColor = WguiColorName::Secondary.to_wgui_color().add_rgb(0.1);
const HANDLE_BORDER_COLOR: WguiColor = WguiColorName::Primary.to_wgui_color();
const HANDLE_BORDER_COLOR_HOVERED: WguiColor = WguiColorName::Primary.to_wgui_color().mult_rgb(1.25);
const SLIDER_HOVER_SCALE: f32 = 0.25;
fn get_anim_transform(pos: f32, widget_size: Vec2) -> Mat4 {
@ -361,9 +361,9 @@ fn get_anim_transform(pos: f32, widget_size: Vec2) -> Mat4 {
)
}
fn anim_rect(rect: &mut WidgetRectangle, pos: f32) {
rect.params.color = drawing::Color::lerp(&HANDLE_COLOR, &HANDLE_COLOR_HOVERED, pos);
rect.params.border_color = drawing::Color::lerp(&HANDLE_BORDER_COLOR, &HANDLE_BORDER_COLOR_HOVERED, pos);
fn anim_rect(rect: &mut WidgetRectangle, palette: &WguiColorPalette, pos: f32) {
rect.params.color = WguiColor::lerp(&HANDLE_COLOR.into(), palette, &HANDLE_COLOR_HOVERED, pos);
rect.params.border_color = WguiColor::lerp(&HANDLE_BORDER_COLOR, palette, &HANDLE_BORDER_COLOR_HOVERED, pos);
}
fn on_enter_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID, anim_mult: f32) {
@ -374,7 +374,7 @@ fn on_enter_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID, an
Box::new(move |common, data| {
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
data.data.transform = get_anim_transform(data.pos, data.widget_boundary.size);
anim_rect(rect, data.pos);
anim_rect(rect, &common.globals().palette, data.pos);
common.alterables.mark_redraw();
}),
));
@ -388,7 +388,7 @@ fn on_leave_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID, an
Box::new(move |common, data| {
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap();
data.data.transform = get_anim_transform(1.0 - data.pos, data.widget_boundary.size);
anim_rect(rect, 1.0 - data.pos);
anim_rect(rect, &common.globals().palette, 1.0 - data.pos);
common.alterables.mark_redraw();
}),
));
@ -606,7 +606,7 @@ fn mount_slider_handle(
let (slider_handle_rect, _) = ess.layout.add_child(
slider_handle.id,
WidgetRectangle::create(WidgetRectangleParams {
color: HANDLE_COLOR,
color: HANDLE_COLOR.into(),
border_color: HANDLE_BORDER_COLOR,
border: 2.0,
round: WLength::Percent(1.0),
@ -628,7 +628,7 @@ fn mount_slider_handle(
WidgetLabelParams {
content: Translation::default(),
style: TextStyle {
color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)), // always black
color: Some(WguiColorName::OnPrimary.into()),
weight: Some(FontWeight::Bold),
align: Some(HorizontalAlign::Center),
..Default::default()

View File

@ -1,5 +1,6 @@
use crate::{
assets::AssetPath,
color::WguiColorName,
components::{
Component, ComponentBase, ComponentTrait, RefreshData,
button::{self, ComponentButton},
@ -66,16 +67,11 @@ impl ComponentTrait for ComponentTabs {
impl State {
fn select_entry(&mut self, common: &mut CallbackDataCommon, name: &Rc<str>) {
let (color_accent, color_button) = {
let theme = &common.state.theme;
(theme.accent_color, theme.button_color)
};
for entry in &self.mounted_entries {
if *entry.name == **name {
entry.button.set_color(common, color_accent);
entry.button.set_color(common, WguiColorName::Primary.into());
} else {
entry.button.set_color(common, color_button);
entry.button.set_color(common, WguiColorName::BackgroundVariant.into());
}
}
self.selected_entry_name = name.clone();

View File

@ -4,8 +4,8 @@ use taffy::prelude::length;
use crate::{
animation::{Animation, AnimationEasing},
color::{WguiColor, WguiColorName},
components::{self, Component, ComponentBase, ComponentTrait, RefreshData},
drawing::Color,
event::CallbackDataCommon,
i18n::Translation,
layout::{self, LayoutTask, LayoutTasks, WidgetID, WidgetPair},
@ -153,8 +153,8 @@ impl Drop for ComponentTooltip {
}
}
pub const TOOLTIP_COLOR: Color = Color::new(0.02, 0.02, 0.02, 0.95);
pub const TOOLTIP_BORDER_COLOR: Color = Color::new(0.4, 0.4, 0.4, 1.0);
pub const TOOLTIP_COLOR: WguiColorName = WguiColorName::BackgroundVariant;
pub const TOOLTIP_BORDER_COLOR: WguiColorName = WguiColorName::Outline;
pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Result<(WidgetPair, Rc<ComponentTooltip>)> {
let absolute_boundary = {
@ -233,8 +233,8 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
let (rect, _) = ess.layout.add_child(
div.id,
WidgetRectangle::create(WidgetRectangleParams {
color: TOOLTIP_COLOR,
border_color: TOOLTIP_BORDER_COLOR,
color: TOOLTIP_COLOR.into(),
border_color: TOOLTIP_BORDER_COLOR.into(),
border: 2.0,
round: WLength::Units(24.0),
..Default::default()
@ -300,8 +300,8 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
Box::new(move |common, data| {
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap(); /* safe */
let alpha = data.pos;
rect.params.color.a = alpha;
rect.params.border_color.a = alpha;
rect.params.color = rect.params.color.with_alpha(alpha);
rect.params.border_color = rect.params.border_color.with_alpha(alpha);
let position_shift = state.borrow().position_shift;
@ -313,7 +313,11 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
));
if let Some(mut label) = common.state.widgets.get_as::<WidgetLabel>(label.id) {
label.set_color(common, Color::new(1.0, 1.0, 1.0, alpha), true);
label.set_color(
common,
WguiColor::from(WguiColorName::OnBackground).with_alpha(alpha),
true,
);
}
common.alterables.mark_redraw();

View File

@ -4,8 +4,8 @@ use taffy::prelude::percent;
use crate::{
animation::Animation,
assets::AssetPath,
color::WguiColorName,
components::{Component, ComponentBase, ComponentTrait, RefreshData},
drawing::Color,
event::EventAlterables,
globals::WguiGlobals,
layout::{Layout, WidgetID, WidgetPair},
@ -227,7 +227,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
let (root, _) = ess.layout.add_child(
ess.parent,
WidgetRectangle::create(WidgetRectangleParams {
color: Color::new(0.1, 0.1, 0.1, 1.0),
color: WguiColorName::Background.into(),
..Default::default()
}),
style,

View File

@ -119,7 +119,7 @@ impl Color {
}
#[must_use]
pub fn add_rgb(&self, n: f32) -> Self {
pub const fn add_rgb(&self, n: f32) -> Self {
Self {
r: self.r + n,
g: self.g + n,
@ -129,7 +129,7 @@ impl Color {
}
#[must_use]
pub fn mult_rgb(&self, n: f32) -> Self {
pub const fn mult_rgb(&self, n: f32) -> Self {
Self {
r: self.r * n,
g: self.g * n,
@ -139,7 +139,7 @@ impl Color {
}
#[must_use]
pub fn lerp(&self, other: &Self, n: f32) -> Self {
pub const fn lerp(&self, other: &Self, n: f32) -> Self {
Self {
r: self.r * (1.0 - n) + other.r * n,
g: self.g * (1.0 - n) + other.g * n,
@ -191,6 +191,46 @@ impl Color {
pub const fn as_arr(&self) -> [f32; 4] {
[self.r, self.b, self.g, self.a]
}
// expects strings like "#424242" or "#424242FF"
pub fn from_hex(html_hex: &str) -> Option<drawing::Color> {
let Some(ch) = html_hex.chars().next() else {
return None;
};
if ch != '#' {
return None;
}
if html_hex.len() == 7 {
if let (Ok(r), Ok(g), Ok(b)) = (
u8::from_str_radix(&html_hex[1..3], 16),
u8::from_str_radix(&html_hex[3..5], 16),
u8::from_str_radix(&html_hex[5..7], 16),
) {
return Some(drawing::Color::new(
f32::from(r) / 255.,
f32::from(g) / 255.,
f32::from(b) / 255.,
1.,
));
}
} else if html_hex.len() == 9
&& let (Ok(r), Ok(g), Ok(b), Ok(a)) = (
u8::from_str_radix(&html_hex[1..3], 16),
u8::from_str_radix(&html_hex[3..5], 16),
u8::from_str_radix(&html_hex[5..7], 16),
u8::from_str_radix(&html_hex[7..9], 16),
) {
return Some(drawing::Color::new(
f32::from(r) / 255.,
f32::from(g) / 255.,
f32::from(b) / 255.,
f32::from(a) / 255.,
));
}
None
}
}
impl Default for Color {

View File

@ -12,6 +12,7 @@ use regex::Regex;
use crate::{
assets::{AssetPath, AssetProvider, LangProvider},
assets_internal,
color::WguiColorPalette,
font_config::{WguiFontConfig, WguiFontSystem},
i18n::I18n,
renderer_vk::text::custom_glyph::CustomGlyphCache,
@ -24,6 +25,7 @@ pub struct Globals {
pub i18n_builtin: I18n,
pub font_system: WguiFontSystem,
pub custom_glyph_cache: CustomGlyphCache,
pub palette: WguiColorPalette,
}
#[derive(Clone)]
@ -46,6 +48,7 @@ impl WguiGlobals {
font_system: WguiFontSystem::new(font_config, i18n_builtin.get_locale()),
i18n_builtin,
custom_glyph_cache: CustomGlyphCache::new(),
palette: Default::default(),
}))))
}

View File

@ -930,7 +930,7 @@ impl Layout {
layout.location.y,
layout.content_size.width,
layout.content_size.height,
state.obj.debug_print()
state.obj.debug_print(&self.state.globals.get())
);
buf.append(&mut line.into_bytes());

View File

@ -26,6 +26,7 @@ pub mod animation;
pub mod any;
pub mod assets;
mod assets_internal;
pub mod color;
pub mod components;
pub mod drawing;
pub mod event;

View File

@ -1,7 +1,7 @@
use crate::{
assets::AssetPath,
color::WguiColor,
components::{Component, button},
drawing::Color,
i18n::Translation,
layout::WidgetID,
parser::{
@ -21,11 +21,11 @@ pub fn parse_component_button<'a>(
attribs: &[AttribPair],
tag_name: &str,
) -> anyhow::Result<WidgetID> {
let mut color: Option<Color> = None;
let mut color: Option<WguiColor> = None;
let mut border = 2.0;
let mut border_color: Option<Color> = None;
let mut hover_color: Option<Color> = None;
let mut hover_border_color: Option<Color> = None;
let mut border_color: Option<WguiColor> = None;
let mut hover_color: Option<WguiColor> = None;
let mut hover_border_color: Option<WguiColor> = None;
let mut round = WLength::Units(4.0);
let mut tooltip = TooltipAttribs::default();
let mut sticky: bool = false;

View File

@ -21,7 +21,6 @@ mod widget_sprite;
use crate::{
assets::{AssetPath, AssetPathOwned, normalize_path},
components::{Component, ComponentWeak},
drawing::{self},
globals::WguiGlobals,
i18n::Translation,
layout::{Layout, LayoutParams, LayoutState, Widget, WidgetID, WidgetMap, WidgetPair},
@ -529,31 +528,6 @@ impl ParserContext<'_> {
}
}
fn populate_theme_variables(&mut self) {
let theme = self.layout.state.theme.clone();
macro_rules! insert_color_vars {
($self:expr, $name:literal, $field:expr, $alpha:expr) => {
$self.insert_var(concat!("color_", $name), &$field.to_hex());
$self.insert_var(
concat!("color_", $name, "_translucent"),
&$field.with_alpha($alpha).to_hex(),
);
$self.insert_var(concat!("color_", $name, "_50"), &$field.mult_rgb(0.50).to_hex());
$self.insert_var(concat!("color_", $name, "_40"), &$field.mult_rgb(0.40).to_hex());
$self.insert_var(concat!("color_", $name, "_30"), &$field.mult_rgb(0.30).to_hex());
$self.insert_var(concat!("color_", $name, "_20"), &$field.mult_rgb(0.20).to_hex());
$self.insert_var(concat!("color_", $name, "_10"), &$field.mult_rgb(0.10).to_hex());
};
}
insert_color_vars!(self, "text", theme.text_color, theme.translucent_alpha);
insert_color_vars!(self, "accent", theme.accent_color, theme.translucent_alpha);
insert_color_vars!(self, "danger", theme.danger_color, theme.translucent_alpha);
insert_color_vars!(self, "faded", theme.faded_color, theme.translucent_alpha);
insert_color_vars!(self, "bg", theme.bg_color, theme.translucent_alpha);
}
fn print_invalid_attrib(&self, tag_name: &str, key: &str, value: &str) {
log::warn!(
"{}: <{tag_name}> value for \"{key}\" is invalid: \"{value}\"",
@ -644,38 +618,6 @@ fn is_percent(value: &str) -> bool {
value.ends_with('%')
}
// Parses a color from a HTML hex string
pub fn parse_color_hex(html_hex: &str) -> Option<drawing::Color> {
if html_hex.len() == 7 {
if let (Ok(r), Ok(g), Ok(b)) = (
u8::from_str_radix(&html_hex[1..3], 16),
u8::from_str_radix(&html_hex[3..5], 16),
u8::from_str_radix(&html_hex[5..7], 16),
) {
return Some(drawing::Color::new(
f32::from(r) / 255.,
f32::from(g) / 255.,
f32::from(b) / 255.,
1.,
));
}
} else if html_hex.len() == 9
&& let (Ok(r), Ok(g), Ok(b), Ok(a)) = (
u8::from_str_radix(&html_hex[1..3], 16),
u8::from_str_radix(&html_hex[3..5], 16),
u8::from_str_radix(&html_hex[5..7], 16),
u8::from_str_radix(&html_hex[7..9], 16),
) {
return Some(drawing::Color::new(
f32::from(r) / 255.,
f32::from(g) / 255.,
f32::from(b) / 255.,
f32::from(a) / 255.,
));
}
None
}
fn get_tag_by_name<'a>(node: &roxmltree::Node<'a, 'a>, name: &str) -> Option<roxmltree::Node<'a, 'a>> {
node.children().find(|&child| child.tag_name().name() == name)
}
@ -864,7 +806,7 @@ fn process_attrib(template_parameters: &TemplateParams, ctx: &ParserContext, key
Some(name) => AttribPair::new(key, name),
None => {
log::warn!("{}: undefined variable \"{value}\"", ctx.doc_params.path.get_str());
AttribPair::new(key, "undefined")
AttribPair::new(key, format!("undefined_{}", value))
}
}
} else {
@ -1298,7 +1240,6 @@ pub fn parse_from_assets(
) -> anyhow::Result<ParserState> {
let parser_data = ParserData::default();
let mut ctx = create_default_context(doc_params, layout, &parser_data);
ctx.populate_theme_variables();
ctx.populate_extra_variables(&doc_params.extra.extra_vars);
let (file, node_layout) = get_doc_from_asset_path(&ctx, doc_params.path)?;

View File

@ -4,8 +4,9 @@ use taffy::{
};
use crate::{
color::WguiColor,
drawing,
parser::{AttribPair, ParserContext, is_percent, parse_color_hex, parse_f32},
parser::{AttribPair, ParserContext, is_percent, parse_f32},
renderer_vk::text::{FontWeight, HorizontalAlign, TextStyle},
widget::util::WLength,
};
@ -31,12 +32,19 @@ pub fn parse_round(
}
}
pub fn parse_color(ctx: &ParserContext<'_>, tag_name: &str, key: &str, value: &str, color: &mut drawing::Color) {
if let Some(res_color) = parse_color_hex(value) {
*color = res_color;
} else {
ctx.print_invalid_attrib(tag_name, key, value);
pub fn parse_color(ctx: &ParserContext<'_>, tag_name: &str, key: &str, value: &str, out_color: &mut WguiColor) -> bool {
if let Some(color) = drawing::Color::from_hex(value) {
*out_color = color.into();
return true;
}
if let Some(color) = ctx.layout.state.globals.get().palette.find(value) {
*out_color = color;
return true;
}
ctx.print_invalid_attrib(tag_name, key, value);
false
}
pub fn parse_color_opt(
@ -44,12 +52,11 @@ pub fn parse_color_opt(
tag_name: &str,
key: &str,
value: &str,
color: &mut Option<drawing::Color>,
out_color: &mut Option<WguiColor>,
) {
if let Some(res_color) = parse_color_hex(value) {
*color = Some(res_color);
} else {
ctx.print_invalid_attrib(tag_name, key, value);
let mut color = WguiColor::default();
if parse_color(ctx, tag_name, key, value, &mut color) {
*out_color = Some(color);
}
}
@ -60,9 +67,7 @@ pub fn parse_text_style(ctx: &ParserContext<'_>, attribs: &[AttribPair], tag_nam
let (key, value) = (pair.attrib.as_ref(), pair.value.as_ref());
match key {
"color" => {
if let Some(color) = parse_color_hex(value) {
style.color = Some(color);
}
parse_color_opt(ctx, tag_name, key, value, &mut style.color);
}
"align" => match value {
"left" => style.align = Some(HorizontalAlign::Left),
@ -90,7 +95,7 @@ pub fn parse_text_style(ctx: &ParserContext<'_>, attribs: &[AttribPair], tag_nam
}
}
"shadow" => {
if let Some(color) = parse_color_hex(value) {
if let Some(color) = drawing::Color::from_hex(value) {
style.shadow.get_or_insert_default().color = color;
}
}

View File

@ -2,14 +2,12 @@ use crate::{
layout::WidgetID,
parser::{
AttribPair, ParserContext, ParserFile, get_asset_path_from_kv, parse_children, parse_widget_universal,
style::parse_style,
style::{parse_color_opt, parse_style},
},
renderer_vk::text::custom_glyph::CustomGlyphData,
widget::sprite::{WidgetSprite, WidgetSpriteParams},
};
use super::parse_color_hex;
pub fn parse_widget_sprite<'a>(
file: &'a ParserFile,
ctx: &mut ParserContext,
@ -39,11 +37,7 @@ pub fn parse_widget_sprite<'a>(
}
}
"color" => {
if let Some(color) = parse_color_hex(value) {
params.color = Some(color);
} else {
ctx.print_invalid_attrib(tag_name, key, value);
}
parse_color_opt(ctx, tag_name, key, value, &mut params.color);
}
_ => {}
}

View File

@ -11,7 +11,10 @@ use etagere::AllocId;
use glam::Mat4;
use parking_lot::Mutex;
use crate::drawing::{self};
use crate::{
color::{WguiColor, WguiColorPalette},
drawing::{self},
};
pub static SWASH_CACHE: LazyLock<Mutex<SwashCache>> = LazyLock::new(|| Mutex::new(SwashCache::new()));
@ -45,7 +48,7 @@ impl Default for TextShadow {
pub struct TextStyle {
pub size: Option<f32>,
pub line_height: Option<f32>,
pub color: Option<drawing::Color>,
pub color: Option<WguiColor>,
pub style: Option<FontStyle>,
pub weight: Option<FontWeight>,
pub align: Option<HorizontalAlign>,
@ -53,12 +56,12 @@ pub struct TextStyle {
pub shadow: Option<TextShadow>,
}
impl From<&TextStyle> for Attrs<'_> {
fn from(style: &TextStyle) -> Self {
impl TextStyle {
pub fn to_attrs(&self, palette: &WguiColorPalette) -> Attrs<'_> {
Attrs::new()
.color(style.color.unwrap_or_default().into())
.style(style.style.unwrap_or_default().into())
.weight(style.weight.unwrap_or_default().into())
.color(self.color.unwrap_or_default().resolve(palette).into())
.style(self.style.unwrap_or_default().into())
.weight(self.weight.unwrap_or_default().into())
}
}

View File

@ -1,16 +1,5 @@
use crate::drawing;
#[derive(Clone)]
pub struct WguiTheme {
pub dark_mode: bool,
pub text_color: drawing::Color,
pub button_color: drawing::Color,
pub accent_color: drawing::Color,
pub danger_color: drawing::Color,
pub faded_color: drawing::Color,
pub bg_color: drawing::Color,
pub editbox_color: drawing::Color,
pub translucent_alpha: f32,
pub animation_mult: f32,
pub rounding_mult: f32,
pub gradient_intensity: f32, // currently used for buttons
@ -19,15 +8,6 @@ pub struct WguiTheme {
impl Default for WguiTheme {
fn default() -> Self {
Self {
dark_mode: true,
text_color: drawing::Color::new(1.0, 1.0, 1.0, 1.0),
button_color: drawing::Color::new(1.0, 1.0, 1.0, 0.02),
accent_color: drawing::Color::new(0.13, 0.68, 1.0, 1.0),
danger_color: drawing::Color::new(0.9, 0.0, 0.0, 1.0),
faded_color: drawing::Color::new(0.67, 0.74, 0.80, 1.0),
bg_color: drawing::Color::new(0.0, 0.07, 0.1, 0.75),
editbox_color: drawing::Color::new(0.15, 0.25, 0.35, 0.95),
translucent_alpha: 0.5,
animation_mult: 1.0,
rounding_mult: 1.0,
gradient_intensity: 0.3,

View File

@ -2,6 +2,7 @@ use slotmap::Key;
use crate::{
drawing::{self},
globals::Globals,
layout::WidgetID,
stack,
widget::WidgetStateFlags,
@ -59,7 +60,7 @@ impl WidgetObj for WidgetCustomDraw {
super::WidgetType::Rectangle
}
fn debug_print(&self) -> String {
fn debug_print(&self, _globals: &Globals) -> String {
String::default()
}
}

View File

@ -1,6 +1,6 @@
use slotmap::Key;
use crate::{layout::WidgetID, widget::WidgetStateFlags};
use crate::{globals::Globals, layout::WidgetID, widget::WidgetStateFlags};
use super::{WidgetObj, WidgetState};
@ -31,7 +31,7 @@ impl WidgetObj for WidgetDiv {
super::WidgetType::Div
}
fn debug_print(&self) -> String {
fn debug_print(&self, _globals: &Globals) -> String {
String::default()
}
}

View File

@ -3,6 +3,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use slotmap::Key;
use crate::{
color::WguiColor,
drawing::{self, ImagePrimitive, PrimitiveExtent},
event::EventAlterables,
globals::Globals,
@ -20,7 +21,7 @@ pub struct WidgetImageParams {
pub glyph_data: Option<CustomGlyphData>,
pub border: f32,
pub border_color: drawing::Color,
pub border_color: WguiColor,
pub round: WLength,
}
@ -84,7 +85,7 @@ impl WidgetObj for WidgetImage {
content_key: self.content_key,
skip_cache: self.dirty,
border: self.params.border,
border_color: self.params.border_color,
border_color: self.params.border_color.resolve(&state.globals.palette),
round_units,
},
));
@ -112,7 +113,7 @@ impl WidgetObj for WidgetImage {
super::WidgetType::Sprite
}
fn debug_print(&self) -> String {
fn debug_print(&self, _globals: &Globals) -> String {
String::default()
}
}

View File

@ -5,13 +5,13 @@ use slotmap::Key;
use taffy::AvailableSpace;
use crate::{
color::{WguiColor, WguiColorName, WguiColorPalette},
drawing::{self, PrimitiveExtent},
event::CallbackDataCommon,
globals::Globals,
i18n::Translation,
layout::{LayoutState, WidgetID},
renderer_vk::text::TextStyle,
theme::WguiTheme,
widget::WidgetStateFlags,
};
@ -32,16 +32,16 @@ pub struct WidgetLabel {
impl WidgetLabel {
pub fn create(state: &mut LayoutState, params: WidgetLabelParams) -> WidgetState {
WidgetLabel::create_ex(&mut state.globals.get(), &state.theme, params)
WidgetLabel::create_ex(&mut state.globals.get(), params)
}
pub fn create_ex(globals: &mut Globals, theme: &WguiTheme, mut params: WidgetLabelParams) -> WidgetState {
pub fn create_ex(globals: &mut Globals, mut params: WidgetLabelParams) -> WidgetState {
if params.style.color.is_none() {
params.style.color = Some(theme.text_color);
params.style.color = Some(WguiColorName::OnPrimary.into());
}
let metrics = Metrics::from(&params.style);
let attrs = Attrs::from(&params.style);
let attrs = params.style.to_attrs(&globals.palette);
let wrap = Wrap::from(&params.style);
let mut buffer = Buffer::new_empty(metrics);
@ -86,7 +86,7 @@ impl WidgetLabel {
}
self.params.content = translation;
let attrs = Attrs::from(&self.params.style);
let attrs = self.params.style.to_attrs(&globals.palette);
let text = self.params.content.generate(&mut globals.i18n_builtin);
@ -101,8 +101,8 @@ impl WidgetLabel {
true
}
fn update_attrs(&mut self) {
let attrs = Attrs::from(&self.params.style);
fn update_attrs(&mut self, palette: &WguiColorPalette) {
let attrs = self.params.style.to_attrs(palette);
for line in &mut self.buffer.borrow_mut().lines {
line.set_attrs_list(AttrsList::new(&attrs));
}
@ -117,10 +117,10 @@ impl WidgetLabel {
}
}
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: drawing::Color, apply_to_existing_text: bool) {
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: WguiColor, apply_to_existing_text: bool) {
self.params.style.color = Some(color);
if apply_to_existing_text {
self.update_attrs();
self.update_attrs(&common.globals().palette);
common.mark_widget_dirty(self.id);
}
}
@ -183,9 +183,9 @@ impl WidgetObj for WidgetLabel {
super::WidgetType::Label
}
fn debug_print(&self) -> String {
fn debug_print(&self, globals: &Globals) -> String {
let color = if let Some(color) = self.params.style.color {
format!("[color: {}]", color.debug_ansi_block())
format!("[color: {}]", color.resolve(&globals.palette).debug_ansi_block())
} else {
String::default()
};

View File

@ -187,7 +187,7 @@ pub trait WidgetObj: AnyTrait {
fn get_id(&self) -> WidgetID;
fn set_id(&mut self, id: WidgetID); // always set at insertion
fn get_type(&self) -> WidgetType;
fn debug_print(&self) -> String;
fn debug_print(&self, _globals: &Globals) -> String;
fn draw(&mut self, state: &mut DrawState, params: &DrawParams);

View File

@ -1,8 +1,10 @@
use slotmap::Key;
use crate::{
color::WguiColor,
drawing::{self, GradientMode, PrimitiveExtent},
event::CallbackDataCommon,
globals::Globals,
layout::WidgetID,
widget::{WidgetStateFlags, util::WLength},
};
@ -11,12 +13,12 @@ use super::{WidgetObj, WidgetState};
#[derive(Debug, Default)]
pub struct WidgetRectangleParams {
pub color: drawing::Color,
pub color2: drawing::Color,
pub color: WguiColor,
pub color2: WguiColor,
pub gradient: GradientMode,
pub border: f32,
pub border_color: drawing::Color,
pub border_color: WguiColor,
pub round: WLength,
}
@ -36,7 +38,8 @@ impl WidgetRectangle {
}),
)
}
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: drawing::Color) {
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: WguiColor) {
self.params.color = color;
common.mark_widget_dirty(self.id);
}
@ -51,17 +54,21 @@ impl WidgetObj for WidgetRectangle {
WLength::Percent(percent) => (f32::min(boundary.size.x, boundary.size.y) * percent / 2.0) as u8,
};
let color = self.params.color.resolve(&state.globals.palette);
let color2 = self.params.color2.resolve(&state.globals.palette);
let border_color = self.params.border_color.resolve(&state.globals.palette);
state.primitives.push(drawing::RenderPrimitive::Rectangle(
PrimitiveExtent {
boundary,
transform: state.transform_stack.get().transform,
},
drawing::Rectangle {
color: self.params.color,
color2: self.params.color2,
color,
color2,
border_color,
gradient: self.params.gradient,
border: self.params.border,
border_color: self.params.border_color,
round_units,
},
));
@ -79,11 +86,11 @@ impl WidgetObj for WidgetRectangle {
super::WidgetType::Rectangle
}
fn debug_print(&self) -> String {
fn debug_print(&self, globals: &Globals) -> String {
format!(
"[color: {}][color2: {}][gradient: {:?}]",
self.params.color.debug_ansi_block(),
self.params.color2.debug_ansi_block(),
self.params.color.resolve(&globals.palette).debug_ansi_block(),
self.params.color2.resolve(&globals.palette).debug_ansi_block(),
self.params.gradient,
)
}

View File

@ -4,6 +4,7 @@ use cosmic_text::{Attrs, Buffer, Color, Shaping, Weight};
use slotmap::Key;
use crate::{
color::WguiColor,
drawing::{self, PrimitiveExtent},
event::{CallbackDataCommon, EventAlterables},
globals::Globals,
@ -20,7 +21,7 @@ use super::{WidgetObj, WidgetState};
#[derive(Debug, Default)]
pub struct WidgetSpriteParams {
pub glyph_data: Option<CustomGlyphData>,
pub color: Option<drawing::Color>,
pub color: Option<WguiColor>,
}
#[derive(Debug, Default)]
@ -40,12 +41,12 @@ impl WidgetSprite {
)
}
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: drawing::Color) {
pub fn set_color(&mut self, common: &mut CallbackDataCommon, color: WguiColor) {
self.params.color = Some(color);
common.mark_widget_dirty(self.id);
}
pub const fn get_color(&self) -> Option<drawing::Color> {
pub const fn get_color(&self) -> Option<WguiColor> {
self.params.color
}
@ -74,12 +75,9 @@ impl WidgetObj for WidgetSprite {
top: 0.0,
width: boundary.size.x,
height: boundary.size.y,
color: Some(
self
.params
.color
.map_or(cosmic_text::Color::rgb(255, 255, 255), Into::into),
),
color: Some(self.params.color.map_or(cosmic_text::Color::rgb(255, 255, 255), |c| {
c.resolve(&state.globals.palette).into()
})),
snap_to_physical_pixel: true,
};
@ -135,7 +133,7 @@ impl WidgetObj for WidgetSprite {
super::WidgetType::Sprite
}
fn debug_print(&self) -> String {
fn debug_print(&self, _globals: &Globals) -> String {
String::default()
}
}

View File

@ -189,7 +189,7 @@ impl WguiWindow {
AnimationEasing::OutQuad,
Box::new(|common, data| {
let rect = data.obj.get_as_mut::<WidgetRectangle>().unwrap() /* should always succeed */;
rect.params.color = drawing::Color::new(0.0, 0.0, 0.0, data.pos * 0.3);
rect.params.color = drawing::Color::new(0.0, 0.0, 0.0, data.pos * 0.3).into();
common.alterables.mark_redraw();
}),
));