diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index a782653..f7bccea 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -1,3 +1,4 @@ +use geo::point; use std::{ future::Future, io, @@ -6,7 +7,10 @@ use std::{ }; use unic_langid::{langid, LanguageIdentifier}; -use topola::specctra::design::{LoadingError as SpecctraLoadingError, SpecctraDesign}; +use topola::{ + interactor::activity::InteractiveInput, + specctra::design::{LoadingError as SpecctraLoadingError, SpecctraDesign}, +}; use crate::{ config::Config, error_dialog::ErrorDialog, menu_bar::MenuBar, status_bar::StatusBar, @@ -62,19 +66,19 @@ impl App { this } - fn advance_state_by_dt(&mut self, dt: f32) { - self.update_counter += dt; + fn advance_state_by_dt(&mut self, interactive_input: &InteractiveInput) { + self.update_counter += interactive_input.dt; while self.update_counter >= self.menu_bar.frame_timestep { self.update_counter -= self.menu_bar.frame_timestep; - if let ControlFlow::Break(()) = self.update_state() { + if let ControlFlow::Break(()) = self.update_state(interactive_input) { return; } } } - fn update_state(&mut self) -> ControlFlow<()> { + fn update_state(&mut self, interactive_input: &InteractiveInput) -> ControlFlow<()> { if let Ok(data) = self.content_channel.1.try_recv() { match data { Ok(design) => match Workspace::new(design, &self.translator) { @@ -112,7 +116,11 @@ impl App { } if let Some(workspace) = &mut self.maybe_workspace { - return workspace.update_state(&self.translator, &mut self.error_dialog); + return workspace.update_state( + &self.translator, + &mut self.error_dialog, + interactive_input, + ); } ControlFlow::Break(()) @@ -135,7 +143,13 @@ impl eframe::App for App { self.maybe_workspace.as_mut(), ); - self.advance_state_by_dt(ctx.input(|i| i.stable_dt)); + let pointer_pos = self.viewport.transform.inverse() + * ctx.input(|i| i.pointer.latest_pos().unwrap_or_default()); + + self.advance_state_by_dt(&InteractiveInput { + pointer_pos: point! {x: pointer_pos.x as f64, y: pointer_pos.y as f64}, + dt: ctx.input(|i| i.stable_dt), + }); self.status_bar.update( ctx, diff --git a/src/bin/topola-egui/menu_bar.rs b/src/bin/topola-egui/menu_bar.rs index b195642..ca63ba3 100644 --- a/src/bin/topola-egui/menu_bar.rs +++ b/src/bin/topola-egui/menu_bar.rs @@ -8,10 +8,7 @@ use topola::{ autorouter::{ execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions, }, - interactor::{ - activity::{ActivityContext, ActivityStepperWithStatus}, - interaction::InteractionContext, - }, + interactor::activity::{ActivityContext, ActivityStepperWithStatus, InteractiveInput}, router::RouterOptions, specctra::design::{LoadingError as SpecctraLoadingError, SpecctraDesign}, stepper::Abort, @@ -277,7 +274,7 @@ impl MenuBar { } else if actions.edit.redo.consume_key_triggered(ctx, ui) { workspace.interactor.redo(); } else if actions.edit.abort.consume_key_triggered(ctx, ui) { - workspace.interactor.abort() + workspace.interactor.abort(); } else if actions.place.place_via.consume_key_enabled( ctx, ui, diff --git a/src/bin/topola-egui/workspace.rs b/src/bin/topola-egui/workspace.rs index 5a07372..8d5e94d 100644 --- a/src/bin/topola-egui/workspace.rs +++ b/src/bin/topola-egui/workspace.rs @@ -6,8 +6,7 @@ use std::{ use topola::{ autorouter::{history::History, invoker::Invoker, Autorouter}, interactor::{ - activity::{ActivityContext, ActivityStepperWithStatus}, - interaction::InteractionContext, + activity::{ActivityContext, ActivityStepperWithStatus, InteractiveInput}, Interactor, }, specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata}, @@ -59,6 +58,7 @@ impl Workspace { &mut self, tr: &Translator, error_dialog: &mut ErrorDialog, + interactive_input: &InteractiveInput, ) -> ControlFlow<()> { if let Ok(data) = self.history_channel.1.try_recv() { match data { @@ -84,7 +84,7 @@ impl Workspace { } } - match self.interactor.update() { + match self.interactor.update(interactive_input) { ControlFlow::Continue(()) => ControlFlow::Continue(()), ControlFlow::Break(Ok(())) => ControlFlow::Break(()), ControlFlow::Break(Err(err)) => { diff --git a/src/interactor/activity.rs b/src/interactor/activity.rs index ad1b65b..fb72eed 100644 --- a/src/interactor/activity.rs +++ b/src/interactor/activity.rs @@ -1,5 +1,6 @@ use std::ops::ControlFlow; +use geo::Point; use thiserror::Error; use crate::{ @@ -12,13 +13,18 @@ use crate::{ board::mesadata::AccessMesadata, drawing::graph::PrimitiveIndex, geometry::primitive::PrimitiveShape, - interactor::interaction::{InteractionContext, InteractionError, InteractionStepper}, + interactor::interaction::{InteractionError, InteractionStepper}, router::{navcord::NavcordStepper, navmesh::Navmesh}, stepper::{Abort, Step}, }; +pub struct InteractiveInput { + pub pointer_pos: Point, + pub dt: f32, +} + pub struct ActivityContext<'a, M: AccessMesadata> { - pub interaction: InteractionContext, + pub interactive_input: &'a InteractiveInput, pub invoker: &'a mut Invoker, } @@ -43,9 +49,7 @@ impl Step, String> for ActivityStepper context: &mut ActivityContext, ) -> Result, ActivityError> { match self { - ActivityStepper::Interaction(interaction) => { - Ok(interaction.step(&mut context.interaction)?) - } + ActivityStepper::Interaction(interaction) => Ok(interaction.step(context)?), ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?), } } @@ -54,9 +58,7 @@ impl Step, String> for ActivityStepper impl Abort> for ActivityStepper { fn abort(&mut self, context: &mut ActivityContext) { match self { - ActivityStepper::Interaction(interaction) => { - interaction.abort(&mut context.interaction) - } + ActivityStepper::Interaction(interaction) => interaction.abort(context), ActivityStepper::Execution(execution) => { execution.finish(context.invoker); } // TODO. diff --git a/src/interactor/interaction.rs b/src/interactor/interaction.rs index 5e8d9dd..0ee5ce2 100644 --- a/src/interactor/interaction.rs +++ b/src/interactor/interaction.rs @@ -4,17 +4,14 @@ use thiserror::Error; use crate::{ autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles}, + board::mesadata::AccessMesadata, drawing::graph::PrimitiveIndex, geometry::primitive::PrimitiveShape, router::{navcord::NavcordStepper, navmesh::Navmesh}, stepper::{Abort, Step}, }; -pub struct InteractionContext { - // Empty for now. - // For example, this will contain mouse pointer position. - // (we will need an additional struct to hold a reference to a `Board<...>`) -} +use super::activity::ActivityContext; #[derive(Error, Debug, Clone)] pub enum InteractionError { @@ -29,19 +26,19 @@ pub enum InteractionStepper { // - interactively moving a footprint. } -impl Step for InteractionStepper { +impl<'a, M: AccessMesadata> Step, String> for InteractionStepper { type Error = InteractionError; fn step( &mut self, - context: &mut InteractionContext, + context: &mut ActivityContext, ) -> Result, InteractionError> { Ok(ControlFlow::Break(String::from(""))) } } -impl Abort for InteractionStepper { - fn abort(&mut self, context: &mut InteractionContext) { +impl<'a, M: AccessMesadata> Abort> for InteractionStepper { + fn abort(&mut self, context: &mut ActivityContext) { todo!(); } } diff --git a/src/interactor/interactor.rs b/src/interactor/interactor.rs index 2c0f372..6f04bfb 100644 --- a/src/interactor/interactor.rs +++ b/src/interactor/interactor.rs @@ -10,9 +10,8 @@ use crate::{ Autorouter, }, board::{mesadata::AccessMesadata, Board}, - interactor::{ - activity::{ActivityContext, ActivityError, ActivityStepperWithStatus}, - interaction::InteractionContext, + interactor::activity::{ + ActivityContext, ActivityError, ActivityStepperWithStatus, InteractiveInput, }, stepper::{Abort, Step}, }; @@ -51,8 +50,11 @@ impl Interactor { pub fn abort(&mut self) { if let Some(ref mut activity) = self.activity { - activity.abort(&mut ActivityContext { - interaction: InteractionContext {}, + activity.abort(&mut ActivityContext:: { + interactive_input: &InteractiveInput { + pointer_pos: [0.0, 0.0].into(), + dt: 0.0, + }, invoker: &mut self.invoker, }); } @@ -62,10 +64,13 @@ impl Interactor { self.invoker.replay(history); } - pub fn update(&mut self) -> ControlFlow> { + pub fn update( + &mut self, + interactive_input: &InteractiveInput, + ) -> ControlFlow> { if let Some(ref mut activity) = self.activity { return match activity.step(&mut ActivityContext { - interaction: InteractionContext {}, + interactive_input, invoker: &mut self.invoker, }) { Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()),