simplify and optimize event states, deduplication
This commit is contained in:
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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));
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
let mut params = EventParams {
|
||||||
|
refs: &EventRefs {
|
||||||
|
tree: &self.tree,
|
||||||
|
widget_map: &self.widget_map,
|
||||||
|
widget_node_map: &self.widget_node_map,
|
||||||
|
},
|
||||||
|
layout: l,
|
||||||
|
alterables,
|
||||||
|
node_id,
|
||||||
|
style,
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(listeners) = listeners.get(widget_id) {
|
if let Some(listeners) = listeners.get(widget_id) {
|
||||||
match widget.process_event(
|
match widget.process_event(widget_id, listeners, node_id, event, user_data, &mut params) {
|
||||||
widget_id,
|
|
||||||
listeners,
|
|
||||||
node_id,
|
|
||||||
event,
|
|
||||||
user_data,
|
|
||||||
&mut EventParams {
|
|
||||||
transform_stack: state.transform_stack,
|
|
||||||
widgets: &self.widget_map,
|
|
||||||
tree: &self.tree,
|
|
||||||
animations: state.animations,
|
|
||||||
needs_redraw: &mut state.needs_redraw,
|
|
||||||
trigger_haptics: &mut state.trigger_haptics,
|
|
||||||
node_id,
|
|
||||||
style,
|
|
||||||
taffy_layout: l,
|
|
||||||
dirty_nodes,
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user