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,6 +138,27 @@ impl Viewport {
if let Some(workspace) = maybe_workspace {
let latest_point = point! {x: latest_pos.x as f64, y: -latest_pos.y as f64};
// 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 += 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: point! {x: latest_pos.x as f64, y: latest_pos.y as f64},
dt,
},
) {
break;
}
}
if !workspace.interactor.maybe_activity().as_ref().map_or(true, |activity| {
matches!(activity.maybe_status(), Some(ControlFlow::Break(..)))
}) {
@ -149,27 +170,10 @@ impl Viewport {
} 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(
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 {
@ -178,32 +182,9 @@ impl Viewport {
dt,
},
interactive_event,
) {
break;
}
);
}
} else {
// 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 += 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: point! {x: latest_pos.x as f64, y: latest_pos.y as f64},
dt,
},
None,
) {
break;
}
}
let layers = &mut workspace.appearance_panel;
let overlay = &mut workspace.overlay;
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(
&mut self,
tr: &Translator,
error_dialog: &mut ErrorDialog,
interactive_input: &InteractiveInput,
interactive_event: Option<InteractiveEvent>,
) -> ControlFlow<()> {
if let Ok(data) = self.history_channel.1.try_recv() {
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::Break(Ok(())) => ControlFlow::Break(()),
ControlFlow::Break(Err(err)) => {

View File

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