simplify and optimize event states, deduplication

This commit is contained in:
Aleksander
2025-07-02 22:55:42 +02:00
parent 283d7fd64e
commit 92444bb5c4
7 changed files with 167 additions and 212 deletions

View File

@@ -1,7 +1,7 @@
use glam::{FloatExt, Vec2}; use glam::{FloatExt, Vec2};
use crate::{ use crate::{
event::CallbackDataCommon, event::{CallbackDataCommon, EventAlterables, EventRefs},
layout::{WidgetID, WidgetMap, WidgetNodeMap}, layout::{WidgetID, WidgetMap, WidgetNodeMap},
widget::{WidgetData, WidgetObj}, widget::{WidgetData, WidgetObj},
}; };
@@ -59,11 +59,6 @@ pub struct Animation {
callback: AnimationCallback, callback: AnimationCallback,
} }
#[derive(Default)]
struct CallResult {
needs_redraw: bool,
}
impl Animation { impl Animation {
pub fn new( pub fn new(
target_widget: WidgetID, target_widget: WidgetID,
@@ -94,22 +89,13 @@ impl Animation {
} }
} }
fn call( fn call(&self, refs: &EventRefs, alterables: &mut EventAlterables, pos: f32) {
&self, let Some(widget) = refs.widget_map.get(self.target_widget).cloned() else {
widget_map: &WidgetMap, return; // failed
widget_node_map: &WidgetNodeMap,
tree: &taffy::tree::TaffyTree<WidgetID>,
dirty_nodes: &mut Vec<taffy::NodeId>,
pos: f32,
) -> CallResult {
let mut res = CallResult::default();
let Some(widget) = widget_map.get(self.target_widget).cloned() else {
return res; // failed
}; };
let widget_node = *widget_node_map.get(self.target_widget).unwrap(); let widget_node = *refs.widget_node_map.get(self.target_widget).unwrap();
let layout = tree.layout(widget_node).unwrap(); // should always succeed let layout = refs.tree.layout(widget_node).unwrap(); // should always succeed
let mut widget = widget.lock().unwrap(); let mut widget = widget.lock().unwrap();
@@ -123,21 +109,9 @@ impl Animation {
pos, pos,
}; };
let common = &mut CallbackDataCommon { let common = &mut CallbackDataCommon { refs, alterables };
dirty_nodes,
needs_redraw: false,
trigger_haptics: false,
widgets: widget_map,
taffy_layout: layout,
};
(self.callback)(common, data); (self.callback)(common, data);
if common.needs_redraw {
res.needs_redraw = true;
}
res
} }
} }
@@ -147,14 +121,7 @@ pub struct Animations {
} }
impl Animations { impl Animations {
pub fn tick( pub fn tick(&mut self, refs: &EventRefs, alterables: &mut EventAlterables) {
&mut self,
widget_map: &WidgetMap,
widget_node_map: &WidgetNodeMap,
tree: &taffy::tree::TaffyTree<WidgetID>,
dirty_nodes: &mut Vec<taffy::NodeId>,
needs_redraw: &mut bool,
) {
for anim in &mut self.running_animations { for anim in &mut self.running_animations {
let x = 1.0 - (anim.ticks_remaining as f32 / anim.ticks_duration as f32); let x = 1.0 - (anim.ticks_remaining as f32 / anim.ticks_duration as f32);
let pos = if anim.ticks_remaining > 0 { let pos = if anim.ticks_remaining > 0 {
@@ -166,11 +133,10 @@ impl Animations {
anim.pos_prev = anim.pos; anim.pos_prev = anim.pos;
anim.pos = pos; anim.pos = pos;
anim.call(refs, alterables, 1.0);
let res = anim.call(widget_map, widget_node_map, tree, dirty_nodes, 1.0); if anim.last_tick {
alterables.needs_redraw = true;
if anim.last_tick || res.needs_redraw {
*needs_redraw = true;
} }
anim.ticks_remaining -= 1; anim.ticks_remaining -= 1;
@@ -181,22 +147,10 @@ impl Animations {
.retain(|anim| anim.ticks_remaining > 0); .retain(|anim| anim.ticks_remaining > 0);
} }
pub fn process( pub fn process(&mut self, refs: &EventRefs, alterables: &mut EventAlterables, alpha: f32) {
&mut self,
widget_map: &WidgetMap,
widget_node_map: &WidgetNodeMap,
tree: &taffy::tree::TaffyTree<WidgetID>,
dirty_nodes: &mut Vec<taffy::NodeId>,
alpha: f32,
needs_redraw: &mut bool,
) {
for anim in &mut self.running_animations { for anim in &mut self.running_animations {
let pos = anim.pos_prev.lerp(anim.pos, alpha); let pos = anim.pos_prev.lerp(anim.pos, alpha);
let res = anim.call(widget_map, widget_node_map, tree, dirty_nodes, pos); anim.call(refs, alterables, pos);
if res.needs_redraw {
*needs_redraw = true;
}
} }
} }

View File

@@ -159,9 +159,7 @@ pub fn construct<U1, U2>(
rect_id, rect_id,
EventListenerKind::MouseEnter, EventListenerKind::MouseEnter,
Box::new(move |common, data, _, _| { Box::new(move |common, data, _, _| {
data common.animate(anim_hover_in(button.clone(), data.widget_id));
.animations
.push(anim_hover_in(button.clone(), data.widget_id));
}), }),
); );
@@ -170,9 +168,7 @@ pub fn construct<U1, U2>(
rect_id, rect_id,
EventListenerKind::MouseLeave, EventListenerKind::MouseLeave,
Box::new(move |common, data, _, _| { Box::new(move |common, data, _, _| {
data common.animate(anim_hover_out(button.clone(), data.widget_id));
.animations
.push(anim_hover_out(button.clone(), data.widget_id));
}), }),
); );

View File

@@ -93,8 +93,8 @@ fn anim_rect(rect: &mut Rectangle, pos: f32) {
drawing::Color::lerp(&HANDLE_BORDER_COLOR, &HANDLE_BORDER_COLOR_HOVERED, pos); drawing::Color::lerp(&HANDLE_BORDER_COLOR, &HANDLE_BORDER_COLOR_HOVERED, pos);
} }
fn on_enter_anim(data: &mut event::CallbackData, handle_id: WidgetID) { fn on_enter_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID) {
data.animations.push(Animation::new( common.animate(Animation::new(
handle_id, handle_id,
5, 5,
AnimationEasing::OutQuad, AnimationEasing::OutQuad,
@@ -107,8 +107,8 @@ fn on_enter_anim(data: &mut event::CallbackData, handle_id: WidgetID) {
)); ));
} }
fn on_leave_anim(data: &mut event::CallbackData, handle_id: WidgetID) { fn on_leave_anim(common: &mut event::CallbackDataCommon, handle_id: WidgetID) {
data.animations.push(Animation::new( common.animate(Animation::new(
handle_id, handle_id,
10, 10,
AnimationEasing::OutQuad, AnimationEasing::OutQuad,
@@ -130,10 +130,10 @@ fn register_event_mouse_enter<U1, U2>(
listeners.add( listeners.add(
slider.body, slider.body,
EventListenerKind::MouseEnter, EventListenerKind::MouseEnter,
Box::new(move |common, data, _, _| { Box::new(move |common, _data, _, _| {
common.trigger_haptics(); common.trigger_haptics();
slider.get_state().hovered = true; slider.get_state().hovered = true;
on_enter_anim(data, slider.slider_handle_rect_id); on_enter_anim(common, slider.slider_handle_rect_id);
}), }),
); );
} }
@@ -145,10 +145,10 @@ fn register_event_mouse_leave<U1, U2>(
listeners.add( listeners.add(
slider.body, slider.body,
EventListenerKind::MouseLeave, EventListenerKind::MouseLeave,
Box::new(move |common, data, _, _| { Box::new(move |common, _data, _, _| {
common.trigger_haptics(); common.trigger_haptics();
slider.get_state().hovered = false; slider.get_state().hovered = false;
on_leave_anim(data, slider.slider_handle_rect_id); on_leave_anim(common, slider.slider_handle_rect_id);
}), }),
); );
} }

View File

@@ -2,9 +2,9 @@ use glam::Vec2;
use slotmap::SecondaryMap; use slotmap::SecondaryMap;
use crate::{ use crate::{
animation, animation::{self, Animation},
layout::{WidgetID, WidgetMap}, layout::{WidgetID, WidgetMap, WidgetNodeMap},
transform_stack::Transform, transform_stack::{Transform, TransformStack},
widget::{WidgetData, WidgetObj}, widget::{WidgetData, WidgetObj},
}; };
@@ -74,21 +74,34 @@ impl Event {
} }
} }
pub struct CallbackDataCommon<'a> { pub struct EventRefs<'a> {
pub widgets: &'a WidgetMap, pub widget_map: &'a WidgetMap,
pub taffy_layout: &'a taffy::Layout, pub widget_node_map: &'a WidgetNodeMap,
pub dirty_nodes: &'a mut Vec<taffy::NodeId>, pub tree: &'a taffy::tree::TaffyTree<WidgetID>,
}
#[derive(Default)]
pub struct EventAlterables {
pub dirty_nodes: Vec<taffy::NodeId>,
pub style_set_requests: Vec<(taffy::NodeId, taffy::Style)>,
pub animations: Vec<animation::Animation>,
pub transform_stack: TransformStack,
pub needs_redraw: bool, pub needs_redraw: bool,
pub trigger_haptics: bool, pub trigger_haptics: bool,
} }
impl<'a> CallbackDataCommon<'a> { pub struct CallbackDataCommon<'a> {
pub refs: &'a EventRefs<'a>,
pub alterables: &'a mut EventAlterables,
}
impl CallbackDataCommon<'_> {
pub fn call_on_widget<WIDGET, FUNC>(&self, widget_id: WidgetID, func: FUNC) pub fn call_on_widget<WIDGET, FUNC>(&self, widget_id: WidgetID, func: FUNC)
where where
WIDGET: WidgetObj, WIDGET: WidgetObj,
FUNC: FnOnce(&mut WIDGET), FUNC: FnOnce(&mut WIDGET),
{ {
let Some(widget) = self.widgets.get(widget_id) else { let Some(widget) = self.refs.widget_map.get(widget_id) else {
debug_assert!(false); debug_assert!(false);
return; return;
}; };
@@ -100,26 +113,33 @@ impl<'a> CallbackDataCommon<'a> {
} }
pub fn mark_redraw(&mut self) { pub fn mark_redraw(&mut self) {
self.needs_redraw = true; self.alterables.needs_redraw = true;
}
pub fn set_style(&mut self, node_id: taffy::NodeId, style: taffy::Style) {
self.alterables.style_set_requests.push((node_id, style));
} }
pub fn mark_dirty(&mut self, node_id: taffy::NodeId) { pub fn mark_dirty(&mut self, node_id: taffy::NodeId) {
self.dirty_nodes.push(node_id); self.alterables.dirty_nodes.push(node_id);
} }
pub fn trigger_haptics(&mut self) { pub fn trigger_haptics(&mut self) {
self.trigger_haptics = true; self.alterables.trigger_haptics = true;
} }
pub fn get_taffy_layout(&self) -> &taffy::Layout { pub fn get_tree(&self) -> &taffy::TaffyTree<WidgetID> {
self.taffy_layout self.refs.tree
}
pub fn animate(&mut self, animation: Animation) {
self.alterables.animations.push(animation);
} }
} }
pub struct CallbackData<'a> { pub struct CallbackData<'a> {
pub obj: &'a mut dyn WidgetObj, pub obj: &'a mut dyn WidgetObj,
pub widget_data: &'a mut WidgetData, pub widget_data: &'a mut WidgetData,
pub animations: &'a mut Vec<animation::Animation>,
pub widget_id: WidgetID, pub widget_id: WidgetID,
pub node_id: taffy::NodeId, pub node_id: taffy::NodeId,
pub metadata: CallbackMetadata, pub metadata: CallbackMetadata,

View File

@@ -3,7 +3,7 @@ use std::sync::{Arc, Mutex};
use crate::{ use crate::{
animation::{self, Animations}, animation::{self, Animations},
assets::AssetProvider, assets::AssetProvider,
event::{self, EventListenerCollection}, event::{self, EventAlterables, EventListenerCollection, EventRefs},
transform_stack::{Transform, TransformStack}, transform_stack::{Transform, TransformStack},
widget::{self, EventParams, WidgetState, div::Div}, widget::{self, EventParams, WidgetState, div::Div},
}; };
@@ -20,13 +20,6 @@ pub type BoxWidget = Arc<Mutex<WidgetState>>;
pub type WidgetMap = HopSlotMap<WidgetID, BoxWidget>; pub type WidgetMap = HopSlotMap<WidgetID, BoxWidget>;
pub type WidgetNodeMap = SecondaryMap<WidgetID, taffy::NodeId>; pub type WidgetNodeMap = SecondaryMap<WidgetID, taffy::NodeId>;
struct PushEventState<'a> {
pub animations: &'a mut Vec<animation::Animation>,
pub transform_stack: &'a mut TransformStack,
pub needs_redraw: bool,
pub trigger_haptics: bool,
}
pub struct Layout { pub struct Layout {
pub tree: TaffyTree<WidgetID>, pub tree: TaffyTree<WidgetID>,
@@ -93,13 +86,12 @@ impl Layout {
&self, &self,
listeners: &EventListenerCollection<U1, U2>, listeners: &EventListenerCollection<U1, U2>,
parent_node_id: taffy::NodeId, parent_node_id: taffy::NodeId,
state: &mut PushEventState,
event: &event::Event, event: &event::Event,
dirty_nodes: &mut Vec<taffy::NodeId>, alterables: &mut EventAlterables,
user_data: &mut (&mut U1, &mut U2), user_data: &mut (&mut U1, &mut U2),
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
for child_id in self.tree.child_ids(parent_node_id) { for child_id in self.tree.child_ids(parent_node_id) {
self.push_event_widget(listeners, state, child_id, event, dirty_nodes, user_data)?; self.push_event_widget(listeners, child_id, event, alterables, user_data)?;
} }
Ok(()) Ok(())
@@ -108,10 +100,9 @@ impl Layout {
fn push_event_widget<U1, U2>( fn push_event_widget<U1, U2>(
&self, &self,
listeners: &EventListenerCollection<U1, U2>, listeners: &EventListenerCollection<U1, U2>,
state: &mut PushEventState,
node_id: taffy::NodeId, node_id: taffy::NodeId,
event: &event::Event, event: &event::Event,
dirty_nodes: &mut Vec<taffy::NodeId>, alterables: &mut EventAlterables,
user_data: &mut (&mut U1, &mut U2), user_data: &mut (&mut U1, &mut U2),
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let l = self.tree.layout(node_id)?; let l = self.tree.layout(node_id)?;
@@ -134,30 +125,24 @@ impl Layout {
transform: glam::Mat4::IDENTITY, // TODO: event transformations? Not needed for now transform: glam::Mat4::IDENTITY, // TODO: event transformations? Not needed for now
}; };
state.transform_stack.push(transform); alterables.transform_stack.push(transform);
let mut iter_children = true; let mut iter_children = true;
if let Some(listeners) = listeners.get(widget_id) { let mut params = EventParams {
match widget.process_event( refs: &EventRefs {
widget_id,
listeners,
node_id,
event,
user_data,
&mut EventParams {
transform_stack: state.transform_stack,
widgets: &self.widget_map,
tree: &self.tree, tree: &self.tree,
animations: state.animations, widget_map: &self.widget_map,
needs_redraw: &mut state.needs_redraw, widget_node_map: &self.widget_node_map,
trigger_haptics: &mut state.trigger_haptics, },
layout: l,
alterables,
node_id, node_id,
style, style,
taffy_layout: l, };
dirty_nodes,
}, if let Some(listeners) = listeners.get(widget_id) {
) { match widget.process_event(widget_id, listeners, node_id, event, user_data, &mut params) {
widget::EventResult::Pass => { widget::EventResult::Pass => {
// go on // go on
} }
@@ -173,10 +158,10 @@ impl Layout {
drop(widget); // free mutex drop(widget); // free mutex
if iter_children { if iter_children {
self.push_event_children(listeners, node_id, state, event, dirty_nodes, user_data)?; self.push_event_children(listeners, node_id, event, alterables, user_data)?;
} }
state.transform_stack.pop(); alterables.transform_stack.pop();
Ok(()) Ok(())
} }
@@ -205,44 +190,17 @@ impl Layout {
event: &event::Event, event: &event::Event,
mut user_data: (&mut U1, &mut U2), mut user_data: (&mut U1, &mut U2),
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let mut transform_stack = TransformStack::new(); let mut alterables = EventAlterables::default();
let mut animations_to_add = Vec::<animation::Animation>::new();
let mut dirty_nodes = Vec::new();
let mut state = PushEventState {
transform_stack: &mut transform_stack,
animations: &mut animations_to_add,
needs_redraw: false,
trigger_haptics: false,
};
self.push_event_widget( self.push_event_widget(
listeners, listeners,
&mut state,
self.root_node, self.root_node,
event, event,
&mut dirty_nodes, &mut alterables,
&mut user_data, &mut user_data,
)?; )?;
for node in dirty_nodes { self.process_alterables(alterables)?;
self.tree.mark_dirty(node)?;
}
if state.trigger_haptics {
self.haptics_triggered = true;
}
if state.needs_redraw {
self.needs_redraw = true;
}
if !animations_to_add.is_empty() {
self.needs_redraw = true;
for anim in animations_to_add {
self.animations.add(anim);
}
}
Ok(()) Ok(())
} }
@@ -280,20 +238,19 @@ impl Layout {
} }
pub fn update(&mut self, size: Vec2, timestep_alpha: f32) -> anyhow::Result<()> { pub fn update(&mut self, size: Vec2, timestep_alpha: f32) -> anyhow::Result<()> {
let mut dirty_nodes = Vec::new(); let mut alterables = EventAlterables::default();
self.animations.process( let refs = EventRefs {
&self.widget_map, tree: &self.tree,
&self.widget_node_map, widget_map: &self.widget_map,
&self.tree, widget_node_map: &self.widget_node_map,
&mut dirty_nodes, };
timestep_alpha,
&mut self.needs_redraw,
);
for node in dirty_nodes { self
self.tree.mark_dirty(node)?; .animations
} .process(&refs, &mut alterables, timestep_alpha);
self.process_alterables(alterables)?;
if self.tree.dirty(self.root_node)? || self.prev_size != size { if self.tree.dirty(self.root_node)? || self.prev_size != size {
self.needs_redraw = true; self.needs_redraw = true;
@@ -343,20 +300,50 @@ impl Layout {
} }
pub fn tick(&mut self) -> anyhow::Result<()> { pub fn tick(&mut self) -> anyhow::Result<()> {
let mut dirty_nodes = Vec::new(); let mut alterables = EventAlterables::default();
self.animations.tick( let refs = EventRefs {
&self.widget_map, tree: &self.tree,
&self.widget_node_map, widget_map: &self.widget_map,
&self.tree, widget_node_map: &self.widget_node_map,
&mut dirty_nodes, };
&mut self.needs_redraw,
);
for node in dirty_nodes { self.animations.tick(&refs, &mut alterables);
self.process_alterables(alterables)?;
Ok(())
}
fn process_alterables(&mut self, alterables: EventAlterables) -> anyhow::Result<()> {
for node in alterables.dirty_nodes {
self.tree.mark_dirty(node)?; self.tree.mark_dirty(node)?;
} }
if alterables.needs_redraw {
self.needs_redraw = true;
}
if alterables.trigger_haptics {
self.haptics_triggered = true;
}
if !alterables.animations.is_empty() {
self.needs_redraw = true;
for anim in alterables.animations {
self.animations.add(anim);
}
}
for request in alterables.style_set_requests {
if let Err(e) = self.tree.set_style(request.0, request.1) {
log::error!(
"failed to set style for taffy widget ID {:?}: {:?}",
request.0,
e
);
}
}
Ok(()) Ok(())
} }
} }

View File

@@ -2,14 +2,13 @@ use glam::Vec2;
use super::drawing::RenderPrimitive; use super::drawing::RenderPrimitive;
use crate::{ use crate::{
animation,
any::AnyTrait, any::AnyTrait,
drawing, drawing,
event::{ event::{
CallbackData, CallbackDataCommon, CallbackMetadata, Event, EventListener, EventListenerKind, CallbackData, CallbackDataCommon, CallbackMetadata, Event, EventAlterables, EventListener,
MouseWheelEvent, EventListenerKind, EventRefs, MouseWheelEvent,
}, },
layout::{Layout, WidgetID, WidgetMap}, layout::{Layout, WidgetID},
transform_stack::TransformStack, transform_stack::TransformStack,
}; };
@@ -124,14 +123,15 @@ pub trait WidgetObj: AnyTrait {
pub struct EventParams<'a> { pub struct EventParams<'a> {
pub node_id: taffy::NodeId, pub node_id: taffy::NodeId,
pub style: &'a taffy::Style, pub style: &'a taffy::Style,
pub taffy_layout: &'a taffy::Layout, pub refs: &'a EventRefs<'a>,
pub widgets: &'a WidgetMap, pub alterables: &'a mut EventAlterables,
pub tree: &'a taffy::TaffyTree<WidgetID>, pub layout: &'a taffy::Layout,
pub transform_stack: &'a TransformStack, }
pub animations: &'a mut Vec<animation::Animation>,
pub needs_redraw: &'a mut bool, impl EventParams<'_> {
pub trigger_haptics: &'a mut bool, pub fn mark_redraw(&mut self) {
pub dirty_nodes: &'a mut Vec<taffy::NodeId>, self.alterables.needs_redraw = true;
}
} }
pub enum EventResult { pub enum EventResult {
@@ -189,27 +189,17 @@ macro_rules! call_event {
let mut data = CallbackData { let mut data = CallbackData {
obj: $self.obj.as_mut(), obj: $self.obj.as_mut(),
widget_data: &mut $self.data, widget_data: &mut $self.data,
animations: $params.animations,
$widget_id, $widget_id,
$node_id, $node_id,
metadata: $metadata, metadata: $metadata,
}; };
let mut common = CallbackDataCommon { let mut common = CallbackDataCommon {
widgets: $params.widgets, refs: $params.refs,
needs_redraw: false, alterables: $params.alterables,
trigger_haptics: false,
dirty_nodes: $params.dirty_nodes,
taffy_layout: $params.taffy_layout,
}; };
callback(&mut common, &mut data, $user_data.0, $user_data.1); callback(&mut common, &mut data, $user_data.0, $user_data.1);
if common.trigger_haptics {
*$params.trigger_haptics = true;
}
if common.needs_redraw {
*$params.needs_redraw = true;
}
} }
} }
}; };
@@ -290,13 +280,13 @@ impl WidgetState {
return false; return false;
} }
let l = params.taffy_layout; let l = params.layout;
let overflow = Vec2::new(l.scroll_width(), l.scroll_height()); let overflow = Vec2::new(l.scroll_width(), l.scroll_height());
if overflow.x == 0.0 && overflow.y == 0.0 { if overflow.x == 0.0 && overflow.y == 0.0 {
return false; // not overflowing return false; // not overflowing
} }
let Some(info) = get_scrollbar_info(params.taffy_layout) else { let Some(info) = get_scrollbar_info(params.layout) else {
return false; return false;
}; };
@@ -308,7 +298,7 @@ impl WidgetState {
let new_scroll = (self.data.scrolling.x + wheel.shift.x * mult).clamp(0.0, 1.0); let new_scroll = (self.data.scrolling.x + wheel.shift.x * mult).clamp(0.0, 1.0);
if self.data.scrolling.x != new_scroll { if self.data.scrolling.x != new_scroll {
self.data.scrolling.x = new_scroll; self.data.scrolling.x = new_scroll;
*params.needs_redraw = true; params.mark_redraw();
} }
} }
@@ -318,23 +308,23 @@ impl WidgetState {
let new_scroll = (self.data.scrolling.y + wheel.shift.y * mult).clamp(0.0, 1.0); let new_scroll = (self.data.scrolling.y + wheel.shift.y * mult).clamp(0.0, 1.0);
if self.data.scrolling.y != new_scroll { if self.data.scrolling.y != new_scroll {
self.data.scrolling.y = new_scroll; self.data.scrolling.y = new_scroll;
*params.needs_redraw = true; params.mark_redraw();
} }
} }
true true
} }
pub fn process_event<U1, U2>( pub fn process_event<'a, U1, U2>(
&mut self, &mut self,
widget_id: WidgetID, widget_id: WidgetID,
listeners: &[EventListener<U1, U2>], listeners: &[EventListener<U1, U2>],
node_id: taffy::NodeId, node_id: taffy::NodeId,
event: &Event, event: &Event,
user_data: &mut (&mut U1, &mut U2), user_data: &mut (&mut U1, &mut U2),
params: &mut EventParams, params: &'a mut EventParams<'a>,
) -> EventResult { ) -> EventResult {
let hovered = event.test_mouse_within_transform(params.transform_stack.get()); let hovered = event.test_mouse_within_transform(params.alterables.transform_stack.get());
match &event { match &event {
Event::MouseDown(e) => { Event::MouseDown(e) => {

View File

@@ -193,7 +193,7 @@ where
let k = key_state.clone(); let k = key_state.clone();
move |common, data, _app, _state| { move |common, data, _app, _state| {
common.trigger_haptics(); common.trigger_haptics();
on_enter_anim(k.clone(), data); on_enter_anim(k.clone(), common, data);
} }
}), }),
); );
@@ -204,7 +204,7 @@ where
let k = key_state.clone(); let k = key_state.clone();
move |common, data, _app, _state| { move |common, data, _app, _state| {
common.trigger_haptics(); common.trigger_haptics();
on_leave_anim(k.clone(), data); on_leave_anim(k.clone(), common, data);
} }
}), }),
); );
@@ -299,8 +299,12 @@ fn set_anim_color(key_state: &KeyState, rect: &mut Rectangle, pos: f32) {
rect.params.color2.b = key_state.color2.b + br2; rect.params.color2.b = key_state.color2.b + br2;
} }
fn on_enter_anim(key_state: Rc<KeyState>, data: &mut event::CallbackData) { fn on_enter_anim(
data.animations.push(Animation::new( key_state: Rc<KeyState>,
common: &mut event::CallbackDataCommon,
data: &event::CallbackData,
) {
common.animate(Animation::new(
data.widget_id, data.widget_id,
10, 10,
AnimationEasing::OutBack, AnimationEasing::OutBack,
@@ -313,8 +317,12 @@ fn on_enter_anim(key_state: Rc<KeyState>, data: &mut event::CallbackData) {
)); ));
} }
fn on_leave_anim(key_state: Rc<KeyState>, data: &mut event::CallbackData) { fn on_leave_anim(
data.animations.push(Animation::new( key_state: Rc<KeyState>,
common: &mut event::CallbackDataCommon,
data: &event::CallbackData,
) {
common.animate(Animation::new(
data.widget_id, data.widget_id,
15, 15,
AnimationEasing::OutQuad, AnimationEasing::OutQuad,