diff options
| author | s-ol <s+removethis@s-ol.nu> | 2025-12-27 10:52:42 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-12-27 10:52:42 +0000 |
| commit | 5fb707b4d872f3822dbb9a65c51408ca2ed0c39f (patch) | |
| tree | 43a7edd02841c1474c30f57b5c31ec100f7952f8 /src | |
| parent | auto-recompile (diff) | |
| download | nodetoy-5fb707b4d872f3822dbb9a65c51408ca2ed0c39f.tar.gz nodetoy-5fb707b4d872f3822dbb9a65c51408ca2ed0c39f.zip | |
NodeIndex type
Diffstat (limited to 'src')
| -rw-r--r-- | src/library.rs | 71 | ||||
| -rw-r--r-- | src/main.rs | 60 |
2 files changed, 76 insertions, 55 deletions
diff --git a/src/library.rs b/src/library.rs index 111f365..3402382 100644 --- a/src/library.rs +++ b/src/library.rs @@ -4,7 +4,8 @@ use serde::{Deserialize, Serialize}; use std::fmt; use crate::{ - ConcreteNode, Dimension::*, FloatPrecision::*, ScalarType::*, Type, Type::*, TypeSignature, + ConcreteNode, Dimension, Dimension::*, FloatPrecision::*, ScalarType, ScalarType::*, Type, + Type::*, TypeSignature, }; const GEN_F_TYPES: [Type; 4] = [ @@ -38,6 +39,26 @@ const _GEN_B_TYPES: [Type; 4] = [ Vector(Bool, D4), ]; +pub trait NodeIndex: Sized + fmt::Display { + const TITLE: &'static str; + + fn all() -> impl Iterator<Item = Self>; + + fn pick_node(ui: &mut egui::Ui) -> Option<Self> { + ui.menu_button(Self::TITLE, |ui| { + for node in Self::all() { + if ui.button(format!("{node}")).clicked() { + return Some(node); + } + } + + None + }) + .inner + .unwrap_or(None) + } +} + /// Helper trait for Nodes with fixed number of inputs and outputs trait FixedNode: fmt::Debug { const NI: usize; @@ -389,8 +410,10 @@ pub enum BuiltinFunction { Mix(Mix), } -impl BuiltinFunction { - pub fn all() -> impl Iterator<Item = Self> { +impl NodeIndex for BuiltinFunction { + const TITLE: &'static str = "Builtin Functions"; + + fn all() -> impl Iterator<Item = Self> { BinArithmetic::all() .map(Self::from) .chain(Thru1::all().map(Self::from)) @@ -451,10 +474,22 @@ impl FixedNode for Output { } } } -impl Output { - pub fn all() -> impl Iterator<Item = Self> { +impl NodeIndex for Output { + const TITLE: &'static str = "Output"; + + fn all() -> impl Iterator<Item = Self> { std::iter::once(Output) } + + fn pick_node(ui: &mut egui::Ui) -> Option<Self> { + for node in Self::all() { + if ui.button(format!("{node}")).clicked() { + return Some(node); + } + } + + None + } } impl fmt::Display for Output { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -468,7 +503,7 @@ trait Value: fmt::Display { trait ScalarValue: fmt::Display { type Raw; - const SCALAR_TYPE: crate::ScalarType; + const SCALAR_TYPE: ScalarType; fn make_widget(val: &mut Self::Raw) -> impl egui::Widget; } @@ -487,35 +522,35 @@ pub struct Constant<T>(T); // scalar implementations impl ScalarValue for Constant<f32> { type Raw = f32; - const SCALAR_TYPE: crate::ScalarType = Float(Single); + const SCALAR_TYPE: ScalarType = Float(Single); fn make_widget(val: &mut Self::Raw) -> impl egui::Widget { egui::DragValue::new(val).speed(0.1) } } impl ScalarValue for Constant<f64> { type Raw = f64; - const SCALAR_TYPE: crate::ScalarType = Float(Double); + const SCALAR_TYPE: ScalarType = Float(Double); fn make_widget(val: &mut Self::Raw) -> impl egui::Widget { egui::DragValue::new(val).speed(0.1) } } impl ScalarValue for Constant<i32> { type Raw = i32; - const SCALAR_TYPE: crate::ScalarType = Int; + const SCALAR_TYPE: ScalarType = Int; fn make_widget(val: &mut Self::Raw) -> impl egui::Widget { egui::DragValue::new(val) } } impl ScalarValue for Constant<u32> { type Raw = u32; - const SCALAR_TYPE: crate::ScalarType = UInt; + const SCALAR_TYPE: ScalarType = UInt; fn make_widget(val: &mut Self::Raw) -> impl egui::Widget { egui::DragValue::new(val) } } impl ScalarValue for Constant<bool> { type Raw = bool; - const SCALAR_TYPE: crate::ScalarType = Bool; + const SCALAR_TYPE: ScalarType = Bool; fn make_widget(val: &mut Self::Raw) -> impl egui::Widget { egui::Checkbox::without_text(val) } @@ -547,7 +582,7 @@ where Constant<T>: ScalarValue, T: fmt::Display, { - const TYPE: Type = Vector(Constant::<T>::SCALAR_TYPE, crate::Dimension::from(N)); + const TYPE: Type = Vector(Constant::<T>::SCALAR_TYPE, Dimension::from(N)); } impl<T, const N: usize> ValueEditor for Constant<[T; N]> @@ -647,8 +682,10 @@ pub enum AnyConstant { BVec4(Constant<[bool; 4]>), } -impl AnyConstant { - pub fn all() -> impl Iterator<Item = Self> { +impl NodeIndex for AnyConstant { + const TITLE: &'static str = "Constants"; + + fn all() -> impl Iterator<Item = Self> { [ Self::Float(Default::default()), Self::Vec2(Default::default()), @@ -741,8 +778,10 @@ impl ConcreteNode for Input { ) } } -impl Input { - pub fn all() -> impl Iterator<Item = Input> { +impl NodeIndex for Input { + const TITLE: &'static str = "Inputs"; + + fn all() -> impl Iterator<Item = Input> { [ Input::UV, // Input::Resolution, diff --git a/src/main.rs b/src/main.rs index 13096b2..a40fb21 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ use egui_snarl::{ ui::{NodeLayout, PinInfo, PinPlacement, SnarlStyle, SnarlViewer, SnarlWidget}, }; use enum_dispatch::enum_dispatch; +use library::NodeIndex; use log::*; use std::fmt; @@ -221,14 +222,30 @@ impl DemoNode { let connected = self.get_input_types(node, snarl); self.signature(&connected) } +} + +impl NodeIndex for DemoNode { + const TITLE: &'static str = ""; - pub fn all() -> impl Iterator<Item = Self> { + fn all() -> impl Iterator<Item = Self> { (library::AnyConstant::all().map(DemoNode::from)) .chain(library::Input::all().map(DemoNode::from)) .chain(library::Output::all().map(DemoNode::from)) .chain(library::BuiltinFunction::all().map(DemoNode::from)) } + + fn pick_node(ui: &mut egui::Ui) -> Option<Self> { + ui.label("Add node"); + + let a = library::AnyConstant::pick_node(ui).map(DemoNode::from); + let b = library::Input::pick_node(ui).map(DemoNode::from); + let c = library::Output::pick_node(ui).map(DemoNode::from); + let d = library::BuiltinFunction::pick_node(ui).map(DemoNode::from); + + a.or(b).or(c).or(d) + } } + impl fmt::Display for DemoNode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -377,38 +394,9 @@ 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"); - - 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, DemoNode::from(node)); - ui.close(); - } + if let Some(node) = DemoNode::pick_node(ui) { + snarl.insert_node(pos, node); + ui.close(); } } @@ -540,12 +528,6 @@ impl App for DemoApp { egui::SidePanel::right("preview").show(ctx, |ui| { egui::ScrollArea::vertical().show(ui, |ui| { egui::Frame::canvas(ui.style()).show(ui, |ui| { - // let shader = if self.viewer.dirty { - // self.viewer.dirty = false; - // } else { - // None - // }; - self.preview.custom_painting(ui, shader); }); }); |
