use crate::*;
pub mod prelude {
pub use super::{
UiHover,
hover_set,
};
}
#[derive(Component, Reflect, Clone, Debug)]
pub struct UiHover {
value: f32,
pub enable: bool,
#[reflect(ignore, default = "default_linear_curve")]
pub curve: fn(f32) -> f32,
pub forward_speed: f32,
pub backward_speed: f32,
pub instant: bool,
}
impl UiHover {
pub fn new() -> Self {
Self::default()
}
pub fn curve(mut self, curve: fn(f32) -> f32) -> Self {
self.curve = curve;
self
}
pub fn forward_speed(mut self, forward_speed: f32) -> Self {
self.forward_speed = forward_speed;
self
}
pub fn backward_speed(mut self, backward_speed: f32) -> Self {
self.backward_speed = backward_speed;
self
}
pub fn instant(mut self, instant: bool) -> Self {
self.instant = instant;
self
}
}
impl Default for UiHover {
fn default() -> Self {
Self {
value: 0.0,
enable: false,
curve: |v| {v},
forward_speed: 1.0,
backward_speed: 1.0,
instant: false,
}
}
}
impl UiStateTrait for UiHover {
fn value(&self) -> f32 {
(self.curve)(self.value)
}
}
pub fn system_state_hover_update(
time: Res<Time>,
mut query: Query<&mut UiHover>,
) {
for mut hover in &mut query {
if hover.enable && hover.value < 1.0 {
if hover.instant { hover.value = 1.0; continue; }
hover.value = (hover.value + hover.forward_speed * time.delta_secs()).min(1.0);
}
if !hover.enable && hover.value > 0.0 {
if hover.instant { hover.value = 0.0; continue; }
hover.value = (hover.value - hover.backward_speed * time.delta_secs()).max(0.0);
}
}
}
#[derive(EntityEvent, Clone, Copy)]
pub struct UiHoverSet{
entity: Entity,
enable_hover_transition: bool,
}
fn observer_state_hover_set(
trigger: On<UiHoverSet>,
mut query: Query<&mut UiHover>,
) {
if let Ok(mut hover) = query.get_mut(trigger.event_target()) {
hover.enable = trigger.enable_hover_transition;
}
}
pub fn hover_set<E: EntityEvent, const BOOL: bool>(trigger: On<E>, mut commands: Commands) {
commands.trigger(UiHoverSet{entity: trigger.event_target(), enable_hover_transition: BOOL});
}
#[derive(Component, Reflect, Clone, PartialEq, Debug)]
pub struct UiSelected(pub f32);
impl UiStateTrait for UiSelected {
fn value(&self) -> f32 {
self.0
}
}
#[derive(Component, Reflect, Clone, PartialEq, Debug)]
pub struct UiClicked(pub f32);
impl UiStateTrait for UiClicked {
fn value(&self) -> f32 {
self.0
}
}
#[derive(Component, Reflect, Clone, PartialEq, Debug)]
pub struct UiIntro(pub f32);
impl UiStateTrait for UiIntro {
fn value(&self) -> f32 {
self.0
}
}
#[derive(Component, Reflect, Clone, PartialEq, Debug)]
pub struct UiOutro(pub f32);
impl UiStateTrait for UiOutro {
fn value(&self) -> f32 {
self.0
}
}
pub fn default_linear_curve() -> fn(f32) -> f32 { |v| {v} }
fn observer_event_duplicator<'a, E: EntityEvent + Copy>(trigger: On<E>, mut commands: Commands, mut query: Query<&Children>)
where E::Trigger<'a>: Default
{
if let Ok(children) = query.get_mut(trigger.event_target()) {
for target in children.iter() {
let child_event = *trigger.event();
commands.entity(target).trigger(|_| child_event);
}
}
}
pub struct UiLunexStatePlugin;
impl Plugin for UiLunexStatePlugin {
fn build(&self, app: &mut App) {
app.add_observer(observer_state_hover_set);
app.add_observer(observer_event_duplicator::<UiHoverSet>);
app.add_systems(Update, (
system_state_hover_update,
system_state_pipe_into_manager::<UiHover>,
system_state_pipe_into_manager::<UiSelected>,
system_state_pipe_into_manager::<UiClicked>,
system_state_pipe_into_manager::<UiIntro>,
system_state_pipe_into_manager::<UiOutro>,
).in_set(UiSystems::PreCompute));
}
}