mirror of
https://github.com/Astatin3/rushroom.git
synced 2026-06-08 16:18:04 -06:00
Add node graph editor
This commit is contained in:
+3
-1
@@ -1,3 +1,5 @@
|
|||||||
|
.idea/
|
||||||
|
|
||||||
debug/
|
debug/
|
||||||
target/
|
target/
|
||||||
dist/
|
dist/
|
||||||
@@ -6,4 +8,4 @@ Cargo.lock
|
|||||||
|
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
*.pdb
|
*.pdb
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ eframe = { version = "0.29.1", features = [
|
|||||||
"persistence",]}
|
"persistence",]}
|
||||||
|
|
||||||
egui = { version = "0.29.1", features = ["callstack", "default", "log"] }
|
egui = { version = "0.29.1", features = ["callstack", "default", "log"] }
|
||||||
|
egui-snarl = {version = "0.5.0", features = ["serde"]}
|
||||||
glam = "0.29.2"
|
glam = "0.29.2"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
serde_json = "1.0.133"
|
serde_json = "1.0.133"
|
||||||
|
syn = "2.0.89"
|
||||||
typetag = "0.2.18"
|
typetag = "0.2.18"
|
||||||
|
|||||||
+78
-12
@@ -1,14 +1,80 @@
|
|||||||
{
|
[
|
||||||
"Properties": {
|
{
|
||||||
"mode": "Hidden",
|
"pane": {
|
||||||
"position": null,
|
"type": "BluePane"
|
||||||
"size": null,
|
},
|
||||||
"order": 1
|
"id": "BLUE",
|
||||||
|
"mode": "Left"
|
||||||
},
|
},
|
||||||
"Console": {
|
{
|
||||||
"mode": "Tiled",
|
"pane": {
|
||||||
"position": null,
|
"type": "GreenPane"
|
||||||
"size": null,
|
},
|
||||||
"order": 0
|
"id": "Green",
|
||||||
|
"mode": "Bottom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pane": {
|
||||||
|
"type": "PointRendererPane"
|
||||||
|
},
|
||||||
|
"id": "Point Cloud",
|
||||||
|
"mode": "Center"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pane": {
|
||||||
|
"type": "PipelinePane",
|
||||||
|
"snarl": {
|
||||||
|
"nodes": {
|
||||||
|
"0": {
|
||||||
|
"value": {
|
||||||
|
"type": "Node1"
|
||||||
|
},
|
||||||
|
"pos": {
|
||||||
|
"x": -56.0,
|
||||||
|
"y": -52.5
|
||||||
|
},
|
||||||
|
"open": true
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"value": {
|
||||||
|
"type": "Node1"
|
||||||
|
},
|
||||||
|
"pos": {
|
||||||
|
"x": -61.21814,
|
||||||
|
"y": 155.28181
|
||||||
|
},
|
||||||
|
"open": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wires": [
|
||||||
|
{
|
||||||
|
"out_pin": {
|
||||||
|
"node": 1,
|
||||||
|
"output": 0
|
||||||
|
},
|
||||||
|
"in_pin": {
|
||||||
|
"node": 0,
|
||||||
|
"input": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"out_pin": {
|
||||||
|
"node": 0,
|
||||||
|
"output": 0
|
||||||
|
},
|
||||||
|
"in_pin": {
|
||||||
|
"node": 1,
|
||||||
|
"input": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"select_rect_contained": null
|
||||||
|
},
|
||||||
|
"snarl_ui_id": 12028535709621507733
|
||||||
|
},
|
||||||
|
"id": "Pipeline Pane",
|
||||||
|
"mode": "Right"
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
// use egui::{accesskit::TextAlign, mutex::Mutex, Align2, Color32, FontId, Pos2, Stroke};
|
// use egui::{accesskit::TextAlign, mutex::Mutex, Align2, Color32, FontId, Pos2, Stroke};
|
||||||
// use egui_glow::glow;
|
// use egui_glow::glow;
|
||||||
|
|
||||||
use crate::panes::PaneManager;
|
use crate::pane_manager::PaneManager;
|
||||||
|
|
||||||
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
/// We derive Deserialize/Serialize so we can persist app state on shutdown.
|
||||||
// #[derive(serde::Deserialize, serde::Serialize)]
|
// #[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
#![warn(clippy::all, rust_2018_idioms)]
|
#![warn(clippy::all, rust_2018_idioms)]
|
||||||
mod app;
|
mod app;
|
||||||
mod point_cloud_renderer;
|
mod pane_manager;
|
||||||
mod panes;
|
mod panes;
|
||||||
|
mod nodes;
|
||||||
|
|
||||||
pub use app::App;
|
pub use app::App;
|
||||||
pub use panes::PaneManager;
|
pub use pane_manager::PaneManager;
|
||||||
// pub use point_cloud_renderer::PointCloudApp;
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod constants;
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
use egui::{Ui, Color32, Stroke};
|
use egui::{Ui, Color32, Stroke};
|
||||||
use eframe::egui_glow::glow;
|
use eframe::egui_glow::glow;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use crate::panes::*;
|
||||||
// use erased_serde::serialize_trait_object;
|
// use erased_serde::serialize_trait_object;
|
||||||
|
|
||||||
#[derive(serde::Deserialize, serde::Serialize, PartialEq)]
|
#[derive(serde::Deserialize, serde::Serialize, PartialEq)]
|
||||||
@@ -75,47 +76,6 @@ impl PaneState {
|
|||||||
// #[derive(serde::Deserialize, serde::Serialize)]
|
// #[derive(serde::Deserialize, serde::Serialize)]
|
||||||
// #[derive(serde::Deserialize, serde::Serialize)]
|
// #[derive(serde::Deserialize, serde::Serialize)]
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct BluePane {}
|
|
||||||
#[typetag::serde]
|
|
||||||
impl Pane for BluePane {
|
|
||||||
fn new() -> PaneState where Self: Sized {
|
|
||||||
let mut s = Self {};
|
|
||||||
PaneState {
|
|
||||||
id: s.name().to_string(),
|
|
||||||
mode: PaneMode::Left,
|
|
||||||
pane: Box::new(s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn init(&mut self, _pcc: &PsudoCreationContext){}
|
|
||||||
fn name(&mut self) -> &str {"BLUE"}
|
|
||||||
fn render(&mut self, ui: &mut Ui){
|
|
||||||
ui.painter().rect(ui.max_rect(), 0., Color32::BLUE, Stroke::NONE);
|
|
||||||
}
|
|
||||||
fn context_menu(&mut self, _ui: &mut Ui) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct GreenPane {}
|
|
||||||
#[typetag::serde]
|
|
||||||
impl Pane for GreenPane {
|
|
||||||
fn new() -> PaneState where Self: Sized {
|
|
||||||
let mut s = Self {};
|
|
||||||
PaneState {
|
|
||||||
id: s.name().to_string(),
|
|
||||||
mode: PaneMode::Bottom,
|
|
||||||
pane: Box::new(s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn init(&mut self, _cc: &PsudoCreationContext){}
|
|
||||||
fn name(&mut self) -> &str {"Green"}
|
|
||||||
fn render(&mut self, ui: &mut Ui){
|
|
||||||
ui.painter().rect(ui.max_rect(), 0., Color32::GREEN, Stroke::NONE);
|
|
||||||
}
|
|
||||||
fn context_menu(&mut self, _ui: &mut Ui) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PsudoCreationContext {
|
pub struct PsudoCreationContext {
|
||||||
pub gl: Option<Arc<glow::Context>>,
|
pub gl: Option<Arc<glow::Context>>,
|
||||||
}
|
}
|
||||||
@@ -131,9 +91,8 @@ impl PaneManager {
|
|||||||
// if let Some(cc) = cc {
|
// if let Some(cc) = cc {
|
||||||
|
|
||||||
let mut panes = vec![
|
let mut panes = vec![
|
||||||
BluePane::new(),
|
point_cloud_renderer::PointRendererPane::new(),
|
||||||
GreenPane::new(),
|
pipeline_editor::PipelinePane::new(),
|
||||||
crate::point_cloud_renderer::PointRendererPane::new(),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let pcc = PsudoCreationContext {
|
let pcc = PsudoCreationContext {
|
||||||
@@ -172,21 +131,6 @@ impl PaneManager {
|
|||||||
|
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
ui.menu_button(self.panes[i].id.clone(), |ui| {
|
ui.menu_button(self.panes[i].id.clone(), |ui| {
|
||||||
if ui.button("Hidden").clicked() {
|
|
||||||
self.panes[i].mode = PaneMode::Hidden;
|
|
||||||
}
|
|
||||||
if ui.button("Windowed").clicked() {
|
|
||||||
self.panes[i].mode = PaneMode::Windowed;
|
|
||||||
}
|
|
||||||
if ui.button("Left").clicked() {
|
|
||||||
self.panes[i].mode = PaneMode::Left;
|
|
||||||
}
|
|
||||||
if ui.button("Right").clicked() {
|
|
||||||
self.panes[i].mode = PaneMode::Right;
|
|
||||||
}
|
|
||||||
if ui.button("Bottom").clicked() {
|
|
||||||
self.panes[i].mode = PaneMode::Bottom;
|
|
||||||
}
|
|
||||||
if ui.button("Center").clicked() {
|
if ui.button("Center").clicked() {
|
||||||
for a in 0..len {
|
for a in 0..len {
|
||||||
let pane2: &mut PaneState = &mut self.panes[a];
|
let pane2: &mut PaneState = &mut self.panes[a];
|
||||||
@@ -195,6 +139,27 @@ impl PaneManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.panes[i].mode = PaneMode::Center;
|
self.panes[i].mode = PaneMode::Center;
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Windowed").clicked() {
|
||||||
|
self.panes[i].mode = PaneMode::Windowed;
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Left").clicked() {
|
||||||
|
self.panes[i].mode = PaneMode::Left;
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Right").clicked() {
|
||||||
|
self.panes[i].mode = PaneMode::Right;
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Bottom").clicked() {
|
||||||
|
self.panes[i].mode = PaneMode::Bottom;
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Hidden").clicked() {
|
||||||
|
self.panes[i].mode = PaneMode::Hidden;
|
||||||
|
ui.close_menu();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -203,12 +168,11 @@ impl PaneManager {
|
|||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
for i in 0..len {
|
for i in 0..len {
|
||||||
ui.menu_button(self.panes[i].id.clone(), |ui| {
|
if self.panes[i].mode != PaneMode::Hidden {
|
||||||
let pane: &mut PaneState = &mut self.panes[i];
|
ui.menu_button(self.panes[i].id.clone(), |ui| {
|
||||||
if pane.mode != PaneMode::Hidden {
|
let _ = &mut self.panes[i].pane.context_menu(ui);
|
||||||
pane.pane.context_menu(ui);
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -269,7 +233,7 @@ impl PaneManager {
|
|||||||
|
|
||||||
self.panes = panes;
|
self.panes = panes;
|
||||||
|
|
||||||
for (mut pane) in &mut self.panes {
|
for pane in &mut self.panes {
|
||||||
pane.pane.init(&self.pcc);
|
pane.pane.init(&self.pcc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod pipeline_editor;
|
||||||
|
pub mod point_cloud_renderer;
|
||||||
@@ -0,0 +1,257 @@
|
|||||||
|
use crate::pane_manager::{Pane, PaneMode, PaneState, PsudoCreationContext};
|
||||||
|
|
||||||
|
|
||||||
|
use egui::{Color32, Id, Pos2, Ui};
|
||||||
|
use egui_snarl::{
|
||||||
|
ui::{PinInfo, SnarlStyle, SnarlViewer},
|
||||||
|
InPin, NodeId, OutPin, Snarl,
|
||||||
|
};
|
||||||
|
use egui_snarl::ui::{PinShape, WireStyle};
|
||||||
|
|
||||||
|
#[derive(serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct PipelinePane {
|
||||||
|
snarl: Option<Snarl<Box<dyn Node>>>,
|
||||||
|
style: Option<SnarlStyle>,
|
||||||
|
snarl_ui_id: Option<Id>,
|
||||||
|
}
|
||||||
|
#[typetag::serde]
|
||||||
|
impl Pane for PipelinePane {
|
||||||
|
fn new() -> PaneState
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
let mut s = Self {
|
||||||
|
snarl: Some(Snarl::new()),
|
||||||
|
style: Some(SnarlStyle::new()),
|
||||||
|
snarl_ui_id: None,
|
||||||
|
};
|
||||||
|
PaneState {
|
||||||
|
id: s.name().to_string(),
|
||||||
|
mode: PaneMode::Center,
|
||||||
|
pane: Box::new(s),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn init(&mut self, _cc: &PsudoCreationContext) {}
|
||||||
|
fn name(&mut self) -> &str {
|
||||||
|
"Pipeline Pane"
|
||||||
|
}
|
||||||
|
fn render(&mut self, ui: &mut Ui) {
|
||||||
|
self.snarl_ui_id = Some(ui.id());
|
||||||
|
|
||||||
|
if let Some(snarl) = &mut self.snarl {
|
||||||
|
if let Some(style) = &self.style {
|
||||||
|
snarl.show(&mut NodeViewer, style, "snarl", ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
fn context_menu(&mut self, ui: &mut Ui) {
|
||||||
|
|
||||||
|
ui.menu_button("Add Node", |ui| {
|
||||||
|
if let Some(snarl) = &mut self.snarl {
|
||||||
|
NodeViewer::add_node_menu(Pos2 { x: 0., y: 0. }, ui, snarl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if ui.button("Run").clicked() {
|
||||||
|
ui.close_menu();
|
||||||
|
self.run();
|
||||||
|
}
|
||||||
|
// if !self.snarl.is_none() {
|
||||||
|
// self.snarl.unwrap().add_node_menu(ui, ui.clip_rect().min.clone(), )
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipelinePane {
|
||||||
|
pub fn run(&mut self) {
|
||||||
|
// Todo:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_float(v: f64) -> String {
|
||||||
|
let v = (v * 1000.0).round() / 1000.0;
|
||||||
|
format!("{}", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[typetag::serde(tag = "type")]
|
||||||
|
trait Node {
|
||||||
|
fn new() -> Self
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn get_name(&self) -> &str;
|
||||||
|
fn get_description(&self) -> &str;
|
||||||
|
fn duplicate(&self) -> Box<dyn Node>;
|
||||||
|
fn inputs(&self) -> usize;
|
||||||
|
fn outputs(&self) -> usize;
|
||||||
|
fn show_input(&self, pin: &InPin, ui: &mut Ui, scale: f32) -> PinInfo;
|
||||||
|
fn show_output(&self, pin: &OutPin, ui: &mut Ui, scale: f32) -> PinInfo;
|
||||||
|
fn can_rx(&self, other: &Box<dyn Node>) -> bool;
|
||||||
|
fn can_tx(&self, other: &Box<dyn Node>) -> bool;
|
||||||
|
fn context_menu(&self, ui: &mut Ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
struct Node1;
|
||||||
|
#[typetag::serde]
|
||||||
|
impl Node for Node1 {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_name(&self) -> &str {
|
||||||
|
"Test"
|
||||||
|
}
|
||||||
|
fn get_description(&self) -> &str {"Test Node"}
|
||||||
|
|
||||||
|
fn duplicate(&self) -> Box<dyn Node> {
|
||||||
|
Box::new(Self::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inputs(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
fn outputs(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
fn show_input(&self, _pin: &InPin, _ui: &mut Ui, _scale: f32) -> PinInfo {
|
||||||
|
PinInfo::square()
|
||||||
|
}
|
||||||
|
fn show_output(&self, _pin: &OutPin, _ui: &mut Ui, _scale: f32) -> PinInfo {
|
||||||
|
PinInfo::square().with_fill(Color32::RED).with_wire_style(WireStyle::Bezier3)
|
||||||
|
}
|
||||||
|
fn can_rx(&self, _other: &Box<dyn Node>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn can_tx(&self, _other: &Box<dyn Node>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
fn context_menu(&self, ui: &mut Ui) {
|
||||||
|
ui.label("Test!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
struct NodeViewer;
|
||||||
|
|
||||||
|
impl SnarlViewer<Box<dyn Node>> for NodeViewer {
|
||||||
|
fn connect(&mut self, from: &OutPin, to: &InPin, snarl: &mut Snarl<Box<dyn Node>>) {
|
||||||
|
// Validate connection
|
||||||
|
|
||||||
|
let rx = snarl.get_node(to.id.node).unwrap();
|
||||||
|
let tx = snarl.get_node(from.id.node).unwrap();
|
||||||
|
|
||||||
|
if rx.can_rx(tx) && tx.can_tx(rx) {
|
||||||
|
for &remote in &to.remotes {
|
||||||
|
snarl.disconnect(remote, to.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
snarl.connect(from.id, to.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn title(&mut self, node: &Box<dyn Node>) -> String {
|
||||||
|
node.get_name().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn outputs(&mut self, node: &Box<dyn Node>) -> usize {
|
||||||
|
node.outputs()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inputs(&mut self, node: &Box<dyn Node>) -> usize {
|
||||||
|
node.inputs()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_input(
|
||||||
|
&mut self,
|
||||||
|
pin: &InPin,
|
||||||
|
ui: &mut Ui,
|
||||||
|
scale: f32,
|
||||||
|
snarl: &mut Snarl<Box<dyn Node>>,
|
||||||
|
) -> PinInfo {
|
||||||
|
snarl
|
||||||
|
.get_node(pin.id.node)
|
||||||
|
.unwrap()
|
||||||
|
.show_input(pin, ui, scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_output(
|
||||||
|
&mut self,
|
||||||
|
pin: &OutPin,
|
||||||
|
ui: &mut Ui,
|
||||||
|
scale: f32,
|
||||||
|
snarl: &mut Snarl<Box<dyn Node>>,
|
||||||
|
) -> PinInfo {
|
||||||
|
snarl
|
||||||
|
.get_node(pin.id.node)
|
||||||
|
.unwrap()
|
||||||
|
.show_output(pin, ui, scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn has_graph_menu(&mut self, _pos: Pos2, _snarl: &mut Snarl<Box<dyn Node>>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_graph_menu(
|
||||||
|
&mut self,
|
||||||
|
pos: egui::Pos2,
|
||||||
|
ui: &mut Ui,
|
||||||
|
_scale: f32,
|
||||||
|
snarl: &mut Snarl<Box<dyn Node>>,
|
||||||
|
) {
|
||||||
|
NodeViewer::add_node_menu(pos, ui, snarl);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_on_hover_popup(&mut self, _: &Box<dyn Node>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_on_hover_popup(
|
||||||
|
&mut self,
|
||||||
|
node: NodeId,
|
||||||
|
_inputs: &[InPin],
|
||||||
|
_outputs: &[OutPin],
|
||||||
|
ui: &mut Ui,
|
||||||
|
_scale: f32,
|
||||||
|
snarl: &mut Snarl<Box<dyn Node>>,
|
||||||
|
) {
|
||||||
|
ui.label(snarl.get_node(node).unwrap().get_description());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_node_menu(&mut self, _node: &Box<dyn Node>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_node_menu(
|
||||||
|
&mut self,
|
||||||
|
nodeid: NodeId,
|
||||||
|
_inputs: &[InPin],
|
||||||
|
_outputs: &[OutPin],
|
||||||
|
ui: &mut Ui,
|
||||||
|
_scale: f32,
|
||||||
|
snarl: &mut Snarl<Box<dyn Node + 'static>>,
|
||||||
|
) {
|
||||||
|
ui.label("Node menu");
|
||||||
|
if ui.button("Remove").clicked() {
|
||||||
|
snarl.remove_node(nodeid);
|
||||||
|
ui.close_menu();
|
||||||
|
} else if ui.button("Duplicate").clicked() {
|
||||||
|
snarl.insert_node(Pos2 {x:0.,y:0.}, snarl.get_node(nodeid).unwrap().duplicate());
|
||||||
|
ui.close_menu();
|
||||||
|
} else {
|
||||||
|
snarl.get_node(nodeid).unwrap().context_menu(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeViewer {
|
||||||
|
pub fn add_node_menu(pos: Pos2, ui: &mut Ui, snarl: &mut Snarl<Box<dyn Node>>) {
|
||||||
|
ui.label("Add node");
|
||||||
|
let button = ui.button("Test1");
|
||||||
|
if button.clicked() {
|
||||||
|
snarl.insert_node(pos, Box::new(Node1::new()));
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ use glam::{Vec3, Mat4, Quat};
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
// use std::path::Path;
|
// use std::path::Path;
|
||||||
use std::io::{BufReader, BufRead};
|
use std::io::{BufReader, BufRead};
|
||||||
use crate::panes::{Pane, PaneMode, PaneState};
|
use crate::pane_manager::{Pane, PaneMode, PaneState, PsudoCreationContext};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use egui::FontId;
|
use egui::FontId;
|
||||||
use egui::Align2;
|
use egui::Align2;
|
||||||
@@ -14,7 +14,6 @@ use egui::Align2;
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use egui::Stroke;
|
use egui::Stroke;
|
||||||
use egui::Ui;
|
use egui::Ui;
|
||||||
use crate::panes;
|
|
||||||
|
|
||||||
// Shader sources updated for 3D rendering with fixed-point positions
|
// Shader sources updated for 3D rendering with fixed-point positions
|
||||||
const VERTEX_SHADER: &str = r#"
|
const VERTEX_SHADER: &str = r#"
|
||||||
@@ -532,7 +531,7 @@ pub struct PointRendererPane {
|
|||||||
#[typetag::serde]
|
#[typetag::serde]
|
||||||
impl Pane for PointRendererPane {
|
impl Pane for PointRendererPane {
|
||||||
fn new() -> PaneState where Self: Sized {
|
fn new() -> PaneState where Self: Sized {
|
||||||
let mut renderer = PointRenderer::default();
|
let renderer = PointRenderer::default();
|
||||||
let mut s = Self {
|
let mut s = Self {
|
||||||
renderer: Arc::new(Mutex::new(renderer)),
|
renderer: Arc::new(Mutex::new(renderer)),
|
||||||
points: Vec::new(),
|
points: Vec::new(),
|
||||||
@@ -541,11 +540,11 @@ impl Pane for PointRendererPane {
|
|||||||
};
|
};
|
||||||
PaneState {
|
PaneState {
|
||||||
id: s.name().to_string(),
|
id: s.name().to_string(),
|
||||||
mode: PaneMode::Center,
|
mode: PaneMode::Hidden,
|
||||||
pane: Box::new(s),
|
pane: Box::new(s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn init(&mut self, pcc: &panes::PsudoCreationContext){
|
fn init(&mut self, pcc: &PsudoCreationContext){
|
||||||
self.renderer.lock().expect("Renderer Not Initialized").init(pcc.gl.clone(), 1_000_000);
|
self.renderer.lock().expect("Renderer Not Initialized").init(pcc.gl.clone(), 1_000_000);
|
||||||
}
|
}
|
||||||
fn name(&mut self) -> &str {"Point Cloud"}
|
fn name(&mut self) -> &str {"Point Cloud"}
|
||||||
Reference in New Issue
Block a user