forked from 1b-agent/opencadstudio-upstream
feat(plugin): wire on_cursor_move and preview wires through IPC plugin runner
This commit is contained in:
1 parent
5eda52626e
commit
358103c1e4
4 files changed
+88
No files matched your search
@@ -23,6 +23,7 @@ use crate::ribbon::owned::{OwnedPluginManifest, OwnedRibbonGroup};
|
|||||||
|
|
||||||
pub use acadrust::xdata::{ExtendedDataRecord, XDataValue};
|
pub use acadrust::xdata::{ExtendedDataRecord, XDataValue};
|
||||||
pub use acadrust::{CadDocument, EntityType, Handle};
|
pub use acadrust::{CadDocument, EntityType, Handle};
|
||||||
|
pub use crate::host::PreviewWire;
|
||||||
|
|
||||||
/// Events the host forwards to an active plugin `InteractiveCommand`.
|
/// Events the host forwards to an active plugin `InteractiveCommand`.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -83,6 +84,11 @@ pub enum HostRequest {
|
|||||||
},
|
},
|
||||||
/// V7: release an interactive command after completion or cancellation.
|
/// V7: release an interactive command after completion or cancellation.
|
||||||
DropInteractive { command_id: u64 },
|
DropInteractive { command_id: u64 },
|
||||||
|
/// V7: cursor move preview update during an interactive command.
|
||||||
|
CursorMove {
|
||||||
|
command_id: u64,
|
||||||
|
pt: [f64; 3],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Responses the plugin runner sends back for `HostRequest`.
|
/// Responses the plugin runner sends back for `HostRequest`.
|
||||||
@@ -95,6 +101,7 @@ pub enum HostResponse {
|
|||||||
Manifest(OwnedPluginManifest),
|
Manifest(OwnedPluginManifest),
|
||||||
Error(String),
|
Error(String),
|
||||||
CodeExecutionResult(crate::host::ExecutionResult),
|
CodeExecutionResult(crate::host::ExecutionResult),
|
||||||
|
PreviewWires(Vec<PreviewWire>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Requests the plugin runner sends to the host.
|
/// Requests the plugin runner sends to the host.
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ fn base_max_floor(base: Duration, kind: &'static str) -> Duration {
|
|||||||
"GetManifest" | "GetRibbon" => Duration::from_secs(5),
|
"GetManifest" | "GetRibbon" => Duration::from_secs(5),
|
||||||
"Dispatch" => Duration::from_secs(10),
|
"Dispatch" => Duration::from_secs(10),
|
||||||
"InteractiveEvent" | "GetPrompt" | "NeedsEntityPick" => Duration::from_secs(2),
|
"InteractiveEvent" | "GetPrompt" | "NeedsEntityPick" => Duration::from_secs(2),
|
||||||
|
"CursorMove" => Duration::from_millis(500),
|
||||||
"ExecuteCode" => execute_code_timeout(),
|
"ExecuteCode" => execute_code_timeout(),
|
||||||
_ => Duration::from_secs(1),
|
_ => Duration::from_secs(1),
|
||||||
};
|
};
|
||||||
@@ -238,6 +239,7 @@ pub(crate) fn request_kind(req: &HostRequest) -> &'static str {
|
|||||||
HostRequest::NeedsEntityPick { .. } => "NeedsEntityPick",
|
HostRequest::NeedsEntityPick { .. } => "NeedsEntityPick",
|
||||||
HostRequest::ExecuteCode { .. } => "ExecuteCode",
|
HostRequest::ExecuteCode { .. } => "ExecuteCode",
|
||||||
HostRequest::DropInteractive { .. } => "DropInteractive",
|
HostRequest::DropInteractive { .. } => "DropInteractive",
|
||||||
|
HostRequest::CursorMove { .. } => "CursorMove",
|
||||||
HostRequest::Shutdown => "Shutdown",
|
HostRequest::Shutdown => "Shutdown",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -681,6 +683,35 @@ impl PluginProcess {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ask the plugin process for real-time preview wires for the cursor position.
|
||||||
|
pub fn on_cursor_move(
|
||||||
|
&self,
|
||||||
|
command_id: u64,
|
||||||
|
pt: [f64; 3],
|
||||||
|
) -> Result<Vec<crate::host::PreviewWire>, PluginError> {
|
||||||
|
if let Some(v4) = &self.v4 {
|
||||||
|
let resp = v4.call(
|
||||||
|
&mut NullHost,
|
||||||
|
HostRequest::CursorMove { command_id, pt },
|
||||||
|
&mut |_| {},
|
||||||
|
)?;
|
||||||
|
match resp {
|
||||||
|
HostResponse::PreviewWires(w) => Ok(w),
|
||||||
|
other => Err(PluginError::UnexpectedResponse(Box::new(other))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.call_simple(
|
||||||
|
HostRequest::CursorMove { command_id, pt },
|
||||||
|
"CursorMove",
|
||||||
|
"cursor_move",
|
||||||
|
|resp| match resp {
|
||||||
|
HostResponse::PreviewWires(w) => Ok(w),
|
||||||
|
other => Err(Box::new(other)),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_alive(&self) -> bool {
|
pub fn is_alive(&self) -> bool {
|
||||||
if let Some(v4) = &self.v4 {
|
if let Some(v4) = &self.v4 {
|
||||||
return v4.is_alive();
|
return v4.is_alive();
|
||||||
|
|||||||
@@ -243,6 +243,21 @@ fn handle_host_request(
|
|||||||
None => HostResponse::Error(format!("unknown interactive command {command_id}")),
|
None => HostResponse::Error(format!("unknown interactive command {command_id}")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HostRequest::CursorMove { command_id, pt } => {
|
||||||
|
let result = {
|
||||||
|
let mut registry = interactive.borrow_mut();
|
||||||
|
registry.get_mut(&command_id).map(|cmd| {
|
||||||
|
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||||
|
cmd.on_cursor_move(pt)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
match result {
|
||||||
|
Some(Ok(wires)) => HostResponse::PreviewWires(wires),
|
||||||
|
Some(Err(_)) => HostResponse::PreviewWires(Vec::new()),
|
||||||
|
None => HostResponse::PreviewWires(Vec::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
HostRequest::ExecuteCode { .. } => {
|
HostRequest::ExecuteCode { .. } => {
|
||||||
HostResponse::Error("ExecuteCode requires V4 protocol".to_string())
|
HostResponse::Error("ExecuteCode requires V4 protocol".to_string())
|
||||||
}
|
}
|
||||||
@@ -366,6 +381,21 @@ fn handle_host_request_v4(
|
|||||||
None => Some(HostResponse::Error(format!("unknown interactive command {command_id}"))),
|
None => Some(HostResponse::Error(format!("unknown interactive command {command_id}"))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
HostRequest::CursorMove { command_id, pt } => {
|
||||||
|
let result = {
|
||||||
|
let mut registry = interactive.borrow_mut();
|
||||||
|
registry.get_mut(&command_id).map(|cmd| {
|
||||||
|
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||||
|
cmd.on_cursor_move(pt)
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
};
|
||||||
|
match result {
|
||||||
|
Some(Ok(wires)) => Some(HostResponse::PreviewWires(wires)),
|
||||||
|
Some(Err(_)) => Some(HostResponse::PreviewWires(Vec::new())),
|
||||||
|
None => Some(HostResponse::PreviewWires(Vec::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
HostRequest::ExecuteCode {
|
HostRequest::ExecuteCode {
|
||||||
command_id,
|
command_id,
|
||||||
source,
|
source,
|
||||||
|
|||||||
@@ -2842,6 +2842,26 @@ impl crate::command::CadCommand for PluginProcessInteractiveAdapter {
|
|||||||
self.refresh();
|
self.refresh();
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn on_preview_wires(&mut self, pt: glam::DVec3) -> Vec<crate::scene::model::wire_model::WireModel> {
|
||||||
|
let raw_wires = self
|
||||||
|
.process
|
||||||
|
.on_cursor_move(self.command_id, [pt.x as f64, pt.y as f64, pt.z as f64])
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
raw_wires
|
||||||
|
.into_iter()
|
||||||
|
.filter(|w| w.points.len() >= 2)
|
||||||
|
.map(|w| {
|
||||||
|
let color = w.color.unwrap_or(crate::scene::model::wire_model::WireModel::CYAN);
|
||||||
|
crate::scene::model::wire_model::WireModel::solid_f64(
|
||||||
|
"rubber_band".into(),
|
||||||
|
w.points,
|
||||||
|
color,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn plugin_step_to_result(step: ocs_plugin_api::host::CommandStep) -> crate::command::CmdResult {
|
fn plugin_step_to_result(step: ocs_plugin_api::host::CommandStep) -> crate::command::CmdResult {
|
||||||
|
|||||||
Reference in new issue
Block a user