Add preview and disable buttons for nodes (#905)
* Add preview and disable button * Fix tests Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
41b07ad0cf
commit
8d7e6c530e
|
|
@ -250,6 +250,13 @@ pub enum LayoutGroup {
|
||||||
#[serde(rename = "section")]
|
#[serde(rename = "section")]
|
||||||
Section { name: String, layout: SubLayout },
|
Section { name: String, layout: SubLayout },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for LayoutGroup {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Row { widgets: Vec::new() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LayoutGroup {
|
impl LayoutGroup {
|
||||||
/// Applies a tooltip to all widgets in this row or column without a tooltip.
|
/// Applies a tooltip to all widgets in this row or column without a tooltip.
|
||||||
pub fn with_tooltip(self, tooltip: impl Into<String>) -> Self {
|
pub fn with_tooltip(self, tooltip: impl Into<String>) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,12 @@ pub enum NodeGraphMessage {
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
value: TaggedValue,
|
value: TaggedValue,
|
||||||
},
|
},
|
||||||
|
SetSelectedEnabled {
|
||||||
|
enabled: bool,
|
||||||
|
},
|
||||||
|
SetSelectedOutput {
|
||||||
|
output: bool,
|
||||||
|
},
|
||||||
ShiftNode {
|
ShiftNode {
|
||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
|
use crate::messages::layout::utility_types::layout_widget::{Layout, LayoutGroup, Widget, WidgetCallback, WidgetHolder, WidgetLayout};
|
||||||
use crate::messages::layout::utility_types::widgets::button_widgets::BreadcrumbTrailButtons;
|
use crate::messages::layout::utility_types::widgets::button_widgets::{BreadcrumbTrailButtons, TextButton};
|
||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
|
|
||||||
use document_legacy::document::Document;
|
use document_legacy::document::Document;
|
||||||
|
|
@ -65,6 +65,8 @@ pub struct FrontendNode {
|
||||||
pub exposed_inputs: Vec<NodeGraphInput>,
|
pub exposed_inputs: Vec<NodeGraphInput>,
|
||||||
pub outputs: Vec<FrontendGraphDataType>,
|
pub outputs: Vec<FrontendGraphDataType>,
|
||||||
pub position: (i32, i32),
|
pub position: (i32, i32),
|
||||||
|
pub disabled: bool,
|
||||||
|
pub output: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// (link_start, link_end, link_end_input_index)
|
// (link_start, link_end, link_end_input_index)
|
||||||
|
|
@ -92,11 +94,13 @@ impl FrontendNodeType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Default, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Default, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct NodeGraphMessageHandler {
|
pub struct NodeGraphMessageHandler {
|
||||||
pub layer_path: Option<Vec<document_legacy::LayerId>>,
|
pub layer_path: Option<Vec<document_legacy::LayerId>>,
|
||||||
pub nested_path: Vec<graph_craft::document::NodeId>,
|
pub nested_path: Vec<graph_craft::document::NodeId>,
|
||||||
pub selected_nodes: Vec<graph_craft::document::NodeId>,
|
pub selected_nodes: Vec<graph_craft::document::NodeId>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub widgets: [LayoutGroup; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeGraphMessageHandler {
|
impl NodeGraphMessageHandler {
|
||||||
|
|
@ -124,8 +128,20 @@ impl NodeGraphMessageHandler {
|
||||||
network
|
network
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send the cached layout for the bar at the top of the node panel to the frontend
|
||||||
|
fn send_node_bar_layout(&self, responses: &mut VecDeque<Message>) {
|
||||||
|
responses.push_back(
|
||||||
|
LayoutMessage::SendLayout {
|
||||||
|
layout: Layout::WidgetLayout(WidgetLayout::new(self.widgets.to_vec())),
|
||||||
|
layout_target: crate::messages::layout::utility_types::misc::LayoutTarget::NodeGraphBar,
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Collect the addresses of the currently viewed nested node e.g. Root -> MyFunFilter -> Exposure
|
/// Collect the addresses of the currently viewed nested node e.g. Root -> MyFunFilter -> Exposure
|
||||||
fn collect_nested_addresses(&self, document: &Document, responses: &mut VecDeque<Message>) {
|
fn collect_nested_addresses(&mut self, document: &Document, responses: &mut VecDeque<Message>) {
|
||||||
|
// Build path list
|
||||||
let mut path = vec!["Root".to_string()];
|
let mut path = vec!["Root".to_string()];
|
||||||
let mut network = self.get_root_network(document);
|
let mut network = self.get_root_network(document);
|
||||||
for node_id in &self.nested_path {
|
for node_id in &self.nested_path {
|
||||||
|
|
@ -137,24 +153,56 @@ impl NodeGraphMessageHandler {
|
||||||
}
|
}
|
||||||
let nesting = path.len();
|
let nesting = path.len();
|
||||||
|
|
||||||
responses.push_back(
|
// Update UI
|
||||||
LayoutMessage::SendLayout {
|
self.widgets[0] = LayoutGroup::Row {
|
||||||
layout: Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
|
widgets: vec![WidgetHolder::new(Widget::BreadcrumbTrailButtons(BreadcrumbTrailButtons {
|
||||||
widgets: vec![WidgetHolder::new(Widget::BreadcrumbTrailButtons(BreadcrumbTrailButtons {
|
labels: path.clone(),
|
||||||
labels: path,
|
on_update: WidgetCallback::new(move |input: &u64| {
|
||||||
on_update: WidgetCallback::new(move |input: &u64| {
|
NodeGraphMessage::ExitNestedNetwork {
|
||||||
NodeGraphMessage::ExitNestedNetwork {
|
depth_of_nesting: nesting - (*input as usize) - 1,
|
||||||
depth_of_nesting: nesting - (*input as usize) - 1,
|
}
|
||||||
}
|
.into()
|
||||||
.into()
|
}),
|
||||||
}),
|
..Default::default()
|
||||||
..Default::default()
|
}))],
|
||||||
}))],
|
};
|
||||||
}])),
|
|
||||||
layout_target: crate::messages::layout::utility_types::misc::LayoutTarget::NodeGraphBar,
|
self.send_node_bar_layout(responses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the buttons for disable and preview
|
||||||
|
fn update_selection_action_buttons(&mut self, document: &mut Document, responses: &mut VecDeque<Message>) {
|
||||||
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
|
let mut widgets = Vec::new();
|
||||||
|
|
||||||
|
// Show an enable or disable nodes button if there is a selection
|
||||||
|
if !self.selected_nodes.is_empty() {
|
||||||
|
let is_enabled = self.selected_nodes.iter().any(|id| !network.disabled.contains(id));
|
||||||
|
let enable_button = WidgetHolder::new(Widget::TextButton(TextButton {
|
||||||
|
label: if is_enabled { "Disable" } else { "Enable" }.to_string(),
|
||||||
|
on_update: WidgetCallback::new(move |_| NodeGraphMessage::SetSelectedEnabled { enabled: !is_enabled }.into()),
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
widgets.push(enable_button);
|
||||||
}
|
}
|
||||||
.into(),
|
|
||||||
);
|
// If only one node is selected then show the preview or stop previewing button
|
||||||
|
if self.selected_nodes.len() == 1 {
|
||||||
|
let is_output = network.output == self.selected_nodes[0];
|
||||||
|
// Don't show stop previewing on the output node
|
||||||
|
if !(is_output && network.previous_output.filter(|&id| id != self.selected_nodes[0]).is_none()) {
|
||||||
|
let output_button = WidgetHolder::new(Widget::TextButton(TextButton {
|
||||||
|
label: if is_output { "Stop Previewing" } else { "Preview" }.to_string(),
|
||||||
|
on_update: WidgetCallback::new(move |_| NodeGraphMessage::SetSelectedOutput { output: !is_output }.into()),
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
widgets.push(output_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.widgets[1] = LayoutGroup::Row { widgets };
|
||||||
|
}
|
||||||
|
self.send_node_bar_layout(responses);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn collate_properties(&self, node_graph_frame: &NodeGraphFrameLayer, context: &mut NodePropertiesContext, sections: &mut Vec<LayoutGroup>) {
|
pub fn collate_properties(&self, node_graph_frame: &NodeGraphFrameLayer, context: &mut NodePropertiesContext, sections: &mut Vec<LayoutGroup>) {
|
||||||
|
|
@ -237,14 +285,17 @@ impl NodeGraphMessageHandler {
|
||||||
.collect(),
|
.collect(),
|
||||||
outputs: node_type.outputs.to_vec(),
|
outputs: node_type.outputs.to_vec(),
|
||||||
position: node.metadata.position,
|
position: node.metadata.position,
|
||||||
|
output: network.output == *id,
|
||||||
|
disabled: network.disabled.contains(id),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
log::debug!("Frontend Nodes:\n{:#?}\n\nLinks:\n{:#?}", nodes, links);
|
log::debug!("Frontend Nodes:\n{:#?}\n\nLinks:\n{:#?}", nodes, links);
|
||||||
responses.push_back(FrontendMessage::UpdateNodeGraph { nodes, links }.into());
|
responses.push_back(FrontendMessage::UpdateNodeGraph { nodes, links }.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the frontend's selection state inline with the backend
|
/// Updates the frontend's selection state in line with the backend
|
||||||
fn update_selected(&self, responses: &mut VecDeque<Message>) {
|
fn update_selected(&mut self, document: &mut Document, responses: &mut VecDeque<Message>) {
|
||||||
|
self.update_selection_action_buttons(document, responses);
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
FrontendMessage::UpdateNodeGraphSelection {
|
FrontendMessage::UpdateNodeGraphSelection {
|
||||||
selected: self.selected_nodes.clone(),
|
selected: self.selected_nodes.clone(),
|
||||||
|
|
@ -388,6 +439,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
network.nodes.insert(
|
network.nodes.insert(
|
||||||
|
|
@ -413,6 +465,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::DeleteSelectedNodes => {
|
NodeGraphMessage::DeleteSelectedNodes => {
|
||||||
if let Some(network) = self.get_active_network_mut(document) {
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
|
|
@ -425,6 +478,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::DisconnectNodes { node_id, input_index } => {
|
NodeGraphMessage::DisconnectNodes { node_id, input_index } => {
|
||||||
let Some(network) = self.get_active_network_mut(document) else {
|
let Some(network) = self.get_active_network_mut(document) else {
|
||||||
|
|
@ -443,7 +497,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
Self::send_graph(network, responses);
|
Self::send_graph(network, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::DoubleClickNode { node } => {
|
NodeGraphMessage::DoubleClickNode { node } => {
|
||||||
self.selected_nodes = Vec::new();
|
self.selected_nodes.clear();
|
||||||
if let Some(network) = self.get_active_network_mut(document) {
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
if network.nodes.get(&node).and_then(|node| node.implementation.get_network()).is_some() {
|
if network.nodes.get(&node).and_then(|node| node.implementation.get_network()).is_some() {
|
||||||
self.nested_path.push(node);
|
self.nested_path.push(node);
|
||||||
|
|
@ -453,7 +507,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
Self::send_graph(network, responses);
|
Self::send_graph(network, responses);
|
||||||
}
|
}
|
||||||
self.collect_nested_addresses(document, responses);
|
self.collect_nested_addresses(document, responses);
|
||||||
self.update_selected(responses);
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::DuplicateSelectedNodes => {
|
NodeGraphMessage::DuplicateSelectedNodes => {
|
||||||
if let Some(network) = self.get_active_network_mut(document) {
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
|
|
@ -476,11 +530,11 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
}
|
}
|
||||||
self.selected_nodes = new_selected;
|
self.selected_nodes = new_selected;
|
||||||
Self::send_graph(network, responses);
|
Self::send_graph(network, responses);
|
||||||
self.update_selected(responses);
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NodeGraphMessage::ExitNestedNetwork { depth_of_nesting } => {
|
NodeGraphMessage::ExitNestedNetwork { depth_of_nesting } => {
|
||||||
self.selected_nodes = Vec::new();
|
self.selected_nodes.clear();
|
||||||
for _ in 0..depth_of_nesting {
|
for _ in 0..depth_of_nesting {
|
||||||
self.nested_path.pop();
|
self.nested_path.pop();
|
||||||
}
|
}
|
||||||
|
|
@ -488,6 +542,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
Self::send_graph(network, responses);
|
Self::send_graph(network, responses);
|
||||||
}
|
}
|
||||||
self.collect_nested_addresses(document, responses);
|
self.collect_nested_addresses(document, responses);
|
||||||
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => {
|
NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => {
|
||||||
let Some(network) = self.get_active_network_mut(document) else{
|
let Some(network) = self.get_active_network_mut(document) else{
|
||||||
|
|
@ -542,6 +597,7 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
responses.push_back(FrontendMessage::UpdateNodeTypes { node_types }.into());
|
responses.push_back(FrontendMessage::UpdateNodeTypes { node_types }.into());
|
||||||
}
|
}
|
||||||
self.collect_nested_addresses(document, responses);
|
self.collect_nested_addresses(document, responses);
|
||||||
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::PasteNodes { serialized_nodes } => {
|
NodeGraphMessage::PasteNodes { serialized_nodes } => {
|
||||||
let Some(network) = self.get_active_network_mut(document) else{
|
let Some(network) = self.get_active_network_mut(document) else{
|
||||||
|
|
@ -567,10 +623,11 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::send_graph(network, responses);
|
Self::send_graph(network, responses);
|
||||||
self.update_selected(responses);
|
self.update_selected(document, responses);
|
||||||
}
|
}
|
||||||
NodeGraphMessage::SelectNodes { nodes } => {
|
NodeGraphMessage::SelectNodes { nodes } => {
|
||||||
self.selected_nodes = nodes;
|
self.selected_nodes = nodes;
|
||||||
|
self.update_selection_action_buttons(document, responses);
|
||||||
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
|
responses.push_back(PropertiesPanelMessage::ResendActiveProperties.into());
|
||||||
}
|
}
|
||||||
NodeGraphMessage::SetInputValue { node, input_index, value } => {
|
NodeGraphMessage::SetInputValue { node, input_index, value } => {
|
||||||
|
|
@ -615,6 +672,31 @@ impl MessageHandler<NodeGraphMessage, (&mut Document, &InputPreprocessorMessageH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
NodeGraphMessage::SetSelectedEnabled { enabled } => {
|
||||||
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
|
if enabled {
|
||||||
|
network.disabled.retain(|id| !self.selected_nodes.contains(id));
|
||||||
|
} else {
|
||||||
|
network.disabled.extend(&self.selected_nodes);
|
||||||
|
}
|
||||||
|
Self::send_graph(network, responses);
|
||||||
|
}
|
||||||
|
self.update_selection_action_buttons(document, responses);
|
||||||
|
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
||||||
|
}
|
||||||
|
NodeGraphMessage::SetSelectedOutput { output } => {
|
||||||
|
if let Some(network) = self.get_active_network_mut(document) {
|
||||||
|
if output {
|
||||||
|
network.previous_output = Some(network.previous_output.unwrap_or(network.output));
|
||||||
|
network.output = self.selected_nodes[0];
|
||||||
|
} else if let Some(output) = network.previous_output.take() {
|
||||||
|
network.output = output
|
||||||
|
}
|
||||||
|
Self::send_graph(network, responses);
|
||||||
|
}
|
||||||
|
self.update_selection_action_buttons(document, responses);
|
||||||
|
responses.push_back(DocumentMessage::NodeGraphFrameGenerate.into());
|
||||||
|
}
|
||||||
NodeGraphMessage::ShiftNode { node_id } => {
|
NodeGraphMessage::ShiftNode { node_id } => {
|
||||||
let Some(network) = self.get_active_network_mut(document) else{
|
let Some(network) = self.get_active_network_mut(document) else{
|
||||||
warn!("No network");
|
warn!("No network");
|
||||||
|
|
|
||||||
|
|
@ -657,6 +657,30 @@ impl PortfolioMessageHandler {
|
||||||
self.document_ids.iter().position(|id| id == &document_id).expect("Active document is missing from document ids")
|
self.document_ids.iter().position(|id| id == &document_id).expect("Active document is missing from document ids")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execute the network by flattening it and creating a borrow stack. Casts the output to the generic `T`.
|
||||||
|
fn execute_network<T: dyn_any::StaticType>(mut network: NodeNetwork, image: Image) -> Result<T, String> {
|
||||||
|
for node_id in network.nodes.keys().copied().collect::<Vec<_>>() {
|
||||||
|
network.flatten(node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut proto_network = network.into_proto_network();
|
||||||
|
proto_network.reorder_ids();
|
||||||
|
|
||||||
|
assert_ne!(proto_network.nodes.len(), 0, "No protonodes exist?");
|
||||||
|
let stack = borrow_stack::FixedSizeStack::new(proto_network.nodes.len());
|
||||||
|
for (_id, node) in proto_network.nodes {
|
||||||
|
interpreted_executor::node_registry::push_node(node, &stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
use borrow_stack::BorrowStack;
|
||||||
|
use dyn_any::IntoDynAny;
|
||||||
|
use graphene_core::Node;
|
||||||
|
|
||||||
|
let boxed = unsafe { stack.get().last().unwrap().eval(image.into_dyn()) };
|
||||||
|
|
||||||
|
dyn_any::downcast::<T>(boxed).map(|v| *v)
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes an input for a node in the graph
|
/// Computes an input for a node in the graph
|
||||||
fn compute_input<T: dyn_any::StaticType>(old_network: &NodeNetwork, node_path: &[NodeId], mut input_index: usize, image: Cow<Image>) -> Result<T, String> {
|
fn compute_input<T: dyn_any::StaticType>(old_network: &NodeNetwork, node_path: &[NodeId], mut input_index: usize, image: Cow<Image>) -> Result<T, String> {
|
||||||
let mut network = old_network.clone();
|
let mut network = old_network.clone();
|
||||||
|
|
@ -694,26 +718,7 @@ impl PortfolioMessageHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let stack = borrow_stack::FixedSizeStack::new(256);
|
Self::execute_network(network, image.into_owned())
|
||||||
for node_id in old_network.nodes.keys() {
|
|
||||||
network.flatten(*node_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut proto_network = network.into_proto_network();
|
|
||||||
proto_network.reorder_ids();
|
|
||||||
|
|
||||||
assert_ne!(proto_network.nodes.len(), 0, "No protonodes exist?");
|
|
||||||
for (_id, node) in proto_network.nodes {
|
|
||||||
interpreted_executor::node_registry::push_node(node, &stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
use borrow_stack::BorrowStack;
|
|
||||||
use dyn_any::IntoDynAny;
|
|
||||||
use graphene_core::Node;
|
|
||||||
|
|
||||||
let boxed = unsafe { stack.get().last().unwrap().eval(image.into_owned().into_dyn()) };
|
|
||||||
|
|
||||||
dyn_any::downcast::<T>(boxed).map(|v| *v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes an image into a format using the image crate
|
/// Encodes an image into a format using the image crate
|
||||||
|
|
@ -856,7 +861,7 @@ impl PortfolioMessageHandler {
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let mut image: Image = Self::compute_input(&network, &[1], 0, Cow::Owned(image))?;
|
let mut image: Image = Self::execute_network(network, image)?;
|
||||||
|
|
||||||
// If no image was generated, use the input image
|
// If no image was generated, use the input image
|
||||||
if image.width == 0 || image.height == 0 {
|
if image.width == 0 || image.height == 0 {
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ impl Fsm for ImaginateToolFsmState {
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
let mut imaginate_inputs: Vec<NodeInput> = imaginate_node_type.inputs.iter().map(|input| input.default.clone()).collect();
|
let mut imaginate_inputs: Vec<NodeInput> = imaginate_node_type.inputs.iter().map(|input| input.default.clone()).collect();
|
||||||
imaginate_inputs[0] = NodeInput::Node(0);
|
imaginate_inputs[0] = NodeInput::Node(0);
|
||||||
|
|
@ -197,6 +198,7 @@ impl Fsm for ImaginateToolFsmState {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,7 @@ impl Fsm for NodeGraphToolFsmState {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
v-for="node in nodes"
|
v-for="node in nodes"
|
||||||
:key="String(node.id)"
|
:key="String(node.id)"
|
||||||
class="node"
|
class="node"
|
||||||
:class="{ selected: selected.includes(node.id) }"
|
:class="{ selected: selected.includes(node.id), output: node.output, disabled: node.disabled }"
|
||||||
:style="{
|
:style="{
|
||||||
'--offset-left': (node.position?.x || 0) + (selected.includes(node.id) ? draggingNodes?.roundX || 0 : 0),
|
'--offset-left': (node.position?.x || 0) + (selected.includes(node.id) ? draggingNodes?.roundX || 0 : 0),
|
||||||
'--offset-top': (node.position?.y || 0) + (selected.includes(node.id) ? draggingNodes?.roundY || 0 : 0),
|
'--offset-top': (node.position?.y || 0) + (selected.includes(node.id) ? draggingNodes?.roundY || 0 : 0),
|
||||||
|
|
@ -127,6 +127,12 @@
|
||||||
margin: 0 4px;
|
margin: 0 4px;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
.widget-layout {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.graph {
|
.graph {
|
||||||
|
|
@ -193,6 +199,19 @@
|
||||||
margin: -1px;
|
margin: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
background: var(--color-3-darkgray);
|
||||||
|
color: var(--color-a-softgray);
|
||||||
|
|
||||||
|
.icon-label {
|
||||||
|
fill: var(--color-a-softgray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.output {
|
||||||
|
outline: 3px solid var(--color-data-vector);
|
||||||
|
}
|
||||||
|
|
||||||
.primary {
|
.primary {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -385,6 +404,7 @@ export default defineComponent({
|
||||||
nodes: {
|
nodes: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
async handler() {
|
async handler() {
|
||||||
|
this.selected = this.selected.filter((id) => this.nodeGraph.state.nodes.find((node) => node.id === id));
|
||||||
await this.refreshLinks();
|
await this.refreshLinks();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,10 @@ export class FrontendNode {
|
||||||
|
|
||||||
@TupleToVec2
|
@TupleToVec2
|
||||||
readonly position!: XY | undefined;
|
readonly position!: XY | undefined;
|
||||||
|
|
||||||
|
readonly output!: boolean;
|
||||||
|
|
||||||
|
readonly disabled!: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FrontendNodeLink {
|
export class FrontendNodeLink {
|
||||||
|
|
|
||||||
|
|
@ -163,12 +163,18 @@ pub struct NodeNetwork {
|
||||||
pub inputs: Vec<NodeId>,
|
pub inputs: Vec<NodeId>,
|
||||||
pub output: NodeId,
|
pub output: NodeId,
|
||||||
pub nodes: HashMap<NodeId, DocumentNode>,
|
pub nodes: HashMap<NodeId, DocumentNode>,
|
||||||
|
/// These nodes are replaced with identity nodes when flattening
|
||||||
|
pub disabled: Vec<NodeId>,
|
||||||
|
/// In the case where a new node is chosen as output - what was the origional
|
||||||
|
pub previous_output: Option<NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeNetwork {
|
impl NodeNetwork {
|
||||||
pub fn map_ids(&mut self, f: impl Fn(NodeId) -> NodeId + Copy) {
|
pub fn map_ids(&mut self, f: impl Fn(NodeId) -> NodeId + Copy) {
|
||||||
self.inputs.iter_mut().for_each(|id| *id = f(*id));
|
self.inputs.iter_mut().for_each(|id| *id = f(*id));
|
||||||
self.output = f(self.output);
|
self.output = f(self.output);
|
||||||
|
self.disabled.iter_mut().for_each(|id| *id = f(*id));
|
||||||
|
self.previous_output = self.previous_output.map(f);
|
||||||
let mut empty = HashMap::new();
|
let mut empty = HashMap::new();
|
||||||
std::mem::swap(&mut self.nodes, &mut empty);
|
std::mem::swap(&mut self.nodes, &mut empty);
|
||||||
self.nodes = empty
|
self.nodes = empty
|
||||||
|
|
@ -204,6 +210,13 @@ impl NodeNetwork {
|
||||||
.remove_entry(&node)
|
.remove_entry(&node)
|
||||||
.unwrap_or_else(|| panic!("The node which was supposed to be flattened does not exist in the network, id {} network {:#?}", node, self));
|
.unwrap_or_else(|| panic!("The node which was supposed to be flattened does not exist in the network, id {} network {:#?}", node, self));
|
||||||
|
|
||||||
|
if self.disabled.contains(&id) {
|
||||||
|
node.implementation = DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode", &[generic!("T")]));
|
||||||
|
node.inputs.drain(1..);
|
||||||
|
self.nodes.insert(id, node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
match node.implementation {
|
match node.implementation {
|
||||||
DocumentNodeImplementation::Network(mut inner_network) => {
|
DocumentNodeImplementation::Network(mut inner_network) => {
|
||||||
// Connect all network inputs to either the parent network nodes, or newly created value nodes.
|
// Connect all network inputs to either the parent network nodes, or newly created value nodes.
|
||||||
|
|
@ -211,6 +224,7 @@ impl NodeNetwork {
|
||||||
let new_nodes = inner_network.nodes.keys().cloned().collect::<Vec<_>>();
|
let new_nodes = inner_network.nodes.keys().cloned().collect::<Vec<_>>();
|
||||||
// Copy nodes from the inner network into the parent network
|
// Copy nodes from the inner network into the parent network
|
||||||
self.nodes.extend(inner_network.nodes);
|
self.nodes.extend(inner_network.nodes);
|
||||||
|
self.disabled.extend(inner_network.disabled);
|
||||||
|
|
||||||
let mut network_offsets = HashMap::new();
|
let mut network_offsets = HashMap::new();
|
||||||
for (document_input, network_input) in node.inputs.into_iter().zip(inner_network.inputs.iter()) {
|
for (document_input, network_input) in node.inputs.into_iter().zip(inner_network.inputs.iter()) {
|
||||||
|
|
@ -305,6 +319,7 @@ mod test {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,6 +352,7 @@ mod test {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
assert_eq!(network, maped_add);
|
assert_eq!(network, maped_add);
|
||||||
}
|
}
|
||||||
|
|
@ -363,6 +379,7 @@ mod test {
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
network.flatten_with_fns(1, |self_id, inner_id| self_id * 10 + inner_id, gen_node_id);
|
network.flatten_with_fns(1, |self_id, inner_id| self_id * 10 + inner_id, gen_node_id);
|
||||||
let flat_network = flat_network();
|
let flat_network = flat_network();
|
||||||
|
|
@ -480,6 +497,7 @@ mod test {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ mod tests {
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +111,7 @@ mod tests {
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::executor::DynamicExecutor;
|
use crate::executor::DynamicExecutor;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue