Skip to content

Commit

Permalink
Override node frame and header frame via SnarlViewer methods
Browse files Browse the repository at this point in the history
  • Loading branch information
zakarumych committed Nov 29, 2024
1 parent 70d6c59 commit 846cc83
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 64 deletions.
89 changes: 68 additions & 21 deletions examples/demo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;
use eframe::{App, CreationContext};
use egui::{Color32, Id, Ui};
use egui_snarl::{
ui::{AnyPins, PinInfo, SnarlStyle, SnarlViewer, WireStyle},
ui::{AnyPins, NodeLayout, PinInfo, PinPlacement, SnarlStyle, SnarlViewer, WireStyle},
InPin, InPinId, NodeId, OutPin, OutPinId, Snarl,
};

Expand Down Expand Up @@ -185,20 +185,20 @@ impl SnarlViewer<DemoNode> for DemoViewer {
match &*pin.remotes {
[] => {
ui.label("None");
PinInfo::star().with_fill(UNTYPED_COLOR)
PinInfo::circle().with_fill(UNTYPED_COLOR)
}
[remote] => match snarl[remote.node] {
DemoNode::Sink => unreachable!("Sink node has no outputs"),
DemoNode::Number(value) => {
assert_eq!(remote.output, 0, "Number node has only one output");
ui.label(format_float(value));
PinInfo::square().with_fill(NUMBER_COLOR)
PinInfo::circle().with_fill(NUMBER_COLOR)
}
DemoNode::String(ref value) => {
assert_eq!(remote.output, 0, "String node has only one output");
ui.label(format!("{:?}", value));

PinInfo::triangle().with_fill(STRING_COLOR).with_wire_style(
PinInfo::circle().with_fill(STRING_COLOR).with_wire_style(
WireStyle::AxisAligned {
corner_radius: 10.0,
},
Expand All @@ -207,7 +207,7 @@ impl SnarlViewer<DemoNode> for DemoViewer {
DemoNode::ExprNode(ref expr) => {
assert_eq!(remote.output, 0, "Expr node has only one output");
ui.label(format_float(expr.eval()));
PinInfo::square().with_fill(NUMBER_COLOR)
PinInfo::circle().with_fill(NUMBER_COLOR)
}
DemoNode::ShowImage(ref uri) => {
assert_eq!(remote.output, 0, "ShowImage node has only one output");
Expand Down Expand Up @@ -237,7 +237,7 @@ impl SnarlViewer<DemoNode> for DemoViewer {
.desired_width(0.0)
.margin(ui.spacing().item_spacing)
.show(ui);
PinInfo::triangle().with_fill(STRING_COLOR).with_wire_style(
PinInfo::circle().with_fill(STRING_COLOR).with_wire_style(
WireStyle::AxisAligned {
corner_radius: 10.0,
},
Expand All @@ -255,7 +255,7 @@ impl SnarlViewer<DemoNode> for DemoViewer {
let input = snarl[pin.id.node].string_in();
*input = new_value;

PinInfo::triangle().with_fill(STRING_COLOR).with_wire_style(
PinInfo::circle().with_fill(STRING_COLOR).with_wire_style(
WireStyle::AxisAligned {
corner_radius: 10.0,
},
Expand Down Expand Up @@ -353,11 +353,11 @@ impl SnarlViewer<DemoNode> for DemoViewer {
}
}
}
PinInfo::triangle().with_fill(STRING_COLOR).with_wire_style(
WireStyle::AxisAligned {
PinInfo::circle()
.with_fill(STRING_COLOR)
.with_wire_style(WireStyle::AxisAligned {
corner_radius: 10.0,
},
)
})
}
DemoNode::ExprNode(ref expr_node) => {
if pin.id.input <= expr_node.bindings.len() {
Expand All @@ -366,15 +366,15 @@ impl SnarlViewer<DemoNode> for DemoViewer {
let node = &mut snarl[pin.id.node];
ui.label(node.label_in(pin.id.input));
ui.add(egui::DragValue::new(node.number_in(pin.id.input)));
PinInfo::square().with_fill(NUMBER_COLOR)
PinInfo::circle().with_fill(NUMBER_COLOR)
}
[remote] => {
let new_value = snarl[remote.node].number_out();
let node = &mut snarl[pin.id.node];
ui.label(node.label_in(pin.id.input));
ui.label(format_float(new_value));
*node.number_in(pin.id.input) = new_value;
PinInfo::square().with_fill(NUMBER_COLOR)
PinInfo::circle().with_fill(NUMBER_COLOR)
}
_ => unreachable!("Expr pins has only one wire"),
}
Expand All @@ -400,7 +400,7 @@ impl SnarlViewer<DemoNode> for DemoViewer {
DemoNode::Number(ref mut value) => {
assert_eq!(pin.id.output, 0, "Number node has only one output");
ui.add(egui::DragValue::new(value));
PinInfo::square().with_fill(NUMBER_COLOR)
PinInfo::circle().with_fill(NUMBER_COLOR)
}
DemoNode::String(ref mut value) => {
assert_eq!(pin.id.output, 0, "String node has only one output");
Expand All @@ -409,17 +409,17 @@ impl SnarlViewer<DemoNode> for DemoViewer {
.desired_width(0.0)
.margin(ui.spacing().item_spacing);
ui.add(edit);
PinInfo::triangle().with_fill(STRING_COLOR).with_wire_style(
WireStyle::AxisAligned {
PinInfo::circle()
.with_fill(STRING_COLOR)
.with_wire_style(WireStyle::AxisAligned {
corner_radius: 10.0,
},
)
})
}
DemoNode::ExprNode(ref expr_node) => {
let value = expr_node.eval();
assert_eq!(pin.id.output, 0, "Expr node has only one output");
ui.label(format_float(value));
PinInfo::square().with_fill(NUMBER_COLOR)
PinInfo::circle().with_fill(NUMBER_COLOR)
}
DemoNode::ShowImage(_) => {
ui.allocate_at_least(egui::Vec2::ZERO, egui::Sense::hover());
Expand Down Expand Up @@ -641,6 +641,23 @@ impl SnarlViewer<DemoNode> for DemoViewer {
}
}
}

fn header_frame(
&mut self,
frame: egui::Frame,
node: NodeId,
_inputs: &[InPin],
_outputs: &[OutPin],
snarl: &Snarl<DemoNode>,
) -> egui::Frame {
match snarl[node] {
DemoNode::Sink => frame.fill(egui::Color32::from_rgb(70, 70, 80)),
DemoNode::Number(_) => frame.fill(egui::Color32::from_rgb(70, 40, 40)),
DemoNode::String(_) => frame.fill(egui::Color32::from_rgb(40, 70, 40)),
DemoNode::ShowImage(_) => frame.fill(egui::Color32::from_rgb(40, 40, 70)),
DemoNode::ExprNode(_) => frame.fill(egui::Color32::from_rgb(70, 66, 40)),
}
}
}

#[derive(Clone, serde::Serialize, serde::Deserialize)]
Expand Down Expand Up @@ -940,6 +957,36 @@ pub struct DemoApp {
snarl_ui_id: Option<Id>,
}

fn default_style() -> SnarlStyle {
SnarlStyle {
node_layout: Some(NodeLayout::FlippedSandwich),
pin_placement: Some(PinPlacement::Edge),
pin_size: Some(7.0),
node_frame: Some(egui::Frame {
inner_margin: egui::Margin::same(8.0),
outer_margin: egui::Margin {
left: 0.0,
right: 0.0,
top: 0.0,
bottom: 4.0,
},
rounding: egui::Rounding::same(8.0),
fill: egui::Color32::from_gray(30),
stroke: egui::Stroke::NONE,
shadow: egui::Shadow::NONE,
}),
bg_frame: Some(egui::Frame {
inner_margin: egui::Margin::same(2.0),
outer_margin: egui::Margin::ZERO,
rounding: egui::Rounding::ZERO,
fill: egui::Color32::from_gray(40),
stroke: egui::Stroke::NONE,
shadow: egui::Shadow::NONE,
}),
..SnarlStyle::new()
}
}

impl DemoApp {
pub fn new(cx: &CreationContext) -> Self {
egui_extras::install_image_loaders(&cx.egui_ctx);
Expand All @@ -956,11 +1003,11 @@ impl DemoApp {
// let snarl = Snarl::new();

let style = match cx.storage {
None => SnarlStyle::new(),
None => default_style(),
Some(storage) => storage
.get_string("style")
.and_then(|style| serde_json::from_str(&style).ok())
.unwrap_or_else(SnarlStyle::new),
.unwrap_or_else(default_style),
};
// let style = SnarlStyle::new();

Expand Down
74 changes: 39 additions & 35 deletions src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -681,8 +681,6 @@ impl<T> Snarl<T> {

let wire_frame_size = style.get_wire_frame_size(snarl_state.scale(), ui.style());
let wire_width = style.get_wire_width(snarl_state.scale(), ui.style());
let node_frame = style.get_node_frame(snarl_state.scale(), ui.style());
let header_frame = style.get_header_frame(snarl_state.scale(), ui.style());

let wire_shape_idx = match style.get_wire_layer() {
WireLayer::BehindNodes => Some(ui.painter().add(Shape::Noop)),
Expand Down Expand Up @@ -730,8 +728,6 @@ impl<T> Snarl<T> {
&mut snarl_state,
style,
snarl_id,
&node_frame,
&header_frame,
&mut input_info,
&input,
&mut output_info,
Expand Down Expand Up @@ -1444,8 +1440,6 @@ impl<T> Snarl<T> {
snarl_state: &mut SnarlState,
style: &SnarlStyle,
snarl_id: Id,
node_frame: &Frame,
header_frame: &Frame,
input_positions: &mut HashMap<InPinId, PinResponse>,
input: &Input,
output_positions: &mut HashMap<OutPinId, PinResponse>,
Expand All @@ -1465,6 +1459,14 @@ impl<T> Snarl<T> {
let inputs_count = viewer.inputs(value);
let outputs_count = viewer.outputs(value);

let inputs = (0..inputs_count)
.map(|idx| InPin::new(self, InPinId { node, input: idx }))
.collect::<Vec<_>>();

let outputs = (0..outputs_count)
.map(|idx| OutPin::new(self, OutPinId { node, output: idx }))
.collect::<Vec<_>>();

let node_pos = snarl_state.graph_pos_to_screen(pos, viewport);

// Generate persistent id for the node.
Expand All @@ -1481,6 +1483,21 @@ impl<T> Snarl<T> {
let mut drag_released = false;
let mut pin_hovered = None;

let node_frame = viewer.node_frame(
style.get_node_frame(snarl_state.scale(), ui.style()),
node,
&inputs,
&outputs,
self,
);
let header_frame = viewer.header_frame(
style.get_header_frame(snarl_state.scale(), ui.style()),
node,
&inputs,
&outputs,
self,
);

// Rect for node + frame margin.
let node_frame_rect = node_rect + node_frame.total_margin();

Expand All @@ -1507,14 +1524,6 @@ impl<T> Snarl<T> {
.get_header_drag_space(snarl_state.scale(), ui.style())
.max(Vec2::ZERO);

let inputs = (0..inputs_count)
.map(|idx| InPin::new(self, InPinId { node, input: idx }))
.collect::<Vec<_>>();

let outputs = (0..outputs_count)
.map(|idx| OutPin::new(self, OutPinId { node, output: idx }))
.collect::<Vec<_>>();

// Interact with node frame.
let r = ui.interact(
node_frame_rect,
Expand Down Expand Up @@ -1584,7 +1593,7 @@ impl<T> Snarl<T> {
}
PinPlacement::Edge => node_frame_rect.left(),
PinPlacement::Outside { margin } => {
node_frame_rect.left() - margin - pin_size * 0.5
node_frame_rect.left() - margin * snarl_state.scale() - pin_size * 0.5
}
};

Expand All @@ -1604,7 +1613,7 @@ impl<T> Snarl<T> {
}
PinPlacement::Edge => node_frame_rect.right(),
PinPlacement::Outside { margin } => {
node_frame_rect.right() + margin + pin_size * 0.5
node_frame_rect.right() + margin * snarl_state.scale() + pin_size * 0.5
}
};

Expand Down Expand Up @@ -1636,9 +1645,8 @@ impl<T> Snarl<T> {
node_rect.max,
);

let node_layout = viewer
.node_layout(node, &inputs, &outputs, self)
.unwrap_or(style.get_node_layout());
let node_layout =
viewer.node_layout(style.get_node_layout(), node, &inputs, &outputs, self);

let payload_clip_rect =
Rect::from_min_max(node_rect.min, pos2(node_rect.max.x, f32::INFINITY));
Expand Down Expand Up @@ -1785,7 +1793,8 @@ impl<T> Snarl<T> {
}

let inputs_rect = r.final_rect;
let inputs_size = inputs_rect.size();

new_pins_size = inputs_rect.size();

let mut next_y = inputs_rect.bottom() + ui.spacing().item_spacing.y;

Expand Down Expand Up @@ -1814,8 +1823,8 @@ impl<T> Snarl<T> {

let body_rect = r.final_rect;

new_pins_size.x += body_rect.width() + ui.spacing().item_spacing.x;
new_pins_size.y = f32::max(new_pins_size.y, body_rect.height());
new_pins_size.x = f32::max(new_pins_size.x, body_rect.width());
new_pins_size.y += body_rect.height() + ui.spacing().item_spacing.y;

if !self.nodes.contains(node.0) {
// If removed
Expand Down Expand Up @@ -1855,17 +1864,14 @@ impl<T> Snarl<T> {
}

let outputs_rect = r.final_rect;
let outputs_size = outputs_rect.size();

if !self.nodes.contains(node.0) {
// If removed
return;
}

new_pins_size = vec2(
inputs_size.x + outputs_size.x + ui.spacing().item_spacing.x,
f32::max(inputs_size.y, outputs_size.y),
);
new_pins_size.x = f32::max(new_pins_size.x, outputs_rect.width());
new_pins_size.y += outputs_rect.height() + ui.spacing().item_spacing.y;

pins_rect = pins_rect.union(outputs_rect);

Expand Down Expand Up @@ -1900,7 +1906,8 @@ impl<T> Snarl<T> {
}

let outputs_rect = r.final_rect;
let outputs_size = outputs_rect.size();

new_pins_size = outputs_rect.size();

let mut next_y = outputs_rect.bottom() + ui.spacing().item_spacing.y;

Expand Down Expand Up @@ -1929,8 +1936,8 @@ impl<T> Snarl<T> {

let body_rect = r.final_rect;

new_pins_size.x += body_rect.width() + ui.spacing().item_spacing.x;
new_pins_size.y = f32::max(new_pins_size.y, body_rect.height());
new_pins_size.x = f32::max(new_pins_size.x, body_rect.width());
new_pins_size.y += body_rect.height() + ui.spacing().item_spacing.y;

if !self.nodes.contains(node.0) {
// If removed
Expand Down Expand Up @@ -1970,17 +1977,14 @@ impl<T> Snarl<T> {
}

let inputs_rect = r.final_rect;
let inputs_size = inputs_rect.size();

if !self.nodes.contains(node.0) {
// If removed
return;
}

new_pins_size = vec2(
inputs_size.x + outputs_size.x + ui.spacing().item_spacing.x,
f32::max(inputs_size.y, outputs_size.y),
);
new_pins_size.x = f32::max(new_pins_size.x, inputs_rect.width());
new_pins_size.y += inputs_rect.height() + ui.spacing().item_spacing.y;

pins_rect = pins_rect.union(inputs_rect);

Expand Down
Loading

0 comments on commit 846cc83

Please sign in to comment.