use crate::*;
pub fn default_linear_curve() -> fn(f32) -> f32 { |v| {v} }
#[derive(Component, Reflect, Clone, PartialEq, 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(Event, Clone, Copy)]
pub struct UiHoverSet(pub bool);
fn observer_state_hover_set(
trigger: Trigger<UiHoverSet>,
mut query: Query<&mut UiHover>,
) {
if let Ok(mut hover) = query.get_mut(trigger.entity()) {
hover.enable = trigger.0;
}
}
pub fn hover_set<E: Event, const BOOL: bool>(trigger: Trigger<E>, mut commands: Commands) {
commands.trigger_targets(UiHoverSet(BOOL), trigger.entity());
}
#[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
}
}
fn observer_event_duplicator<E: Event + Copy>(trigger: Trigger<E>, mut commands: Commands, mut query: Query<&Children>) {
if let Ok(children) = query.get_mut(trigger.entity()) {
let targets: Vec<Entity> = children.iter().copied().collect();
commands.trigger_targets(*trigger.event(), targets);
}
}
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));
}
}