Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

Commit

Permalink
Merge pull request #58 from kkngsm/outside-userstate
Browse files Browse the repository at this point in the history
Change UserState to outside of GraphEditorState
  • Loading branch information
setzer22 authored Sep 17, 2022
2 parents 0395039 + 19ce5f4 commit 75308d0
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 25 deletions.
15 changes: 8 additions & 7 deletions egui_node_graph/src/editor_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ where
&mut self,
ui: &mut Ui,
all_kinds: impl NodeTemplateIter<Item = NodeTemplate>,
user_state: &mut UserState,
) -> GraphResponse<UserResponse, NodeData> {
// This causes the graph editor to use as much free space as it can.
// (so for windows it will use up to the resizeably set limit
Expand Down Expand Up @@ -124,7 +125,7 @@ where
.unwrap_or(false),
pan: self.pan_zoom.pan + editor_rect.min.to_vec2(),
}
.show(ui, &self.user_state);
.show(ui, user_state);

// Actions executed later
delayed_responses.extend(responses);
Expand All @@ -147,7 +148,7 @@ where
let new_node = self.graph.add_node(
node_kind.node_graph_label(),
node_kind.user_data(),
|graph, node_id| node_kind.build_node(graph, &self.user_state, node_id),
|graph, node_id| node_kind.build_node(graph, user_state, node_id),
);
self.node_positions.insert(
new_node,
Expand All @@ -174,7 +175,7 @@ where
/* Draw connections */
if let Some((_, ref locator)) = self.connection_in_progress {
let port_type = self.graph.any_param_type(*locator).unwrap();
let connection_color = port_type.data_type_color(&self.user_state);
let connection_color = port_type.data_type_color(user_state);
let start_pos = port_locations[locator];

// Find a port to connect to
Expand Down Expand Up @@ -245,7 +246,7 @@ where
.graph
.any_param_type(AnyParameterId::Output(output))
.unwrap();
let connection_color = port_type.data_type_color(&self.user_state);
let connection_color = port_type.data_type_color(user_state);
let src_pos = port_locations[&AnyParameterId::Output(output)];
let dst_pos = port_locations[&AnyParameterId::Input(input)];
draw_connection(ui.painter(), src_pos, dst_pos, connection_color);
Expand Down Expand Up @@ -390,7 +391,7 @@ where
pub fn show(
self,
ui: &mut Ui,
user_state: &UserState,
user_state: &mut UserState,
) -> Vec<NodeResponse<UserResponse, NodeData>> {
let mut child_ui = ui.child_ui_with_id_source(
Rect::from_min_size(*self.position + self.pan, Self::MAX_NODE_SIZE.into()),
Expand All @@ -406,7 +407,7 @@ where
fn show_graph_node(
self,
ui: &mut Ui,
user_state: &UserState,
user_state: &mut UserState,
) -> Vec<NodeResponse<UserResponse, NodeData>> {
let margin = egui::vec2(15.0, 5.0);
let mut responses = Vec::<NodeResponse<UserResponse, NodeData>>::new();
Expand Down Expand Up @@ -501,7 +502,7 @@ where
ui: &mut Ui,
graph: &Graph<NodeData, DataType, ValueType>,
node_id: NodeId,
user_state: &UserState,
user_state: &mut UserState,
port_pos: Pos2,
responses: &mut Vec<NodeResponse<UserResponse, NodeData>>,
param_id: AnyParameterId,
Expand Down
8 changes: 4 additions & 4 deletions egui_node_graph/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub trait WidgetValueTrait {
/// to the user.
pub trait DataTypeTrait<UserState>: PartialEq + Eq {
/// The associated port color of this datatype
fn data_type_color(&self, user_state: &UserState) -> egui::Color32;
fn data_type_color(&self, user_state: &mut UserState) -> egui::Color32;

/// The name of this datatype. Return type is specified as Cow<str> because
/// some implementations will need to allocate a new string to provide an
Expand Down Expand Up @@ -71,7 +71,7 @@ where
ui: &mut egui::Ui,
node_id: NodeId,
graph: &Graph<Self, Self::DataType, Self::ValueType>,
user_state: &Self::UserState,
user_state: &mut Self::UserState,
) -> Vec<NodeResponse<Self::Response, Self>>
where
Self::Response: UserResponseTrait;
Expand All @@ -83,7 +83,7 @@ where
_ui: &egui::Ui,
_node_id: NodeId,
_graph: &Graph<Self, Self::DataType, Self::ValueType>,
_user_state: &Self::UserState,
_user_state: &mut Self::UserState,
) -> Option<egui::Color32> {
None
}
Expand Down Expand Up @@ -126,7 +126,7 @@ pub trait NodeTemplateTrait: Clone {
fn build_node(
&self,
graph: &mut Graph<Self::NodeData, Self::DataType, Self::ValueType>,
user_state: &Self::UserState,
user_state: &mut Self::UserState,
node_id: NodeId,
);
}
Expand Down
7 changes: 4 additions & 3 deletions egui_node_graph/src/ui_state.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::*;
use std::marker::PhantomData;

#[cfg(feature = "persistence")]
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -29,13 +30,13 @@ pub struct GraphEditorState<NodeData, DataType, ValueType, NodeTemplate, UserSta
pub node_finder: Option<NodeFinder<NodeTemplate>>,
/// The panning of the graph viewport.
pub pan_zoom: PanZoom,
pub user_state: UserState,
pub _user_state: PhantomData<fn() -> UserState>,
}

impl<NodeData, DataType, ValueType, NodeKind, UserState>
GraphEditorState<NodeData, DataType, ValueType, NodeKind, UserState>
{
pub fn new(default_zoom: f32, user_state: UserState) -> Self {
pub fn new(default_zoom: f32) -> Self {
Self {
graph: Graph::new(),
node_order: Vec::new(),
Expand All @@ -47,7 +48,7 @@ impl<NodeData, DataType, ValueType, NodeKind, UserState>
pan: egui::Vec2::ZERO,
zoom: default_zoom,
},
user_state,
_user_state: PhantomData,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions egui_node_graph_example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ crate-type = ["cdylib", "rlib"]
eframe = "0.19.0"
egui_node_graph = { path = "../egui_node_graph" }
anyhow = "1.0"
serde = { version = "1.0", optional = true }

[features]
default = []
persistence = ["serde", "egui_node_graph/persistence", "eframe/persistence"]

[profile.release]
opt-level = 2 # fast and small wasm
53 changes: 42 additions & 11 deletions egui_node_graph_example/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use egui_node_graph::*;
/// The NodeData holds a custom data struct inside each node. It's useful to
/// store additional information that doesn't live in parameters. For this
/// example, the node data stores the template (i.e. the "type") of the node.
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub struct MyNodeData {
template: MyNodeTemplate,
}
Expand All @@ -16,6 +17,7 @@ pub struct MyNodeData {
/// attaching two ports together. The graph UI will make sure to not allow
/// attaching incompatible datatypes.
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub enum MyDataType {
Scalar,
Vec2,
Expand All @@ -29,6 +31,7 @@ pub enum MyDataType {
/// up to the user code in this example to make sure no parameter is created
/// with a DataType of Scalar and a ValueType of Vec2.
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub enum MyValueType {
Vec2 { value: egui::Vec2 },
Scalar { value: f32 },
Expand Down Expand Up @@ -58,6 +61,7 @@ impl MyValueType {
/// will display in the "new node" popup. The user code needs to tell the
/// library how to convert a NodeTemplate into a Node.
#[derive(Clone, Copy)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub enum MyNodeTemplate {
MakeVector,
MakeScalar,
Expand All @@ -82,6 +86,7 @@ pub enum MyResponse {
/// parameter drawing callbacks. The contents of this struct are entirely up to
/// the user. For this example, we use it to keep track of the 'active' node.
#[derive(Default)]
#[cfg_attr(feature = "persistence", derive(serde::Serialize, serde::Deserialize))]
pub struct MyGraphState {
pub active_node: Option<NodeId>,
}
Expand All @@ -90,7 +95,7 @@ pub struct MyGraphState {

// A trait for the data types, to tell the library how to display them
impl DataTypeTrait<MyGraphState> for MyDataType {
fn data_type_color(&self, _user_state: &MyGraphState) -> egui::Color32 {
fn data_type_color(&self, _user_state: &mut MyGraphState) -> egui::Color32 {
match self {
MyDataType::Scalar => egui::Color32::from_rgb(38, 109, 211),
MyDataType::Vec2 => egui::Color32::from_rgb(238, 207, 109),
Expand Down Expand Up @@ -138,7 +143,7 @@ impl NodeTemplateTrait for MyNodeTemplate {
fn build_node(
&self,
graph: &mut Graph<Self::NodeData, Self::DataType, Self::ValueType>,
_user_state: &Self::UserState,
_user_state: &mut Self::UserState,
node_id: NodeId,
) {
// The nodes are created empty by default. This function needs to take
Expand Down Expand Up @@ -295,7 +300,7 @@ impl NodeDataTrait for MyNodeData {
ui: &mut egui::Ui,
node_id: NodeId,
_graph: &Graph<MyNodeData, MyDataType, MyValueType>,
user_state: &Self::UserState,
user_state: &mut Self::UserState,
) -> Vec<NodeResponse<MyResponse, MyNodeData>>
where
MyResponse: UserResponseTrait,
Expand Down Expand Up @@ -340,17 +345,44 @@ pub struct NodeGraphExample {
// The `GraphEditorState` is the top-level object. You "register" all your
// custom types by specifying it as its generic parameters.
state: MyEditorState,

user_state: MyGraphState,
}

impl Default for NodeGraphExample {
fn default() -> Self {
Self {
state: GraphEditorState::new(1.0, MyGraphState::default()),
state: GraphEditorState::new(1.0),
user_state: MyGraphState::default(),
}
}
}
#[cfg(feature = "persistence")]
const PERSISTENCE_KEY: &str = "egui_node_graph";

#[cfg(feature = "persistence")]
impl NodeGraphExample {
/// If the persistence feature is enabled, Called once before the first frame.
/// Load previous app state (if any).
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
let state = cc
.storage
.and_then(|storage| eframe::get_value(storage, PERSISTENCE_KEY))
.unwrap_or_else(|| GraphEditorState::new(0.0));
Self {
state,
user_state: MyGraphState::default(),
}
}
}

impl eframe::App for NodeGraphExample {
#[cfg(feature = "persistence")]
/// If the persistence function is enabled,
/// Called by the frame work to save state before shutdown.
fn save(&mut self, storage: &mut dyn eframe::Storage) {
eframe::set_value(storage, PERSISTENCE_KEY, &self.state);
}
/// Called each time the UI needs repainting, which may be many times per second.
/// Put your widgets into a `SidePanel`, `TopPanel`, `CentralPanel`, `Window` or `Area`.
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
Expand All @@ -361,7 +393,8 @@ impl eframe::App for NodeGraphExample {
});
let graph_response = egui::CentralPanel::default()
.show(ctx, |ui| {
self.state.draw_graph_editor(ui, AllMyNodeTemplates)
self.state
.draw_graph_editor(ui, AllMyNodeTemplates, &mut self.user_state)
})
.inner;
for node_response in graph_response.node_responses {
Expand All @@ -370,15 +403,13 @@ impl eframe::App for NodeGraphExample {
// connection is created
if let NodeResponse::User(user_event) = node_response {
match user_event {
MyResponse::SetActiveNode(node) => {
self.state.user_state.active_node = Some(node)
}
MyResponse::ClearActiveNode => self.state.user_state.active_node = None,
MyResponse::SetActiveNode(node) => self.user_state.active_node = Some(node),
MyResponse::ClearActiveNode => self.user_state.active_node = None,
}
}
}

if let Some(node) = self.state.user_state.active_node {
if let Some(node) = self.user_state.active_node {
if self.state.graph.nodes.contains_key(node) {
let text = match evaluate_node(&self.state.graph, node, &mut HashMap::new()) {
Ok(value) => format!("The result is: {:?}", value),
Expand All @@ -392,7 +423,7 @@ impl eframe::App for NodeGraphExample {
egui::Color32::WHITE,
);
} else {
self.state.user_state.active_node = None;
self.user_state.active_node = None;
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions egui_node_graph_example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ fn main() {
eframe::NativeOptions::default(),
Box::new(|cc| {
cc.egui_ctx.set_visuals(Visuals::dark());
#[cfg(feature = "persistence")]
{
Box::new(egui_node_graph_example::NodeGraphExample::new(cc))
}
#[cfg(not(feature = "persistence"))]
Box::new(egui_node_graph_example::NodeGraphExample::default())
}),
);
Expand Down

0 comments on commit 75308d0

Please sign in to comment.