sickle_ui_scaffold/
ui_style.rs1pub mod attribute;
2pub mod builder;
3pub mod generated;
4pub mod manual;
5
6use bevy::{ecs::system::EntityCommands, prelude::*, utils::HashSet};
7
8use sickle_math::lerp::Lerp;
9
10use attribute::AnimatedVals;
11use generated::LockableStyleAttribute;
12
13pub mod prelude {
14 pub use super::{
15 attribute::{AnimatedVals, InteractiveVals},
16 builder::StyleBuilder,
17 generated::*,
18 manual::*,
19 *,
20 };
21}
22
23pub struct UiStyle<'a> {
24 commands: EntityCommands<'a>,
25}
26
27impl UiStyle<'_> {
28 pub fn id(&self) -> Entity {
30 self.commands.id()
31 }
32
33 pub fn entity_commands(&mut self) -> EntityCommands {
35 self.commands.reborrow()
36 }
37}
38
39pub trait UiStyleExt {
40 fn style(&mut self, entity: Entity) -> UiStyle;
63}
64
65impl UiStyleExt for Commands<'_, '_> {
66 fn style(&mut self, entity: Entity) -> UiStyle {
67 UiStyle {
68 commands: self.entity(entity),
69 }
70 }
71}
72
73pub struct UiStyleUnchecked<'a> {
74 commands: EntityCommands<'a>,
75}
76
77impl UiStyleUnchecked<'_> {
78 pub fn id(&self) -> Entity {
80 self.commands.id()
81 }
82
83 pub fn entity_commands(&mut self) -> EntityCommands {
85 self.commands.reborrow()
86 }
87}
88
89pub trait UiStyleUncheckedExt {
90 fn style_unchecked(&mut self, entity: Entity) -> UiStyleUnchecked;
92}
93
94impl UiStyleUncheckedExt for Commands<'_, '_> {
95 fn style_unchecked(&mut self, entity: Entity) -> UiStyleUnchecked {
96 UiStyleUnchecked {
97 commands: self.entity(entity),
98 }
99 }
100}
101
102pub trait LogicalEq<Rhs: ?Sized = Self> {
103 fn logical_eq(&self, other: &Rhs) -> bool;
104
105 fn logical_ne(&self, other: &Rhs) -> bool {
106 !self.logical_eq(other)
107 }
108}
109
110#[derive(Component, Debug, Default, Reflect)]
114pub struct LockedStyleAttributes(HashSet<LockableStyleAttribute>);
115
116impl LockedStyleAttributes {
117 pub fn new() -> Self {
119 Self(HashSet::<LockableStyleAttribute>::new())
120 }
121
122 pub fn lock(attributes: impl Into<HashSet<LockableStyleAttribute>>) -> Self {
124 Self(attributes.into())
125 }
126
127 pub fn from_vec(attributes: Vec<LockableStyleAttribute>) -> Self {
129 let mut set = HashSet::<LockableStyleAttribute>::with_capacity(attributes.len());
130 for attribute in attributes.iter() {
131 if !set.contains(attribute) {
132 set.insert(*attribute);
133 }
134 }
135
136 Self(set)
137 }
138
139 pub fn contains(&self, attr: LockableStyleAttribute) -> bool {
141 self.0.contains(&attr)
142 }
143}
144
145impl From<LockableStyleAttribute> for HashSet<LockableStyleAttribute> {
146 fn from(value: LockableStyleAttribute) -> Self {
147 let mut set = HashSet::<LockableStyleAttribute>::new();
148 set.insert(value);
149 set
150 }
151}
152
153#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Eq, Reflect)]
157pub enum TrackedStyleState {
158 #[default]
159 None,
160 Transitioning,
161 Enter,
162 Idle,
163 Hover,
164 Pressed,
165 Released,
166 Canceled,
167}
168
169impl Lerp for TrackedStyleState {
170 fn lerp(&self, to: Self, t: f32) -> Self {
171 if t == 0. {
172 *self
173 } else if t == 1. {
174 to
175 } else {
176 Self::Transitioning
177 }
178 }
179}
180
181impl TrackedStyleState {
182 pub fn default_vals() -> AnimatedVals<Self> {
183 AnimatedVals {
184 idle: Self::Idle,
185 hover: Self::Hover.into(),
186 press: Self::Pressed.into(),
187 cancel: Self::Canceled.into(),
188 enter_from: Self::Enter.into(),
189 ..default()
190 }
191 }
192}