fix(interactor/interactor): Factor out the logic for on-event activity updates

This commit is contained in:
Ellen Emilia Anna Zscheile 2025-06-27 06:12:38 +02:00
parent a4b1b3893c
commit c66089bca9
3 changed files with 83 additions and 75 deletions

View File

@ -138,51 +138,6 @@ impl Viewport {
if let Some(workspace) = maybe_workspace { if let Some(workspace) = maybe_workspace {
let latest_point = point! {x: latest_pos.x as f64, y: -latest_pos.y as f64}; let latest_point = point! {x: latest_pos.x as f64, y: -latest_pos.y as f64};
if !workspace.interactor.maybe_activity().as_ref().map_or(true, |activity| {
matches!(activity.maybe_status(), Some(ControlFlow::Break(..)))
}) {
// there is currently some activity
let interactive_event = if response.clicked_by(egui::PointerButton::Primary) {
Some(InteractiveEvent::PointerPrimaryButtonClicked)
} else if response.clicked_by(egui::PointerButton::Secondary) {
Some(InteractiveEvent::PointerSecondaryButtonClicked)
} else {
None
};
if let Some(event) = interactive_event {
log::debug!("got {:?}", event);
}
// Advances the app's state by the delta time `dt`. May call
// `.update_state()` more than once if the delta time is more than a multiple of
// the timestep.
let dt = ctx.input(|i| i.stable_dt);
let active_layer = workspace.appearance_panel.active_layer;
self.update_counter += if interactive_event.is_some() {
// make sure we run the loop below at least once on clicks
let mut dtx = menu_bar.frame_timestep;
if dt > dtx {
dtx = dt;
}
dtx
} else {
dt
};
while self.update_counter >= menu_bar.frame_timestep {
self.update_counter -= menu_bar.frame_timestep;
if let ControlFlow::Break(()) = workspace.update_state(
tr,
error_dialog,
&InteractiveInput {
active_layer,
pointer_pos: latest_point,
dt,
},
interactive_event,
) {
break;
}
}
} else {
// Advances the app's state by the delta time `dt`. May call // Advances the app's state by the delta time `dt`. May call
// `.update_state()` more than once if the delta time is more than a multiple of // `.update_state()` more than once if the delta time is more than a multiple of
// the timestep. // the timestep.
@ -199,11 +154,37 @@ impl Viewport {
pointer_pos: point! {x: latest_pos.x as f64, y: latest_pos.y as f64}, pointer_pos: point! {x: latest_pos.x as f64, y: latest_pos.y as f64},
dt, dt,
}, },
None,
) { ) {
break; break;
} }
} }
if !workspace.interactor.maybe_activity().as_ref().map_or(true, |activity| {
matches!(activity.maybe_status(), Some(ControlFlow::Break(..)))
}) {
// there is currently some activity
let interactive_event = if response.clicked_by(egui::PointerButton::Primary) {
Some(InteractiveEvent::PointerPrimaryButtonClicked)
} else if response.clicked_by(egui::PointerButton::Secondary) {
Some(InteractiveEvent::PointerSecondaryButtonClicked)
} else {
None
};
if let Some(interactive_event) = interactive_event {
let dt = ctx.input(|i| i.stable_dt);
let active_layer = workspace.appearance_panel.active_layer;
let _ = workspace.update_state_for_event(
tr,
error_dialog,
&InteractiveInput {
active_layer,
pointer_pos: latest_point,
dt,
},
interactive_event,
);
}
} else {
let layers = &mut workspace.appearance_panel; let layers = &mut workspace.appearance_panel;
let overlay = &mut workspace.overlay; let overlay = &mut workspace.overlay;
let board = workspace.interactor.invoker().autorouter().board(); let board = workspace.interactor.invoker().autorouter().board();

View File

@ -61,12 +61,31 @@ impl Workspace {
}) })
} }
pub fn update_state_for_event(
&mut self,
tr: &Translator,
error_dialog: &mut ErrorDialog,
interactive_input: &InteractiveInput,
interactive_event: InteractiveEvent,
) -> ControlFlow<()> {
match self
.interactor
.update_for_event(interactive_input, interactive_event)
{
ControlFlow::Continue(()) => ControlFlow::Continue(()),
ControlFlow::Break(Ok(())) => ControlFlow::Break(()),
ControlFlow::Break(Err(err)) => {
error_dialog.push_error("tr-module-invoker", format!("{}", err));
ControlFlow::Break(())
}
}
}
pub fn update_state( pub fn update_state(
&mut self, &mut self,
tr: &Translator, tr: &Translator,
error_dialog: &mut ErrorDialog, error_dialog: &mut ErrorDialog,
interactive_input: &InteractiveInput, interactive_input: &InteractiveInput,
interactive_event: Option<InteractiveEvent>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
if let Ok(data) = self.history_channel.1.try_recv() { if let Ok(data) = self.history_channel.1.try_recv() {
match data { match data {
@ -92,7 +111,7 @@ impl Workspace {
} }
} }
match self.interactor.update(interactive_input, interactive_event) { match self.interactor.update(interactive_input) {
ControlFlow::Continue(()) => ControlFlow::Continue(()), ControlFlow::Continue(()) => ControlFlow::Continue(()),
ControlFlow::Break(Ok(())) => ControlFlow::Break(()), ControlFlow::Break(Ok(())) => ControlFlow::Break(()),
ControlFlow::Break(Err(err)) => { ControlFlow::Break(Err(err)) => {

View File

@ -79,20 +79,19 @@ impl<M: AccessMesadata> Interactor<M> {
self.invoker.replay(history); self.invoker.replay(history);
} }
/// Update the currently running execution or activity /// Update the currently running execution or activity, given an event
pub fn update( pub fn update_for_event(
&mut self, &mut self,
interactive_input: &InteractiveInput, interactive_input: &InteractiveInput,
interactive_event: Option<InteractiveEvent>, interactive_event: InteractiveEvent,
) -> ControlFlow<Result<(), ActivityError>> { ) -> ControlFlow<Result<(), ActivityError>> {
if let Some(ref mut activity) = self.activity { if let Some(ref mut activity) = self.activity {
if let Some(event) = interactive_event {
match activity.on_event( match activity.on_event(
&mut ActivityContext { &mut ActivityContext {
interactive_input, interactive_input,
invoker: &mut self.invoker, invoker: &mut self.invoker,
}, },
event, interactive_event,
) { ) {
Ok(()) => ControlFlow::Continue(()), Ok(()) => ControlFlow::Continue(()),
Err(err) => { Err(err) => {
@ -101,6 +100,16 @@ impl<M: AccessMesadata> Interactor<M> {
} }
} }
} else { } else {
ControlFlow::Break(Ok(()))
}
}
/// Update the currently running execution or activity
pub fn update(
&mut self,
interactive_input: &InteractiveInput,
) -> ControlFlow<Result<(), ActivityError>> {
if let Some(ref mut activity) = self.activity {
match activity.step(&mut ActivityContext { match activity.step(&mut ActivityContext {
interactive_input, interactive_input,
invoker: &mut self.invoker, invoker: &mut self.invoker,
@ -115,7 +124,6 @@ impl<M: AccessMesadata> Interactor<M> {
ControlFlow::Break(Err(err)) ControlFlow::Break(Err(err))
} }
} }
}
} else { } else {
ControlFlow::Break(Ok(())) ControlFlow::Break(Ok(()))
} }