mirror of https://codeberg.org/topola/topola.git
refactor(interactor,egui): pass pointer position down to interactions
This commit is contained in:
parent
1638a289ed
commit
e62bac69ef
|
|
@ -1,3 +1,4 @@
|
||||||
|
use geo::point;
|
||||||
use std::{
|
use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
io,
|
io,
|
||||||
|
|
@ -6,7 +7,10 @@ use std::{
|
||||||
};
|
};
|
||||||
use unic_langid::{langid, LanguageIdentifier};
|
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::{
|
use crate::{
|
||||||
config::Config, error_dialog::ErrorDialog, menu_bar::MenuBar, status_bar::StatusBar,
|
config::Config, error_dialog::ErrorDialog, menu_bar::MenuBar, status_bar::StatusBar,
|
||||||
|
|
@ -62,19 +66,19 @@ impl App {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
fn advance_state_by_dt(&mut self, dt: f32) {
|
fn advance_state_by_dt(&mut self, interactive_input: &InteractiveInput) {
|
||||||
self.update_counter += dt;
|
self.update_counter += interactive_input.dt;
|
||||||
|
|
||||||
while self.update_counter >= self.menu_bar.frame_timestep {
|
while self.update_counter >= self.menu_bar.frame_timestep {
|
||||||
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;
|
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() {
|
if let Ok(data) = self.content_channel.1.try_recv() {
|
||||||
match data {
|
match data {
|
||||||
Ok(design) => match Workspace::new(design, &self.translator) {
|
Ok(design) => match Workspace::new(design, &self.translator) {
|
||||||
|
|
@ -112,7 +116,11 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(workspace) = &mut self.maybe_workspace {
|
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(())
|
ControlFlow::Break(())
|
||||||
|
|
@ -135,7 +143,13 @@ impl eframe::App for App {
|
||||||
self.maybe_workspace.as_mut(),
|
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(
|
self.status_bar.update(
|
||||||
ctx,
|
ctx,
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,7 @@ use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions,
|
execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions,
|
||||||
},
|
},
|
||||||
interactor::{
|
interactor::activity::{ActivityContext, ActivityStepperWithStatus, InteractiveInput},
|
||||||
activity::{ActivityContext, ActivityStepperWithStatus},
|
|
||||||
interaction::InteractionContext,
|
|
||||||
},
|
|
||||||
router::RouterOptions,
|
router::RouterOptions,
|
||||||
specctra::design::{LoadingError as SpecctraLoadingError, SpecctraDesign},
|
specctra::design::{LoadingError as SpecctraLoadingError, SpecctraDesign},
|
||||||
stepper::Abort,
|
stepper::Abort,
|
||||||
|
|
@ -277,7 +274,7 @@ impl MenuBar {
|
||||||
} else if actions.edit.redo.consume_key_triggered(ctx, ui) {
|
} else if actions.edit.redo.consume_key_triggered(ctx, ui) {
|
||||||
workspace.interactor.redo();
|
workspace.interactor.redo();
|
||||||
} else if actions.edit.abort.consume_key_triggered(ctx, ui) {
|
} 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(
|
} else if actions.place.place_via.consume_key_enabled(
|
||||||
ctx,
|
ctx,
|
||||||
ui,
|
ui,
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@ use std::{
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{history::History, invoker::Invoker, Autorouter},
|
autorouter::{history::History, invoker::Invoker, Autorouter},
|
||||||
interactor::{
|
interactor::{
|
||||||
activity::{ActivityContext, ActivityStepperWithStatus},
|
activity::{ActivityContext, ActivityStepperWithStatus, InteractiveInput},
|
||||||
interaction::InteractionContext,
|
|
||||||
Interactor,
|
Interactor,
|
||||||
},
|
},
|
||||||
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
|
specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata},
|
||||||
|
|
@ -59,6 +58,7 @@ impl Workspace {
|
||||||
&mut self,
|
&mut self,
|
||||||
tr: &Translator,
|
tr: &Translator,
|
||||||
error_dialog: &mut ErrorDialog,
|
error_dialog: &mut ErrorDialog,
|
||||||
|
interactive_input: &InteractiveInput,
|
||||||
) -> 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 {
|
||||||
|
|
@ -84,7 +84,7 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.interactor.update() {
|
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)) => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
|
use geo::Point;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
@ -12,13 +13,18 @@ use crate::{
|
||||||
board::mesadata::AccessMesadata,
|
board::mesadata::AccessMesadata,
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
interactor::interaction::{InteractionContext, InteractionError, InteractionStepper},
|
interactor::interaction::{InteractionError, InteractionStepper},
|
||||||
router::{navcord::NavcordStepper, navmesh::Navmesh},
|
router::{navcord::NavcordStepper, navmesh::Navmesh},
|
||||||
stepper::{Abort, Step},
|
stepper::{Abort, Step},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub struct InteractiveInput {
|
||||||
|
pub pointer_pos: Point,
|
||||||
|
pub dt: f32,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ActivityContext<'a, M: AccessMesadata> {
|
pub struct ActivityContext<'a, M: AccessMesadata> {
|
||||||
pub interaction: InteractionContext,
|
pub interactive_input: &'a InteractiveInput,
|
||||||
pub invoker: &'a mut Invoker<M>,
|
pub invoker: &'a mut Invoker<M>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,9 +49,7 @@ impl<M: AccessMesadata> Step<ActivityContext<'_, M>, String> for ActivityStepper
|
||||||
context: &mut ActivityContext<M>,
|
context: &mut ActivityContext<M>,
|
||||||
) -> Result<ControlFlow<String>, ActivityError> {
|
) -> Result<ControlFlow<String>, ActivityError> {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(interaction) => {
|
ActivityStepper::Interaction(interaction) => Ok(interaction.step(context)?),
|
||||||
Ok(interaction.step(&mut context.interaction)?)
|
|
||||||
}
|
|
||||||
ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?),
|
ActivityStepper::Execution(execution) => Ok(execution.step(context.invoker)?),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -54,9 +58,7 @@ impl<M: AccessMesadata> Step<ActivityContext<'_, M>, String> for ActivityStepper
|
||||||
impl<M: AccessMesadata> Abort<ActivityContext<'_, M>> for ActivityStepper {
|
impl<M: AccessMesadata> Abort<ActivityContext<'_, M>> for ActivityStepper {
|
||||||
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(interaction) => {
|
ActivityStepper::Interaction(interaction) => interaction.abort(context),
|
||||||
interaction.abort(&mut context.interaction)
|
|
||||||
}
|
|
||||||
ActivityStepper::Execution(execution) => {
|
ActivityStepper::Execution(execution) => {
|
||||||
execution.finish(context.invoker);
|
execution.finish(context.invoker);
|
||||||
} // TODO.
|
} // TODO.
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,14 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
|
autorouter::invoker::{GetGhosts, GetMaybeNavcord, GetMaybeNavmesh, GetObstacles},
|
||||||
|
board::mesadata::AccessMesadata,
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navcord::NavcordStepper, navmesh::Navmesh},
|
router::{navcord::NavcordStepper, navmesh::Navmesh},
|
||||||
stepper::{Abort, Step},
|
stepper::{Abort, Step},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct InteractionContext {
|
use super::activity::ActivityContext;
|
||||||
// Empty for now.
|
|
||||||
// For example, this will contain mouse pointer position.
|
|
||||||
// (we will need an additional struct to hold a reference to a `Board<...>`)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug, Clone)]
|
#[derive(Error, Debug, Clone)]
|
||||||
pub enum InteractionError {
|
pub enum InteractionError {
|
||||||
|
|
@ -29,19 +26,19 @@ pub enum InteractionStepper {
|
||||||
// - interactively moving a footprint.
|
// - interactively moving a footprint.
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Step<InteractionContext, String> for InteractionStepper {
|
impl<'a, M: AccessMesadata> Step<ActivityContext<'a, M>, String> for InteractionStepper {
|
||||||
type Error = InteractionError;
|
type Error = InteractionError;
|
||||||
|
|
||||||
fn step(
|
fn step(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut InteractionContext,
|
context: &mut ActivityContext<M>,
|
||||||
) -> Result<ControlFlow<String>, InteractionError> {
|
) -> Result<ControlFlow<String>, InteractionError> {
|
||||||
Ok(ControlFlow::Break(String::from("")))
|
Ok(ControlFlow::Break(String::from("")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Abort<InteractionContext> for InteractionStepper {
|
impl<'a, M: AccessMesadata> Abort<ActivityContext<'a, M>> for InteractionStepper {
|
||||||
fn abort(&mut self, context: &mut InteractionContext) {
|
fn abort(&mut self, context: &mut ActivityContext<M>) {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,8 @@ use crate::{
|
||||||
Autorouter,
|
Autorouter,
|
||||||
},
|
},
|
||||||
board::{mesadata::AccessMesadata, Board},
|
board::{mesadata::AccessMesadata, Board},
|
||||||
interactor::{
|
interactor::activity::{
|
||||||
activity::{ActivityContext, ActivityError, ActivityStepperWithStatus},
|
ActivityContext, ActivityError, ActivityStepperWithStatus, InteractiveInput,
|
||||||
interaction::InteractionContext,
|
|
||||||
},
|
},
|
||||||
stepper::{Abort, Step},
|
stepper::{Abort, Step},
|
||||||
};
|
};
|
||||||
|
|
@ -51,8 +50,11 @@ impl<M: AccessMesadata> Interactor<M> {
|
||||||
|
|
||||||
pub fn abort(&mut self) {
|
pub fn abort(&mut self) {
|
||||||
if let Some(ref mut activity) = self.activity {
|
if let Some(ref mut activity) = self.activity {
|
||||||
activity.abort(&mut ActivityContext {
|
activity.abort(&mut ActivityContext::<M> {
|
||||||
interaction: InteractionContext {},
|
interactive_input: &InteractiveInput {
|
||||||
|
pointer_pos: [0.0, 0.0].into(),
|
||||||
|
dt: 0.0,
|
||||||
|
},
|
||||||
invoker: &mut self.invoker,
|
invoker: &mut self.invoker,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -62,10 +64,13 @@ impl<M: AccessMesadata> Interactor<M> {
|
||||||
self.invoker.replay(history);
|
self.invoker.replay(history);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) -> ControlFlow<Result<(), ActivityError>> {
|
pub fn update(
|
||||||
|
&mut self,
|
||||||
|
interactive_input: &InteractiveInput,
|
||||||
|
) -> ControlFlow<Result<(), ActivityError>> {
|
||||||
if let Some(ref mut activity) = self.activity {
|
if let Some(ref mut activity) = self.activity {
|
||||||
return match activity.step(&mut ActivityContext {
|
return match activity.step(&mut ActivityContext {
|
||||||
interaction: InteractionContext {},
|
interactive_input,
|
||||||
invoker: &mut self.invoker,
|
invoker: &mut self.invoker,
|
||||||
}) {
|
}) {
|
||||||
Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()),
|
Ok(ControlFlow::Continue(())) => ControlFlow::Continue(()),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue