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 { 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};
// 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| { if !workspace.interactor.maybe_activity().as_ref().map_or(true, |activity| {
matches!(activity.maybe_status(), Some(ControlFlow::Break(..))) matches!(activity.maybe_status(), Some(ControlFlow::Break(..)))
}) { }) {
@ -149,27 +170,10 @@ impl Viewport {
} else { } else {
None None
}; };
if let Some(event) = interactive_event { if let Some(interactive_event) = interactive_event {
log::debug!("got {:?}", event); let dt = ctx.input(|i| i.stable_dt);
} let active_layer = workspace.appearance_panel.active_layer;
// Advances the app's state by the delta time `dt`. May call let _ = workspace.update_state_for_event(
// `.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, tr,
error_dialog, error_dialog,
&InteractiveInput { &InteractiveInput {
@ -178,32 +182,9 @@ impl Viewport {
dt, dt,
}, },
interactive_event, interactive_event,
) { );
break;
}
} }
} else { } 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 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,41 +79,49 @@ impl<M: AccessMesadata> Interactor<M> {
self.invoker.replay(history); 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 /// Update the currently running execution or activity
pub fn update( pub fn update(
&mut self, &mut self,
interactive_input: &InteractiveInput, interactive_input: &InteractiveInput,
interactive_event: Option<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.step(&mut ActivityContext {
match activity.on_event( interactive_input,
&mut ActivityContext { invoker: &mut self.invoker,
interactive_input, }) {
invoker: &mut self.invoker, Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()),
}, Ok(ControlFlow::Break(_msg)) => {
event, self.activity = None;
) { ControlFlow::Break(Ok(()))
Ok(()) => ControlFlow::Continue(()),
Err(err) => {
self.activity = None;
ControlFlow::Break(Err(err.into()))
}
} }
} else { Err(err) => {
match activity.step(&mut ActivityContext { self.activity = None;
interactive_input, ControlFlow::Break(Err(err))
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))
}
} }
} }
} else { } else {