From 7e6a3d4ca55f366f199506e5e9fbae111ce598c6 Mon Sep 17 00:00:00 2001 From: Charlotte McElwain Date: Fri, 17 Jan 2025 23:49:18 -0800 Subject: [PATCH] Add dynamic menu support. --- Cargo.lock | 8 +++ Cargo.toml | 1 + CrashAutoSave.NewProject.1.toe | 0 plugins/chop/monome-grid/src/lib.rs | 3 +- plugins/dat/dynamic_menu/Cargo.toml | 15 +++++ plugins/dat/dynamic_menu/src/lib.rs | 91 +++++++++++++++++++++++++++++ td-rs-base/src/RustBase.h | 4 ++ td-rs-base/src/RustPy.h | 2 - td-rs-base/src/cxx.rs | 2 + td-rs-base/src/lib.rs | 30 ++++++++++ td-rs-base/src/param.rs | 27 ++++++++- td-rs-base/src/py.rs | 7 +-- td-rs-base/src/sop.rs | 8 ++- td-rs-chop/src/RustChopPlugin.h | 12 ++++ td-rs-chop/src/cxx.rs | 11 +++- td-rs-chop/src/lib.rs | 7 +++ td-rs-dat/src/RustDatPlugin.h | 16 ++++- td-rs-dat/src/cxx.rs | 11 +++- td-rs-dat/src/lib.rs | 8 +++ td-rs-sop/src/RustSopPlugin.h | 13 +++++ td-rs-sop/src/cxx.rs | 11 +++- td-rs-sop/src/lib.rs | 8 +++ td-rs-top/src/RustTopPlugin.h | 12 ++++ td-rs-top/src/cxx.rs | 11 +++- td-rs-top/src/lib.rs | 8 +++ td-rs-xtask/src/lib.rs | 2 +- td-rs-xtask/src/windows/mod.rs | 8 ++- 27 files changed, 315 insertions(+), 21 deletions(-) create mode 100644 CrashAutoSave.NewProject.1.toe create mode 100644 plugins/dat/dynamic_menu/Cargo.toml create mode 100644 plugins/dat/dynamic_menu/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index ee54594..1c62d96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1253,6 +1253,14 @@ dependencies = [ "syn 2.0.92", ] +[[package]] +name = "dynamic-menu" +version = "0.1.0" +dependencies = [ + "td-rs-dat", + "td-rs-derive", +] + [[package]] name = "either" version = "1.13.0" diff --git a/Cargo.toml b/Cargo.toml index 401acdb..38d9225 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ "plugins/chop/python", "plugins/chop/wasm", "plugins/dat/filter", + "plugins/dat/dynamic_menu", "plugins/sop/generator-sop", "plugins/top/cpu-memory-top", "plugins/top/stable-diffusion", diff --git a/CrashAutoSave.NewProject.1.toe b/CrashAutoSave.NewProject.1.toe new file mode 100644 index 0000000..e69de29 diff --git a/plugins/chop/monome-grid/src/lib.rs b/plugins/chop/monome-grid/src/lib.rs index 17513c6..7430dab 100644 --- a/plugins/chop/monome-grid/src/lib.rs +++ b/plugins/chop/monome-grid/src/lib.rs @@ -1,4 +1,5 @@ use monome::{KeyDirection, Monome, MonomeDevice, MonomeEvent}; +use td_rs_chop::cxx::OP_Inputs; use td_rs_chop::*; use td_rs_derive::{Param, Params}; @@ -70,7 +71,7 @@ impl Chop for MonomeGrid { if let Some(ref mut device) = &mut self.device { while let Some(event) = device.poll() { match event { - MonomeEvent::GridKey { x, y, direction, } => { + MonomeEvent::GridKey { x, y, direction } => { let index = (y * 16 + x) as usize; if self.params.hold { if matches!(direction, KeyDirection::Down) { diff --git a/plugins/dat/dynamic_menu/Cargo.toml b/plugins/dat/dynamic_menu/Cargo.toml new file mode 100644 index 0000000..65ff2da --- /dev/null +++ b/plugins/dat/dynamic_menu/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "dynamic-menu" +version = "0.1.0" +edition = "2021" + +[package.metadata.td-rs] +type = "dat" + +[lib] +name = "dynamic_menu" +crate-type = ["staticlib"] + +[dependencies] +td-rs-dat = { path = "../../../td-rs-dat" } +td-rs-derive = { path = "../../../td-rs-derive" } \ No newline at end of file diff --git a/plugins/dat/dynamic_menu/src/lib.rs b/plugins/dat/dynamic_menu/src/lib.rs new file mode 100644 index 0000000..72bd862 --- /dev/null +++ b/plugins/dat/dynamic_menu/src/lib.rs @@ -0,0 +1,91 @@ +use td_rs_dat::chop::ChopInput; +use td_rs_dat::*; +use td_rs_derive::{Param, Params}; + +#[derive(Params, Default, Clone, Debug)] +struct DynamicMenuDatParams { + #[param(label = "Menu")] + menu: DynamicMenuParam, +} + +/// Struct representing our DAT's state +pub struct DynamicMenuDat { + params: DynamicMenuDatParams, +} + +impl OpNew for DynamicMenuDat { + fn new(_info: NodeInfo) -> Self { + Self { + params: Default::default(), + } + } +} + +impl OpInfo for DynamicMenuDat { + const OPERATOR_TYPE: &'static str = "Dynamicmenu"; + const OPERATOR_LABEL: &'static str = "Dynamic Menu"; + const MIN_INPUTS: usize = 1; + // This Dat takes no input + const MAX_INPUTS: usize = 1; +} + +impl Op for DynamicMenuDat { + fn params_mut(&mut self) -> Option> { + Some(Box::new(&mut self.params)) + } +} + +impl Dat for DynamicMenuDat { + fn general_info(&self, _inputs: &OperatorInputs) -> DatGeneralInfo { + DatGeneralInfo { + cook_every_frame: false, + cook_every_frame_if_asked: false, + } + } + + fn execute(&mut self, output: DatOutput, inputs: &OperatorInputs) { + if let Some(input) = inputs.input(0) { + match input.dat_type() { + DatType::Text => { + if let Some(output_text) = &self.params.menu.0 { + output + .text() + .set_text(&format!("Selected: {}", output_text)); + } else { + output.text().set_text(""); + } + } + _ => self.set_warning("Input must be a text DAT"), + } + } + } + + fn build_dynamic_menu( + &mut self, + inputs: &OperatorInputs, + menu_info: &mut DynamicMenuInfo, + ) { + if menu_info.param_name() == "Menu" { + if let Some(input) = inputs.input(0) { + match input.dat_type() { + DatType::Text => { + let text = input.text(); + let labels = text + .split('\n') + .map(|s| s.to_string()) + .collect::>(); + for label in labels { + let name = label.replace(" ", ""); + menu_info.add_menu_entry(&name, &label); + } + } + _ => self.set_warning("Input must be a text DAT"), + } + } + } + } +} + +impl DynamicMenuDat {} + +dat_plugin!(DynamicMenuDat); diff --git a/td-rs-base/src/RustBase.h b/td-rs-base/src/RustBase.h index 9a130ec..1927d43 100644 --- a/td-rs-base/src/RustBase.h +++ b/td-rs-base/src/RustBase.h @@ -27,4 +27,8 @@ void releaseDownloadResult(TD::OP_SmartRef &result) { result.release(); } +const char* getBuildDynamicMenuInfoNames(TD::OP_BuildDynamicMenuInfo &info) { + return info.name; +} + #endif // TD_RS_RUSTBASE_H diff --git a/td-rs-base/src/RustPy.h b/td-rs-base/src/RustPy.h index 172f116..1752096 100644 --- a/td-rs-base/src/RustPy.h +++ b/td-rs-base/src/RustPy.h @@ -16,14 +16,12 @@ TD::PY_Context* getPyContext(TD::PY_Struct *pyStruct) { void setPyInfo(TD::OP_CustomOPInfo &opInfo, void *pymethods, size_t size, void *pygetsets, size_t getsetsize) { if (size == 0) { - std::cout << "No methods" << std::endl; opInfo.pythonMethods = nullptr; } else { opInfo.pythonMethods = static_cast(pymethods); } if (getsetsize == 0) { - std::cout << "No getsets" << std::endl; opInfo.pythonGetSets = nullptr; } else { opInfo.pythonGetSets = static_cast(pygetsets); diff --git a/td-rs-base/src/cxx.rs b/td-rs-base/src/cxx.rs index ab82dc7..47fb9aa 100644 --- a/td-rs-base/src/cxx.rs +++ b/td-rs-base/src/cxx.rs @@ -36,6 +36,7 @@ include_cpp! { generate!("TD::OP_SmartRef") generate_pod!("TD::OP_TextureDesc") generate_pod!("TD::OP_TexDim") + generate!("TD::OP_BuildDynamicMenuInfo") // util fns generate!("setString") @@ -44,6 +45,7 @@ include_cpp! { generate!("getDownloadData") generate!("getDownloadTextureDesc") generate!("releaseDownloadResult") + generate!("getBuildDynamicMenuInfoNames") // Custom ops generate!("TD::OP_CustomOPInstance") diff --git a/td-rs-base/src/lib.rs b/td-rs-base/src/lib.rs index 1a30fb8..592ff24 100644 --- a/td-rs-base/src/lib.rs +++ b/td-rs-base/src/lib.rs @@ -1,6 +1,7 @@ #![feature(associated_type_defaults)] #![feature(min_specialization)] +use crate::cxx::OP_Inputs; pub use param::*; #[cfg(feature = "python")] pub use py::*; @@ -243,6 +244,30 @@ where } } +pub struct DynamicMenuInfo<'cook> { + pub menu_info: Pin<&'cook mut cxx::OP_BuildDynamicMenuInfo>, +} + +impl<'cook> DynamicMenuInfo<'cook> { + pub fn new(menu_info: Pin<&'cook mut cxx::OP_BuildDynamicMenuInfo>) -> Self { + Self { menu_info } + } + + pub fn param_name(&mut self) -> &str { + let name = cxx::getBuildDynamicMenuInfoNames(self.menu_info.as_mut()); + unsafe { ffi::CStr::from_ptr(name).to_str().unwrap() } + } + + pub fn add_menu_entry(&mut self, name: &str, label: &str) -> bool { + unsafe { + self.menu_info.as_mut().addMenuEntry( + ffi::CString::new(name).unwrap().into_raw(), + ffi::CString::new(label).unwrap().into_raw(), + ) + } + } +} + /// Parameter inputs to an operator. pub struct ParamInputs<'cook> { inputs: &'cook crate::cxx::OP_Inputs, @@ -276,6 +301,11 @@ impl<'cook> ParamInputs<'cook> { let res = self .inputs .getParString(ffi::CString::new(name).unwrap().into_raw()); + + if res.is_null() { + return ""; + } + ffi::CStr::from_ptr(res).to_str().unwrap() } } diff --git a/td-rs-base/src/param.rs b/td-rs-base/src/param.rs index 0ca6d7d..941fbc6 100644 --- a/td-rs-base/src/param.rs +++ b/td-rs-base/src/param.rs @@ -111,7 +111,9 @@ pub struct ParameterManager<'cook> { impl<'cook> ParameterManager<'cook> { /// Create a new parameter manager. Should not be called by /// users. - pub fn new(manager: Pin<&'cook mut crate::cxx::OP_ParameterManager>) -> ParameterManager<'cook> { + pub fn new( + manager: Pin<&'cook mut crate::cxx::OP_ParameterManager>, + ) -> ParameterManager<'cook> { Self { manager } } @@ -301,6 +303,12 @@ impl<'cook> ParameterManager<'cook> { let param = param.into(); self.manager.as_mut().appendWH(¶m); } + + /// Append a dynamic menu parameter. + pub fn append_dynamic_menu(&mut self, param: StringParameter) { + let param = param.into(); + self.manager.as_mut().appendDynamicStringMenu(¶m); + } } /// Options for creating parameters in derive macro. @@ -704,3 +712,20 @@ impl Param for Color { *self = (r, g, b, a).into(); } } + +#[derive(Default, Debug, Clone)] +pub struct DynamicMenuParam(pub Option); + +impl Param for DynamicMenuParam { + fn register(&self, options: ParamOptions, parameter_manager: &mut ParameterManager) { + let param = options.into(); + parameter_manager.append_dynamic_menu(param); + } + + fn update(&mut self, name: &str, inputs: &ParamInputs) { + let name = inputs.get_string(name); + if !name.is_empty() { + self.0 = Some(name.to_string()); + } + } +} diff --git a/td-rs-base/src/py.rs b/td-rs-base/src/py.rs index 2520d46..ff920f8 100644 --- a/td-rs-base/src/py.rs +++ b/td-rs-base/src/py.rs @@ -1,9 +1,7 @@ -use pyo3::ffi::PyGetSetDef; use crate::Op; +use pyo3::ffi::PyGetSetDef; -pub trait PyOp : Op { - -} +pub trait PyOp: Op {} pub trait PyGetSets { fn get_get_sets() -> &'static [pyo3::ffi::PyGetSetDef]; @@ -32,7 +30,6 @@ pub(crate) unsafe fn py_op_info( let m_len = methods.len(); let m_arr = methods.as_ptr() as *mut autocxx::prelude::c_void; let get_sets = T::get_get_sets(); - println!("get_sets: {:?}", get_sets); let gs_len = get_sets.len(); let gs_arr = get_sets.as_ptr() as *mut autocxx::prelude::c_void; crate::cxx::setPyInfo(op_info, m_arr, m_len, gs_arr, gs_len); diff --git a/td-rs-base/src/sop.rs b/td-rs-base/src/sop.rs index 0200077..7741f6b 100644 --- a/td-rs-base/src/sop.rs +++ b/td-rs-base/src/sop.rs @@ -80,7 +80,9 @@ impl SopInput { let custom_attribute = &*custom_attribute; let name = custom_attribute._base.name; - let name = std::ffi::CStr::from_ptr(name).to_string_lossy().into_owned(); + let name = std::ffi::CStr::from_ptr(name) + .to_string_lossy() + .into_owned(); let num_components = custom_attribute._base.numComponents as usize; let attr_type = &custom_attribute._base.attribType; let attr_type = attr_type.into(); @@ -109,7 +111,9 @@ impl SopInput { } } - pub fn custom_attributes(&self) -> impl Iterator + '_ { + pub fn custom_attributes( + &self, + ) -> impl Iterator + '_ { let num_custom_attributes = self.num_custom_attributes(); (0..num_custom_attributes).map(move |i| self.custom_attribute(i)) } diff --git a/td-rs-chop/src/RustChopPlugin.h b/td-rs-chop/src/RustChopPlugin.h index bc76c64..c72e81a 100644 --- a/td-rs-chop/src/RustChopPlugin.h +++ b/td-rs-chop/src/RustChopPlugin.h @@ -103,6 +103,15 @@ class ChopPlugin : public CHOP_CPlusPlusBase { }; virtual void pulsePressed(const char *name) {} + + virtual void buildDynamicMenu(const OP_Inputs *inputs, + OP_BuildDynamicMenuInfo *info, + void *reserved1) { + this->buildDynamicMenu(*inputs, *info); + } + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) {} }; class RustChopPlugin : public ChopPlugin { @@ -138,6 +147,9 @@ class RustChopPlugin : public ChopPlugin { virtual void setupParameters(OP_ParameterManager &manager) = 0; virtual void pulsePressed(const char *name) = 0; + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) = 0; }; #endif //TD_RS_RUSTCHOP_H diff --git a/td-rs-chop/src/cxx.rs b/td-rs-chop/src/cxx.rs index ae7b288..02da45d 100644 --- a/td-rs-chop/src/cxx.rs +++ b/td-rs-chop/src/cxx.rs @@ -11,7 +11,7 @@ use autocxx::subclass::*; pub use ffi::TD::*; pub use ffi::*; pub use td_rs_base::cxx::*; -use td_rs_base::{NodeInfo, OperatorInputs, ParameterManager}; +use td_rs_base::{DynamicMenuInfo, NodeInfo, OperatorInputs, ParameterManager}; use crate::{Chop, ChopOutput}; @@ -25,6 +25,7 @@ include_cpp! { extern_cpp_type!("TD::OP_InfoCHOPChan", td_rs_base::cxx::OP_InfoCHOPChan) extern_cpp_type!("TD::OP_Inputs", td_rs_base::cxx::OP_Inputs) extern_cpp_type!("TD::OP_CustomOPInfo", td_rs_base::cxx::OP_CustomOPInfo) + extern_cpp_type!("TD::OP_BuildDynamicMenuInfo", td_rs_base::cxx::OP_BuildDynamicMenuInfo) pod!("TD::OP_CustomOPInfo") generate_pod!("TD::CHOP_PluginInfo") generate_pod!("TD::CHOP_GeneralInfo") @@ -236,4 +237,12 @@ impl RustChopPlugin_methods for RustChopPluginImpl { self.inner .pulse_pressed(std::ffi::CStr::from_ptr(name).to_str().unwrap()); } + + fn buildDynamicMenu(&mut self, inputs: &OP_Inputs, info: Pin<&mut OP_BuildDynamicMenuInfo>) { + #[cfg(feature = "tracing")] + let _span = { tracing_base::trace_span!("buildDynamicMenu").entered() }; + let input = OperatorInputs::new(inputs); + let mut info = DynamicMenuInfo::new(info); + self.inner.build_dynamic_menu(&input, &mut info); + } } diff --git a/td-rs-chop/src/lib.rs b/td-rs-chop/src/lib.rs index a2a3681..ff2dcca 100644 --- a/td-rs-chop/src/lib.rs +++ b/td-rs-chop/src/lib.rs @@ -120,6 +120,13 @@ pub trait Chop: Op { fn output_info(&self, _input: &OperatorInputs) -> Option { None } + + fn build_dynamic_menu( + &self, + inputs: &OperatorInputs, + menu_info: &mut DynamicMenuInfo, + ) { + } } #[macro_export] diff --git a/td-rs-dat/src/RustDatPlugin.h b/td-rs-dat/src/RustDatPlugin.h index fefdaee..2b46931 100644 --- a/td-rs-dat/src/RustDatPlugin.h +++ b/td-rs-dat/src/RustDatPlugin.h @@ -89,15 +89,24 @@ class DatPlugin : public DAT_CPlusPlusBase { }; virtual void pulsePressed(const char *name) {} + + virtual void buildDynamicMenu(const OP_Inputs *inputs, + OP_BuildDynamicMenuInfo *info, + void *reserved1) { + this->buildDynamicMenu(*inputs, *info); + } + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) {} }; class RustDatPlugin : public DatPlugin { public: virtual ~RustDatPlugin(){}; - virtual void* inner() const = 0; + virtual void *inner() const = 0; - virtual void* innerMut() = 0; + virtual void *innerMut() = 0; virtual void getGeneralInfo(DAT_GeneralInfo &info, const OP_Inputs &inputs) = 0; @@ -123,6 +132,9 @@ class RustDatPlugin : public DatPlugin { virtual void setupParameters(OP_ParameterManager &manager) = 0; virtual void pulsePressed(const char *name) = 0; + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) = 0; }; #endif // TD_RS_RUSTDAT_H diff --git a/td-rs-dat/src/cxx.rs b/td-rs-dat/src/cxx.rs index 4aaac1f..d9b9ef8 100644 --- a/td-rs-dat/src/cxx.rs +++ b/td-rs-dat/src/cxx.rs @@ -8,7 +8,7 @@ use autocxx::subclass::*; use std::ffi::CString; use std::pin::Pin; -use td_rs_base::{param::ParameterManager, NodeInfo, OperatorInputs}; +use td_rs_base::{param::ParameterManager, DynamicMenuInfo, NodeInfo, OperatorInputs}; include_cpp! { #include "DAT_CPlusPlusBase.h" @@ -20,6 +20,7 @@ include_cpp! { extern_cpp_type!("TD::OP_InfoCHOPChan", td_rs_base::cxx::OP_InfoCHOPChan) extern_cpp_type!("TD::OP_Inputs", td_rs_base::cxx::OP_Inputs) extern_cpp_type!("TD::OP_CustomOPInfo", td_rs_base::cxx::OP_CustomOPInfo) + extern_cpp_type!("TD::OP_BuildDynamicMenuInfo", td_rs_base::cxx::OP_BuildDynamicMenuInfo) pod!("TD::OP_CustomOPInfo") generate!("TD::DAT_Output") generate_pod!("TD::DAT_GeneralInfo") @@ -201,4 +202,12 @@ impl RustDatPlugin_methods for RustDatPluginImpl { self.inner .pulse_pressed(std::ffi::CStr::from_ptr(name).to_str().unwrap()); } + + fn buildDynamicMenu(&mut self, inputs: &OP_Inputs, info: Pin<&mut OP_BuildDynamicMenuInfo>) { + #[cfg(feature = "tracing")] + let _span = { tracing_base::trace_span!("buildDynamicMenu").entered() }; + let input = OperatorInputs::new(inputs); + let mut info = DynamicMenuInfo::new(info); + self.inner.build_dynamic_menu(&input, &mut info); + } } diff --git a/td-rs-dat/src/lib.rs b/td-rs-dat/src/lib.rs index 54f9f5a..3ecedfd 100644 --- a/td-rs-dat/src/lib.rs +++ b/td-rs-dat/src/lib.rs @@ -2,6 +2,7 @@ use std::ffi::CString; use std::ops::{Index, IndexMut}; use std::pin::Pin; +use td_rs_base::chop::ChopInput; pub use td_rs_base::dat::*; pub use td_rs_base::param::OperatorParams; pub use td_rs_base::*; @@ -237,6 +238,13 @@ pub trait Dat: Op { fn execute(&mut self, _output: DatOutput, _input: &OperatorInputs) { // Do nothing by default. } + + fn build_dynamic_menu( + &mut self, + inputs: &OperatorInputs, + menu_info: &mut DynamicMenuInfo, + ) { + } } #[macro_export] diff --git a/td-rs-sop/src/RustSopPlugin.h b/td-rs-sop/src/RustSopPlugin.h index d291e65..650e80d 100644 --- a/td-rs-sop/src/RustSopPlugin.h +++ b/td-rs-sop/src/RustSopPlugin.h @@ -100,6 +100,15 @@ class SopPlugin : public SOP_CPlusPlusBase { }; virtual void pulsePressed(const char *name) {} + + virtual void buildDynamicMenu(const OP_Inputs *inputs, + OP_BuildDynamicMenuInfo *info, + void *reserved1) { + this->buildDynamicMenu(*inputs, *info); + } + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) {} }; class RustSopPlugin : public SopPlugin { @@ -133,6 +142,10 @@ class RustSopPlugin : public SopPlugin { virtual void setupParameters(OP_ParameterManager &manager) = 0; virtual void pulsePressed(const char *name) = 0; + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) = 0; + }; #endif //TD_RS_RUSTSOP_H diff --git a/td-rs-sop/src/cxx.rs b/td-rs-sop/src/cxx.rs index 979894c..91a8d41 100644 --- a/td-rs-sop/src/cxx.rs +++ b/td-rs-sop/src/cxx.rs @@ -8,7 +8,7 @@ use autocxx::subclass::*; use std::ffi::CString; use std::pin::Pin; -use td_rs_base::{param::ParameterManager, NodeInfo, OperatorInputs}; +use td_rs_base::{param::ParameterManager, DynamicMenuInfo, NodeInfo, OperatorInputs}; include_cpp! { #include "SOP_CPlusPlusBase.h" @@ -31,6 +31,7 @@ include_cpp! { extern_cpp_type!("TD::SOP_CustomAttribData", td_rs_base::cxx::SOP_CustomAttribData) extern_cpp_type!("TD::SOP_CustomAttribInfo", td_rs_base::cxx::SOP_CustomAttribInfo) extern_cpp_type!("TD::OP_CustomOPInfo", td_rs_base::cxx::OP_CustomOPInfo) + extern_cpp_type!("TD::OP_BuildDynamicMenuInfo", td_rs_base::cxx::OP_BuildDynamicMenuInfo) pod!("TD::OP_CustomOPInfo") generate_pod!("TD::SOP_GroupType") generate_pod!("TD::SOP_Winding") @@ -220,4 +221,12 @@ impl RustSopPlugin_methods for RustSopPluginImpl { self.inner .pulse_pressed(std::ffi::CStr::from_ptr(name).to_str().unwrap()); } + + fn buildDynamicMenu(&mut self, inputs: &OP_Inputs, info: Pin<&mut OP_BuildDynamicMenuInfo>) { + #[cfg(feature = "tracing")] + let _span = { tracing_base::trace_span!("buildDynamicMenu").entered() }; + let input = OperatorInputs::new(inputs); + let mut info = DynamicMenuInfo::new(info); + self.inner.build_dynamic_menu(&input, &mut info); + } } diff --git a/td-rs-sop/src/lib.rs b/td-rs-sop/src/lib.rs index 993cdf0..c1a8fb2 100644 --- a/td-rs-sop/src/lib.rs +++ b/td-rs-sop/src/lib.rs @@ -2,6 +2,7 @@ use crate::cxx::{SOP_CustomAttribData, VBOBufferMode, Vector}; use std::pin::Pin; +use td_rs_base::chop::ChopInput; pub use td_rs_base::sop::*; pub use td_rs_base::*; @@ -684,6 +685,13 @@ pub trait Sop: Op { fn execute_vbo(&mut self, _output: SopVboOutput, _inputs: &OperatorInputs) { // Do nothing by default. } + + fn build_dynamic_menu( + &mut self, + inputs: &OperatorInputs, + menu_info: &mut DynamicMenuInfo, + ) { + } } #[macro_export] diff --git a/td-rs-top/src/RustTopPlugin.h b/td-rs-top/src/RustTopPlugin.h index d0f91d3..59b5cbf 100644 --- a/td-rs-top/src/RustTopPlugin.h +++ b/td-rs-top/src/RustTopPlugin.h @@ -95,6 +95,15 @@ class TopPlugin : public TOP_CPlusPlusBase { }; virtual void pulsePressed(const char *name) {} + + virtual void buildDynamicMenu(const OP_Inputs *inputs, + OP_BuildDynamicMenuInfo *info, + void *reserved1) { + this->buildDynamicMenu(*inputs, *info); + } + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) {} }; class RustTopPlugin : public TopPlugin { @@ -129,6 +138,9 @@ class RustTopPlugin : public TopPlugin { virtual void setupParameters(OP_ParameterManager &manager) = 0; virtual void pulsePressed(const char *name) = 0; + + virtual void buildDynamicMenu(const OP_Inputs &inputs, + OP_BuildDynamicMenuInfo &info) = 0; }; #endif //TD_RS_RUSTTOPPLUGIN_H diff --git a/td-rs-top/src/cxx.rs b/td-rs-top/src/cxx.rs index 2e3e96e..3a97d29 100644 --- a/td-rs-top/src/cxx.rs +++ b/td-rs-top/src/cxx.rs @@ -5,7 +5,7 @@ use autocxx::prelude::*; use autocxx::subclass::*; use std::ffi::CString; use std::pin::Pin; -use td_rs_base::{param::ParameterManager, NodeInfo, OperatorInputs}; +use td_rs_base::{param::ParameterManager, DynamicMenuInfo, NodeInfo, OperatorInputs}; use crate::{TopContext, TopOutput}; // use crate::mode::cpu::{TopCpuInput, TopCpuOutput}; @@ -29,6 +29,7 @@ include_cpp! { pod!("TD::OP_TextureDesc") extern_cpp_type!("TD::OP_CPUMemPixelType", td_rs_base::cxx::OP_CPUMemPixelType) extern_cpp_type!("TD::OP_CUDAArrayInfo", td_rs_base::cxx::OP_CUDAArrayInfo) + extern_cpp_type!("TD::OP_BuildDynamicMenuInfo", td_rs_base::cxx::OP_BuildDynamicMenuInfo) generate_pod!("TD::TOP_UploadInfo") generate_pod!("TD::TOP_GeneralInfo") generate_pod!("TD::TOP_PluginInfo") @@ -229,4 +230,12 @@ impl RustTopPlugin_methods for RustTopPluginImpl { self.inner .pulse_pressed(std::ffi::CStr::from_ptr(name).to_str().unwrap()); } + + fn buildDynamicMenu(&mut self, inputs: &OP_Inputs, info: Pin<&mut OP_BuildDynamicMenuInfo>) { + #[cfg(feature = "tracing")] + let _span = { tracing_base::trace_span!("buildDynamicMenu").entered() }; + let input = OperatorInputs::new(inputs); + let mut info = DynamicMenuInfo::new(info); + self.inner.build_dynamic_menu(&input, &mut info); + } } diff --git a/td-rs-top/src/lib.rs b/td-rs-top/src/lib.rs index 6f04041..da6e9c1 100644 --- a/td-rs-top/src/lib.rs +++ b/td-rs-top/src/lib.rs @@ -3,6 +3,7 @@ pub mod cxx; pub use ::cxx::UniquePtr; use std::pin::Pin; +use td_rs_base::chop::ChopInput; pub use td_rs_base::top::*; pub use td_rs_base::*; @@ -161,6 +162,13 @@ pub trait Top: Op { } fn execute(&mut self, _output: TopOutput, _input: &OperatorInputs) {} + + fn build_dynamic_menu( + &mut self, + inputs: &OperatorInputs, + menu_info: &mut DynamicMenuInfo, + ) { + } } #[macro_export] diff --git a/td-rs-xtask/src/lib.rs b/td-rs-xtask/src/lib.rs index 63f0d30..eacd03e 100644 --- a/td-rs-xtask/src/lib.rs +++ b/td-rs-xtask/src/lib.rs @@ -2,9 +2,9 @@ mod config; #[cfg(target_os = "macos")] mod macos; mod metadata; +mod util; #[cfg(target_os = "windows")] mod windows; -mod util; #[cfg(target_os = "macos")] use crate::macos::{build_plugin, install_plugin}; diff --git a/td-rs-xtask/src/windows/mod.rs b/td-rs-xtask/src/windows/mod.rs index 3f4b82d..603ea4c 100644 --- a/td-rs-xtask/src/windows/mod.rs +++ b/td-rs-xtask/src/windows/mod.rs @@ -1,12 +1,12 @@ use crate::config::Config; use crate::metadata::PluginType; +use crate::util::ToTitleCase; use crate::{build, PLUGIN_HOME}; use anyhow::Context; use fs_extra::dir::CopyOptions; use std::io::Read; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use crate::util::ToTitleCase; pub(crate) fn install_plugin( config: &Config, @@ -93,8 +93,10 @@ fn move_plugin(plugin: &str, plugin_type: &PluginType) -> anyhow::Result<()> { let plugin_target_path = plugin_target_path(plugin); std::fs::create_dir_all(&plugin_target_path.parent().unwrap()) .context("Could not create plugin directory")?; - std::fs::copy(&plugin_build_path, &plugin_target_path) - .context(format!("Could not move plugin to target directory {:?}->{:?}", plugin_build_path, plugin_target_path))?; + std::fs::copy(&plugin_build_path, &plugin_target_path).context(format!( + "Could not move plugin to target directory {:?}->{:?}", + plugin_build_path, plugin_target_path + ))?; Ok(()) }