aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2025-12-27 00:52:04 +0000
committers-ol <s+removethis@s-ol.nu>2025-12-27 01:13:52 +0000
commit5f4427c127a862e886f88cbcd35854fd78b10ac5 (patch)
treefc0c3fc9ef8dae310e9733201c27bb2d5bb8ab99 /src
parentdockerize (diff)
downloadnodetoy-5f4427c127a862e886f88cbcd35854fd78b10ac5.tar.gz
nodetoy-5f4427c127a862e886f88cbcd35854fd78b10ac5.zip
auto-recompile
Diffstat (limited to 'src')
-rw-r--r--src/library.rs21
-rw-r--r--src/main.rs116
2 files changed, 100 insertions, 37 deletions
diff --git a/src/library.rs b/src/library.rs
index ba03dd6..111f365 100644
--- a/src/library.rs
+++ b/src/library.rs
@@ -478,7 +478,7 @@ impl<T: ScalarValue> Value for T {
}
trait ValueEditor: Value {
- fn show_editor(&mut self, ui: &mut egui::Ui);
+ fn show_editor(&mut self, ui: &mut egui::Ui) -> egui::Response;
}
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
@@ -536,9 +536,9 @@ where
Constant<T>: ScalarValue<Raw = T>,
T: fmt::Display,
{
- fn show_editor(&mut self, ui: &mut egui::Ui) {
+ fn show_editor(&mut self, ui: &mut egui::Ui) -> egui::Response {
ui.label("value");
- ui.add(Self::make_widget(&mut self.0));
+ ui.add(Self::make_widget(&mut self.0))
}
}
@@ -555,16 +555,19 @@ where
Constant<T>: ScalarValue<Raw = T>,
T: fmt::Display,
{
- fn show_editor(&mut self, ui: &mut egui::Ui) {
+ fn show_editor(&mut self, ui: &mut egui::Ui) -> egui::Response {
const LABELS: [&str; 4] = ["x", "y", "z", "w"];
+ let mut response = ui.response();
ui.vertical(|ui| {
- for i in 0..self.0.len() {
+ for (val, label) in self.0.iter_mut().zip(LABELS) {
ui.horizontal(|ui| {
- ui.label(LABELS[i]);
- ui.add(Constant::<T>::make_widget(&mut self.0[i]));
+ ui.label(label);
+ response |= ui.add(Constant::<T>::make_widget(val));
});
}
});
+
+ response
}
}
@@ -614,8 +617,8 @@ where
writeln!(f, "{out_typ} {out_name} = {};", self)
}
- fn show_body(&mut self, ui: &mut egui::Ui) {
- self.show_editor(ui);
+ fn show_body(&mut self, ui: &mut egui::Ui) -> egui::Response {
+ self.show_editor(ui)
}
}
diff --git a/src/main.rs b/src/main.rs
index 3213501..13096b2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -138,7 +138,9 @@ trait ConcreteNode {
f: &mut dyn fmt::Write,
) -> fmt::Result;
- fn show_body(&mut self, _ui: &mut egui::Ui) {}
+ fn show_body(&mut self, ui: &mut egui::Ui) -> egui::Response {
+ ui.response()
+ }
}
impl TypeSignature {
@@ -199,11 +201,11 @@ impl DemoNode {
) -> fmt::Result {
let signature = self.get_node_signature(node, snarl);
- let inputs: Vec<String> = (0..self.inputs())
+ let inputs: Result<Vec<String>, fmt::Error> = (0..self.inputs())
.map(
|input| match &*snarl.in_pin(InPinId { node, input }).remotes {
- [] => "?".to_owned(),
- [pin] => DemoNode::compile_output(*pin),
+ [] => Err(fmt::Error),
+ [pin] => Ok(DemoNode::compile_output(*pin)),
_ => unreachable!("cannot connect to multiple inputs"),
},
)
@@ -212,7 +214,7 @@ impl DemoNode {
.map(|output| DemoNode::compile_output(OutPinId { node, output }))
.collect();
- snarl[node].compile(signature, inputs, outputs, f)
+ snarl[node].compile(signature, inputs?, outputs, f)
}
pub fn get_node_signature(&self, node: NodeId, snarl: &Snarl<DemoNode>) -> TypeSignature {
@@ -230,15 +232,17 @@ impl DemoNode {
impl fmt::Display for DemoNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
- DemoNode::Constant(x) => fmt::Display::fmt(x, f),
- DemoNode::Input(x) => fmt::Display::fmt(x, f),
- DemoNode::Builtin(x) => fmt::Display::fmt(x, f),
- DemoNode::Output(x) => fmt::Display::fmt(x, f),
+ Self::Constant(x) => fmt::Display::fmt(x, f),
+ Self::Input(x) => fmt::Display::fmt(x, f),
+ Self::Builtin(x) => fmt::Display::fmt(x, f),
+ Self::Output(x) => fmt::Display::fmt(x, f),
}
}
}
-struct DemoViewer;
+struct DemoViewer {
+ dirty: bool,
+}
impl DemoViewer {
fn get_in_type(pin: InPinId, snarl: &Snarl<DemoNode>) -> Option<Type> {
@@ -295,6 +299,20 @@ impl SnarlViewer<DemoNode> for DemoViewer {
}
snarl.connect(from.id, to.id);
+ self.dirty = true;
+ }
+
+ fn disconnect(&mut self, from: &OutPin, to: &InPin, snarl: &mut Snarl<DemoNode>) {
+ snarl.disconnect(from.id, to.id);
+ self.dirty = true;
+ }
+
+ fn drop_outputs(&mut self, pin: &OutPin, snarl: &mut Snarl<DemoNode>) {
+ snarl.drop_outputs(pin.id);
+ }
+
+ fn drop_inputs(&mut self, pin: &InPin, snarl: &mut Snarl<DemoNode>) {
+ snarl.drop_inputs(pin.id);
}
fn title(&mut self, node: &DemoNode) -> String {
@@ -349,7 +367,9 @@ impl SnarlViewer<DemoNode> for DemoViewer {
ui: &mut Ui,
snarl: &mut Snarl<DemoNode>,
) {
- snarl[node].show_body(ui);
+ if snarl[node].show_body(ui).changed() {
+ self.dirty = true;
+ }
}
fn has_graph_menu(&mut self, _pos: egui::Pos2, _snarl: &mut Snarl<DemoNode>) -> bool {
@@ -359,9 +379,34 @@ impl SnarlViewer<DemoNode> for DemoViewer {
fn show_graph_menu(&mut self, pos: egui::Pos2, ui: &mut Ui, snarl: &mut Snarl<DemoNode>) {
ui.label("Add node");
- for node in DemoNode::all() {
+ ui.menu_button("Constants", |ui| {
+ for node in library::AnyConstant::all() {
+ if ui.button(format!("{node}")).clicked() {
+ snarl.insert_node(pos, DemoNode::from(node));
+ ui.close();
+ }
+ }
+ });
+ ui.menu_button("Inputs", |ui| {
+ for node in library::Input::all() {
+ if ui.button(format!("{node}")).clicked() {
+ snarl.insert_node(pos, DemoNode::from(node));
+ ui.close();
+ }
+ }
+ });
+ ui.menu_button("Builtins", |ui| {
+ for node in library::BuiltinFunction::all() {
+ if ui.button(format!("{node}")).clicked() {
+ snarl.insert_node(pos, DemoNode::from(node));
+ ui.close();
+ }
+ }
+ });
+
+ for node in library::Output::all() {
if ui.button(format!("{node}")).clicked() {
- snarl.insert_node(pos, node);
+ snarl.insert_node(pos, DemoNode::from(node));
ui.close();
}
}
@@ -389,6 +434,7 @@ impl SnarlViewer<DemoNode> for DemoViewer {
pub struct DemoApp {
snarl: Snarl<DemoNode>,
+ viewer: DemoViewer,
preview: preview::Custom3d,
}
@@ -438,6 +484,7 @@ impl DemoApp {
DemoApp {
snarl,
+ viewer: DemoViewer { dirty: true },
preview: preview::Custom3d::new(cx).expect("Failed to init preview"),
}
}
@@ -467,29 +514,42 @@ impl App for DemoApp {
});
});
+ let mut shader: Option<String> = None;
+ egui::CentralPanel::default().show(ctx, |ui| {
+ let response = SnarlWidget::new()
+ .id(Id::new("snarl-demo"))
+ .style(default_style())
+ .show(&mut self.snarl, &mut self.viewer, ui);
+
+ let _ = response.changed();
+ if self.viewer.dirty {
+ self.viewer.dirty = false;
+ let mut buf = String::new();
+ match DemoViewer::compile(&self.snarl, &mut buf) {
+ Ok(()) => {
+ info!("{}", buf);
+ shader = Some(buf);
+ }
+ Err(x) => {
+ error!("Error compiling: {}", x);
+ }
+ }
+ }
+ });
+
egui::SidePanel::right("preview").show(ctx, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
egui::Frame::canvas(ui.style()).show(ui, |ui| {
- let shader = if ui.button("compile").clicked() {
- let mut buf = String::new();
- DemoViewer::compile(&self.snarl, &mut buf).expect("compilation");
- info!("{}", buf);
- Some(buf)
- } else {
- None
- };
+ // let shader = if self.viewer.dirty {
+ // self.viewer.dirty = false;
+ // } else {
+ // None
+ // };
self.preview.custom_painting(ui, shader);
});
});
});
-
- egui::CentralPanel::default().show(ctx, |ui| {
- SnarlWidget::new()
- .id(Id::new("snarl-demo"))
- .style(default_style())
- .show(&mut self.snarl, &mut DemoViewer, ui);
- });
}
fn save(&mut self, storage: &mut dyn eframe::Storage) {