mirror of
https://github.com/eliasstepanik/egui_node_graph.git
synced 2026-01-11 05:48:27 +00:00
Merge pull request #69 from setzer22/feature/user_state_in_value_widget
Expose UserState and the node id to value_widget
This commit is contained in:
commit
c2310e5f9b
@ -76,7 +76,8 @@ where
|
|||||||
ValueType = ValueType,
|
ValueType = ValueType,
|
||||||
>,
|
>,
|
||||||
UserResponse: UserResponseTrait,
|
UserResponse: UserResponseTrait,
|
||||||
ValueType: WidgetValueTrait<Response = UserResponse>,
|
ValueType:
|
||||||
|
WidgetValueTrait<Response = UserResponse, UserState = UserState, NodeData = NodeData>,
|
||||||
NodeTemplate: NodeTemplateTrait<
|
NodeTemplate: NodeTemplateTrait<
|
||||||
NodeData = NodeData,
|
NodeData = NodeData,
|
||||||
DataType = DataType,
|
DataType = DataType,
|
||||||
@ -152,10 +153,10 @@ where
|
|||||||
node_finder_area = node_finder_area.current_pos(pos);
|
node_finder_area = node_finder_area.current_pos(pos);
|
||||||
}
|
}
|
||||||
node_finder_area.show(ui.ctx(), |ui| {
|
node_finder_area.show(ui.ctx(), |ui| {
|
||||||
if let Some(node_kind) = node_finder.show(ui, all_kinds) {
|
if let Some(node_kind) = node_finder.show(ui, all_kinds, user_state) {
|
||||||
let new_node = self.graph.add_node(
|
let new_node = self.graph.add_node(
|
||||||
node_kind.node_graph_label(),
|
node_kind.node_graph_label(user_state),
|
||||||
node_kind.user_data(),
|
node_kind.user_data(user_state),
|
||||||
|graph, node_id| node_kind.build_node(graph, user_state, node_id),
|
|graph, node_id| node_kind.build_node(graph, user_state, node_id),
|
||||||
);
|
);
|
||||||
self.node_positions.insert(
|
self.node_positions.insert(
|
||||||
@ -391,7 +392,8 @@ where
|
|||||||
ValueType = ValueType,
|
ValueType = ValueType,
|
||||||
>,
|
>,
|
||||||
UserResponse: UserResponseTrait,
|
UserResponse: UserResponseTrait,
|
||||||
ValueType: WidgetValueTrait<Response = UserResponse>,
|
ValueType:
|
||||||
|
WidgetValueTrait<Response = UserResponse, UserState = UserState, NodeData = NodeData>,
|
||||||
DataType: DataTypeTrait<UserState>,
|
DataType: DataTypeTrait<UserState>,
|
||||||
{
|
{
|
||||||
pub const MAX_NODE_SIZE: [f32; 2] = [200.0, 200.0];
|
pub const MAX_NODE_SIZE: [f32; 2] = [200.0, 200.0];
|
||||||
@ -469,13 +471,23 @@ where
|
|||||||
if self.graph.connection(param_id).is_some() {
|
if self.graph.connection(param_id).is_some() {
|
||||||
ui.label(param_name);
|
ui.label(param_name);
|
||||||
} else {
|
} else {
|
||||||
responses.extend(
|
// NOTE: We want to pass the `user_data` to
|
||||||
self.graph[param_id]
|
// `value_widget`, but we can't since that would require
|
||||||
.value
|
// borrowing the graph twice. Here, we make the
|
||||||
.value_widget(¶m_name, ui)
|
// assumption that the value is cheaply replaced, and
|
||||||
.into_iter()
|
// use `std::mem::take` to temporarily replace it with a
|
||||||
.map(NodeResponse::User),
|
// dummy value. This requires `ValueType` to implement
|
||||||
|
// Default, but results in a totally safe alternative.
|
||||||
|
let mut value = std::mem::take(&mut self.graph[param_id].value);
|
||||||
|
let node_responses = value.value_widget(
|
||||||
|
¶m_name,
|
||||||
|
self.node_id,
|
||||||
|
ui,
|
||||||
|
user_state,
|
||||||
|
&self.graph[self.node_id].user_data,
|
||||||
);
|
);
|
||||||
|
self.graph[param_id].value = value;
|
||||||
|
responses.extend(node_responses.into_iter().map(NodeResponse::User));
|
||||||
}
|
}
|
||||||
let height_after = ui.min_rect().bottom();
|
let height_after = ui.min_rect().bottom();
|
||||||
input_port_heights.push((height_before + height_after) / 2.0);
|
input_port_heights.push((height_before + height_after) / 2.0);
|
||||||
|
|||||||
@ -14,9 +14,9 @@ pub struct NodeFinder<NodeTemplate> {
|
|||||||
_phantom: PhantomData<NodeTemplate>,
|
_phantom: PhantomData<NodeTemplate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<NodeTemplate, NodeData> NodeFinder<NodeTemplate>
|
impl<NodeTemplate, NodeData, UserState> NodeFinder<NodeTemplate>
|
||||||
where
|
where
|
||||||
NodeTemplate: NodeTemplateTrait<NodeData = NodeData>,
|
NodeTemplate: NodeTemplateTrait<NodeData = NodeData, UserState = UserState>,
|
||||||
{
|
{
|
||||||
pub fn new_at(pos: Pos2) -> Self {
|
pub fn new_at(pos: Pos2) -> Self {
|
||||||
NodeFinder {
|
NodeFinder {
|
||||||
@ -34,6 +34,7 @@ where
|
|||||||
&mut self,
|
&mut self,
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
all_kinds: impl NodeTemplateIter<Item = NodeTemplate>,
|
all_kinds: impl NodeTemplateIter<Item = NodeTemplate>,
|
||||||
|
user_state: &mut UserState,
|
||||||
) -> Option<NodeTemplate> {
|
) -> Option<NodeTemplate> {
|
||||||
let background_color;
|
let background_color;
|
||||||
let text_color;
|
let text_color;
|
||||||
@ -68,7 +69,7 @@ where
|
|||||||
.inner_margin(vec2(10.0, 10.0))
|
.inner_margin(vec2(10.0, 10.0))
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
for kind in all_kinds.all_kinds() {
|
for kind in all_kinds.all_kinds() {
|
||||||
let kind_name = kind.node_finder_label().to_string();
|
let kind_name = kind.node_finder_label(user_state).to_string();
|
||||||
if kind_name
|
if kind_name
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
.contains(self.query.to_lowercase().as_str())
|
.contains(self.query.to_lowercase().as_str())
|
||||||
|
|||||||
@ -3,13 +3,28 @@ use super::*;
|
|||||||
/// This trait must be implemented by the `ValueType` generic parameter of the
|
/// This trait must be implemented by the `ValueType` generic parameter of the
|
||||||
/// [`Graph`]. The trait allows drawing custom inline widgets for the different
|
/// [`Graph`]. The trait allows drawing custom inline widgets for the different
|
||||||
/// types of the node graph.
|
/// types of the node graph.
|
||||||
pub trait WidgetValueTrait {
|
///
|
||||||
|
/// The [`Default`] trait bound is required to circumvent borrow checker issues
|
||||||
|
/// using `std::mem::take` Otherwise, it would be impossible to pass the
|
||||||
|
/// `node_data` parameter during `value_widget`. The default value is never
|
||||||
|
/// used, so the implementation is not important, but it should be reasonably
|
||||||
|
/// cheap to construct.
|
||||||
|
pub trait WidgetValueTrait: Default {
|
||||||
type Response;
|
type Response;
|
||||||
|
type UserState;
|
||||||
|
type NodeData;
|
||||||
/// This method will be called for each input parameter with a widget. The
|
/// This method will be called for each input parameter with a widget. The
|
||||||
/// return value is a vector of custom response objects which can be used
|
/// return value is a vector of custom response objects which can be used
|
||||||
/// to implement handling of side effects. If unsure, the response Vec can
|
/// to implement handling of side effects. If unsure, the response Vec can
|
||||||
/// be empty.
|
/// be empty.
|
||||||
fn value_widget(&mut self, param_name: &str, ui: &mut egui::Ui) -> Vec<Self::Response>;
|
fn value_widget(
|
||||||
|
&mut self,
|
||||||
|
param_name: &str,
|
||||||
|
node_id: NodeId,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
user_state: &mut Self::UserState,
|
||||||
|
node_data: &Self::NodeData,
|
||||||
|
) -> Vec<Self::Response>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait must be implemented by the `DataType` generic parameter of the
|
/// This trait must be implemented by the `DataType` generic parameter of the
|
||||||
@ -112,13 +127,17 @@ pub trait NodeTemplateTrait: Clone {
|
|||||||
type UserState;
|
type UserState;
|
||||||
|
|
||||||
/// Returns a descriptive name for the node kind, used in the node finder.
|
/// Returns a descriptive name for the node kind, used in the node finder.
|
||||||
fn node_finder_label(&self) -> &str;
|
///
|
||||||
|
/// The return type is Cow<str> to allow returning owned or borrowed values
|
||||||
|
/// more flexibly. Refer to the documentation for `DataTypeTrait::name` for
|
||||||
|
/// more information
|
||||||
|
fn node_finder_label(&self, user_state: &mut Self::UserState) -> std::borrow::Cow<str>;
|
||||||
|
|
||||||
/// Returns a descriptive name for the node kind, used in the graph.
|
/// Returns a descriptive name for the node kind, used in the graph.
|
||||||
fn node_graph_label(&self) -> String;
|
fn node_graph_label(&self, user_state: &mut Self::UserState) -> String;
|
||||||
|
|
||||||
/// Returns the user data for this node kind.
|
/// Returns the user data for this node kind.
|
||||||
fn user_data(&self) -> Self::NodeData;
|
fn user_data(&self, user_state: &mut Self::UserState) -> Self::NodeData;
|
||||||
|
|
||||||
/// This function is run when this node kind gets added to the graph. The
|
/// This function is run when this node kind gets added to the graph. The
|
||||||
/// node will be empty by default, and this function can be used to fill its
|
/// node will be empty by default, and this function can be used to fill its
|
||||||
|
|||||||
@ -37,6 +37,14 @@ pub enum MyValueType {
|
|||||||
Scalar { value: f32 },
|
Scalar { value: f32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for MyValueType {
|
||||||
|
fn default() -> Self {
|
||||||
|
// NOTE: This is just a dummy `Default` implementation. The library
|
||||||
|
// requires it to circumvent some internal borrow checker issues.
|
||||||
|
Self::Scalar { value: 0.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MyValueType {
|
impl MyValueType {
|
||||||
/// Tries to downcast this value type to a vector
|
/// Tries to downcast this value type to a vector
|
||||||
pub fn try_to_vec2(self) -> anyhow::Result<egui::Vec2> {
|
pub fn try_to_vec2(self) -> anyhow::Result<egui::Vec2> {
|
||||||
@ -118,8 +126,8 @@ impl NodeTemplateTrait for MyNodeTemplate {
|
|||||||
type ValueType = MyValueType;
|
type ValueType = MyValueType;
|
||||||
type UserState = MyGraphState;
|
type UserState = MyGraphState;
|
||||||
|
|
||||||
fn node_finder_label(&self) -> &str {
|
fn node_finder_label(&self, _user_state: &mut Self::UserState) -> Cow<'_, str> {
|
||||||
match self {
|
Cow::Borrowed(match self {
|
||||||
MyNodeTemplate::MakeVector => "New vector",
|
MyNodeTemplate::MakeVector => "New vector",
|
||||||
MyNodeTemplate::MakeScalar => "New scalar",
|
MyNodeTemplate::MakeScalar => "New scalar",
|
||||||
MyNodeTemplate::AddScalar => "Scalar add",
|
MyNodeTemplate::AddScalar => "Scalar add",
|
||||||
@ -127,16 +135,16 @@ impl NodeTemplateTrait for MyNodeTemplate {
|
|||||||
MyNodeTemplate::AddVector => "Vector add",
|
MyNodeTemplate::AddVector => "Vector add",
|
||||||
MyNodeTemplate::SubtractVector => "Vector subtract",
|
MyNodeTemplate::SubtractVector => "Vector subtract",
|
||||||
MyNodeTemplate::VectorTimesScalar => "Vector times scalar",
|
MyNodeTemplate::VectorTimesScalar => "Vector times scalar",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_graph_label(&self) -> String {
|
fn node_graph_label(&self, user_state: &mut Self::UserState) -> String {
|
||||||
// It's okay to delegate this to node_finder_label if you don't want to
|
// It's okay to delegate this to node_finder_label if you don't want to
|
||||||
// show different names in the node finder and the node itself.
|
// show different names in the node finder and the node itself.
|
||||||
self.node_finder_label().into()
|
self.node_finder_label(user_state).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn user_data(&self) -> Self::NodeData {
|
fn user_data(&self, _user_state: &mut Self::UserState) -> Self::NodeData {
|
||||||
MyNodeData { template: *self }
|
MyNodeData { template: *self }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +266,16 @@ impl NodeTemplateIter for AllMyNodeTemplates {
|
|||||||
|
|
||||||
impl WidgetValueTrait for MyValueType {
|
impl WidgetValueTrait for MyValueType {
|
||||||
type Response = MyResponse;
|
type Response = MyResponse;
|
||||||
fn value_widget(&mut self, param_name: &str, ui: &mut egui::Ui) -> Vec<MyResponse> {
|
type UserState = MyGraphState;
|
||||||
|
type NodeData = MyNodeData;
|
||||||
|
fn value_widget(
|
||||||
|
&mut self,
|
||||||
|
param_name: &str,
|
||||||
|
_node_id: NodeId,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
_user_state: &mut MyGraphState,
|
||||||
|
_node_data: &MyNodeData,
|
||||||
|
) -> Vec<MyResponse> {
|
||||||
// This trait is used to tell the library which UI to display for the
|
// This trait is used to tell the library which UI to display for the
|
||||||
// inline parameter widgets.
|
// inline parameter widgets.
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user