Fix a lot of Clippy warnings (#1808)

* fix a lot of clippy warnings

* fix more clippy warnings

* fix yet more clippy warnings

* bump msrv to 1.70.0 to silence warnings

* fix a lot of clippy warnings

* fix more clippy warnings

* fix yet more clippy warnings

* fix a few more warnings

* fix a clippy warning

* remove a commented out line

* silense too many arguments error

* fix more clippy warnings

* prefix underscore to unused vars/functions to fix warnings

* use filter instead of map

* move raw-rs-tests feature flat to module level to fix unused imports warnings

* fix a couple of unused result warnings

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Raminder Singh 2024-07-09 17:32:52 +05:30 committed by GitHub
parent f7ada701e5
commit 62f73df048
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 264 additions and 260 deletions

View file

@ -87,7 +87,7 @@ mod test {
for message in messages { for message in messages {
block_on(crate::node_graph_executor::run_node_graph()); block_on(crate::node_graph_executor::run_node_graph());
let mut res = VecDeque::new(); let mut res = VecDeque::new();
editor.poll_node_graph_evaluation(&mut res); editor.poll_node_graph_evaluation(&mut res).expect("poll_node_graph_evaluation failed");
let res = editor.handle_message(message); let res = editor.handle_message(message);
responses.push(res); responses.push(res);

View file

@ -167,7 +167,7 @@ impl Dispatcher {
if let Some(document) = self.message_handlers.portfolio_message_handler.active_document() { if let Some(document) = self.message_handlers.portfolio_message_handler.active_document() {
let data = ToolMessageData { let data = ToolMessageData {
document_id: self.message_handlers.portfolio_message_handler.active_document_id().unwrap(), document_id: self.message_handlers.portfolio_message_handler.active_document_id().unwrap(),
document: document, document,
input: &self.message_handlers.input_preprocessor_message_handler, input: &self.message_handlers.input_preprocessor_message_handler,
persistent_data: &self.message_handlers.portfolio_message_handler.persistent_data, persistent_data: &self.message_handlers.portfolio_message_handler.persistent_data,
node_graph: &self.message_handlers.portfolio_message_handler.executor, node_graph: &self.message_handlers.portfolio_message_handler.executor,
@ -451,7 +451,8 @@ mod test {
let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler; let portfolio = &mut editor.dispatcher.message_handlers.portfolio_message_handler;
portfolio portfolio
.executor .executor
.submit_node_graph_evaluation(portfolio.documents.get_mut(&portfolio.active_document_id.unwrap()).unwrap(), glam::UVec2::ONE); .submit_node_graph_evaluation(portfolio.documents.get_mut(&portfolio.active_document_id.unwrap()).unwrap(), glam::UVec2::ONE)
.expect("submit_node_graph_evaluation failed");
crate::node_graph_executor::run_node_graph().await; crate::node_graph_executor::run_node_graph().await;
let mut messages = VecDeque::new(); let mut messages = VecDeque::new();
editor.poll_node_graph_evaluation(&mut messages).expect("Graph should render"); editor.poll_node_graph_evaluation(&mut messages).expect("Graph should render");

View file

@ -28,15 +28,11 @@ impl LayoutHolder for DemoArtworkDialog {
fn layout(&self) -> Layout { fn layout(&self) -> Layout {
let mut rows_of_images_with_buttons: Vec<_> = ARTWORK let mut rows_of_images_with_buttons: Vec<_> = ARTWORK
.chunks(3) .chunks(3)
.into_iter() .flat_map(|chunk| {
.map(|chunk| { let images = chunk.iter().map(|(_, thumbnail, _)| ImageLabel::new(*thumbnail).width(Some("256px".into())).widget_holder()).collect();
let images = chunk
.into_iter()
.map(|(_, thumbnail, _)| ImageLabel::new(*thumbnail).width(Some("256px".into())).widget_holder())
.collect();
let buttons = chunk let buttons = chunk
.into_iter() .iter()
.map(|(name, _, filename)| { .map(|(name, _, filename)| {
TextButton::new(*name) TextButton::new(*name)
.min_width(256) .min_width(256)
@ -56,7 +52,6 @@ impl LayoutHolder for DemoArtworkDialog {
vec![LayoutGroup::Row { widgets: images }, LayoutGroup::Row { widgets: buttons }, LayoutGroup::Row { widgets: vec![] }] vec![LayoutGroup::Row { widgets: images }, LayoutGroup::Row { widgets: buttons }, LayoutGroup::Row { widgets: vec![] }]
}) })
.flatten()
.collect(); .collect();
let _ = rows_of_images_with_buttons.pop(); let _ = rows_of_images_with_buttons.pop();

View file

@ -69,12 +69,12 @@ impl ScrollDelta {
} }
pub fn as_dvec2(&self) -> DVec2 { pub fn as_dvec2(&self) -> DVec2 {
DVec2::new(self.x as f64, self.y as f64) DVec2::new(self.x, self.y)
} }
pub fn scroll_delta(&self) -> f64 { pub fn scroll_delta(&self) -> f64 {
let (dx, dy) = (self.x, self.y); let (dx, dy) = (self.x, self.y);
dy.signum() as f64 * ((dy * dy + f64::min(dy.abs(), dx.abs()).powi(2)) as f64).sqrt() dy.signum() * (dy * dy + f64::min(dy.abs(), dx.abs()).powi(2)).sqrt()
} }
} }

View file

@ -105,6 +105,12 @@ impl KeyMappingEntries {
} }
} }
impl Default for KeyMappingEntries {
fn default() -> Self {
Self::new()
}
}
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
pub struct MappingEntry { pub struct MappingEntry {
/// Serves two purposes: /// Serves two purposes:

View file

@ -161,11 +161,11 @@ impl LayoutMessageHandler {
Widget::DropdownInput(dropdown_input) => { Widget::DropdownInput(dropdown_input) => {
let callback_message = match action { let callback_message = match action {
WidgetValueAction::Commit => { WidgetValueAction::Commit => {
let update_value = value.as_u64().expect(&format!("DropdownInput commit was not of type `u64`, found {value:?}")); let update_value = value.as_u64().unwrap_or_else(|| panic!("DropdownInput commit was not of type `u64`, found {value:?}"));
(dropdown_input.entries.iter().flatten().nth(update_value as usize).unwrap().on_commit.callback)(&()) (dropdown_input.entries.iter().flatten().nth(update_value as usize).unwrap().on_commit.callback)(&())
} }
WidgetValueAction::Update => { WidgetValueAction::Update => {
let update_value = value.as_u64().expect(&format!("DropdownInput update was not of type `u64`, found {value:?}")); let update_value = value.as_u64().unwrap_or_else(|| panic!("DropdownInput update was not of type `u64`, found {value:?}"));
dropdown_input.selected_index = Some(update_value as u32); dropdown_input.selected_index = Some(update_value as u32);
(dropdown_input.entries.iter().flatten().nth(update_value as usize).unwrap().on_update.callback)(&()) (dropdown_input.entries.iter().flatten().nth(update_value as usize).unwrap().on_update.callback)(&())
} }

View file

@ -186,7 +186,7 @@ impl WidgetLayout {
// TODO: Diff insersion and deletion of items // TODO: Diff insersion and deletion of items
if self.layout.len() != new.layout.len() { if self.layout.len() != new.layout.len() {
// Update the layout to the new layout // Update the layout to the new layout
self.layout = new.layout.clone(); self.layout.clone_from(&new.layout);
// Push an update sublayout to the diff // Push an update sublayout to the diff
let new = DiffUpdate::SubLayout(new.layout); let new = DiffUpdate::SubLayout(new.layout);
@ -342,7 +342,7 @@ impl LayoutGroup {
Widget::InvisibleStandinInput(_) | Widget::PivotInput(_) | Widget::RadioInput(_) | Widget::Separator(_) | Widget::WorkingColorsInput(_) => continue, Widget::InvisibleStandinInput(_) | Widget::PivotInput(_) | Widget::RadioInput(_) | Widget::Separator(_) | Widget::WorkingColorsInput(_) => continue,
}; };
if val.is_empty() { if val.is_empty() {
*val = tooltip.clone(); val.clone_from(&tooltip);
} }
} }
if is_col { if is_col {
@ -361,7 +361,7 @@ impl LayoutGroup {
// TODO: Diff insersion and deletion of items // TODO: Diff insersion and deletion of items
if current_widgets.len() != new_widgets.len() { if current_widgets.len() != new_widgets.len() {
// Update to the new value // Update to the new value
*current_widgets = new_widgets.clone(); current_widgets.clone_from(&new_widgets);
// Push back a LayoutGroup update to the diff // Push back a LayoutGroup update to the diff
let new_value = DiffUpdate::LayoutGroup(if is_column { Self::Column { widgets: new_widgets } } else { Self::Row { widgets: new_widgets } }); let new_value = DiffUpdate::LayoutGroup(if is_column { Self::Column { widgets: new_widgets } } else { Self::Row { widgets: new_widgets } });
@ -394,10 +394,10 @@ impl LayoutGroup {
// TODO: Diff insersion and deletion of items // TODO: Diff insersion and deletion of items
if current_layout.len() != new_layout.len() || *current_name != new_name || *current_visible != new_visible || *current_id != new_id { if current_layout.len() != new_layout.len() || *current_name != new_name || *current_visible != new_visible || *current_id != new_id {
// Update self to reflect new changes // Update self to reflect new changes
*current_name = new_name.clone(); current_name.clone_from(&new_name);
*current_visible = new_visible; *current_visible = new_visible;
*current_id = new_id; *current_id = new_id;
*current_layout = new_layout.clone(); current_layout.clone_from(&new_layout);
// Push an update layout group to the diff // Push an update layout group to the diff
let new_value = DiffUpdate::LayoutGroup(Self::Section { let new_value = DiffUpdate::LayoutGroup(Self::Section {

View file

@ -187,7 +187,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
node_graph_ptz: &mut self.node_graph_ptz, node_graph_ptz: &mut self.node_graph_ptz,
graph_view_overlay_open: self.graph_view_overlay_open, graph_view_overlay_open: self.graph_view_overlay_open,
node_graph_handler: &self.node_graph_handler, node_graph_handler: &self.node_graph_handler,
node_graph_to_viewport: &self.node_graph_to_viewport.entry(self.node_graph_handler.network.clone()).or_insert(DAffine2::IDENTITY), node_graph_to_viewport: self.node_graph_to_viewport.entry(self.node_graph_handler.network.clone()).or_insert(DAffine2::IDENTITY),
}; };
self.navigation_handler.process_message(message, responses, data); self.navigation_handler.process_message(message, responses, data);
@ -221,7 +221,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
collapsed: &mut self.collapsed, collapsed: &mut self.collapsed,
ipp, ipp,
graph_view_overlay_open: self.graph_view_overlay_open, graph_view_overlay_open: self.graph_view_overlay_open,
node_graph_to_viewport: &self.node_graph_to_viewport.entry(self.node_graph_handler.network.clone()).or_insert(DAffine2::IDENTITY), node_graph_to_viewport: self.node_graph_to_viewport.entry(self.node_graph_handler.network.clone()).or_insert(DAffine2::IDENTITY),
}, },
); );
} }
@ -384,7 +384,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
// TODO: Update click targets when node graph is closed so that this is not necessary // TODO: Update click targets when node graph is closed so that this is not necessary
if self.graph_view_overlay_open { if self.graph_view_overlay_open {
self.node_graph_handler.update_all_click_targets(&mut self.network, self.node_graph_handler.network.clone()) self.node_graph_handler.update_all_click_targets(&self.network, self.node_graph_handler.network.clone())
} }
responses.add(FrontendMessage::TriggerGraphViewOverlay { open }); responses.add(FrontendMessage::TriggerGraphViewOverlay { open });
@ -606,7 +606,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
// Reconnect layer_to_move to new parent at insert index. // Reconnect layer_to_move to new parent at insert index.
responses.add(GraphOperationMessage::InsertNodeAtStackIndex { responses.add(GraphOperationMessage::InsertNodeAtStackIndex {
node_id: layer_to_move.to_node(), node_id: layer_to_move.to_node(),
parent: parent, parent,
insert_index, insert_index,
}); });
} }
@ -1047,13 +1047,13 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
}); });
// Get the node that feeds into the primary input for the folder (if it exists) // Get the node that feeds into the primary input for the folder (if it exists)
if let Some(NodeInput::Node { node_id, .. }) = self.network.nodes.get(&folder.to_node()).expect("Folder should always exist").inputs.get(0) { if let Some(NodeInput::Node { node_id, .. }) = self.network.nodes.get(&folder.to_node()).expect("Folder should always exist").inputs.first() {
let upstream_sibling_id = *node_id; let upstream_sibling_id = *node_id;
// Get the node at the bottom of the first layer node stack // Get the node at the bottom of the first layer node stack
let mut last_child_node_id = child_layer.to_node(); let mut last_child_node_id = child_layer.to_node();
loop { loop {
let Some(NodeInput::Node { node_id, .. }) = self.network.nodes.get(&last_child_node_id).expect("Child node should always exist").inputs.get(0) else { let Some(NodeInput::Node { node_id, .. }) = self.network.nodes.get(&last_child_node_id).expect("Child node should always exist").inputs.first() else {
break; break;
}; };
last_child_node_id = *node_id; last_child_node_id = *node_id;
@ -1276,7 +1276,7 @@ impl DocumentMessageHandler {
self.selected_nodes self.selected_nodes
.selected_nodes(network) .selected_nodes(network)
.filter_map(|node| { .filter_map(|node| {
let Some(node_metadata) = self.node_graph_handler.node_metadata.get(&node) else { let Some(node_metadata) = self.node_graph_handler.node_metadata.get(node) else {
log::debug!("Could not get click target for node {node}"); log::debug!("Could not get click target for node {node}");
return None; return None;
}; };
@ -1437,7 +1437,7 @@ impl DocumentMessageHandler {
// Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents // Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents
responses.add(PortfolioMessage::UpdateOpenDocumentsList); responses.add(PortfolioMessage::UpdateOpenDocumentsList);
// If there is no history return and don't broadcast SelectionChanged // If there is no history return and don't broadcast SelectionChanged
let Some(network) = self.document_undo_history.pop_back() else { return None }; let network = self.document_undo_history.pop_back()?;
responses.add(BroadcastEvent::SelectionChanged); responses.add(BroadcastEvent::SelectionChanged);
@ -1460,7 +1460,7 @@ impl DocumentMessageHandler {
// Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents // Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents
responses.add(PortfolioMessage::UpdateOpenDocumentsList); responses.add(PortfolioMessage::UpdateOpenDocumentsList);
// If there is no history return and don't broadcast SelectionChanged // If there is no history return and don't broadcast SelectionChanged
let Some(network) = self.document_redo_history.pop_back() else { return None }; let network = self.document_redo_history.pop_back()?;
responses.add(BroadcastEvent::SelectionChanged); responses.add(BroadcastEvent::SelectionChanged);
@ -1480,9 +1480,9 @@ impl DocumentMessageHandler {
}; };
for (node_id, current_node) in &network.nodes { for (node_id, current_node) in &network.nodes {
if let Some(previous_node) = previous_nested_network.nodes.get(&node_id) { if let Some(previous_node) = previous_nested_network.nodes.get(node_id) {
if previous_node.alias == current_node.alias if previous_node.alias == current_node.alias
&& previous_node.inputs.iter().map(|node_input| node_input.is_exposed()).count() == current_node.inputs.iter().map(|node_input| node_input.is_exposed()).count() && previous_node.inputs.iter().filter(|node_input| node_input.is_exposed()).count() == current_node.inputs.iter().filter(|node_input| node_input.is_exposed()).count()
&& previous_node.is_layer == current_node.is_layer && previous_node.is_layer == current_node.is_layer
&& previous_node.metadata.position == current_node.metadata.position && previous_node.metadata.position == current_node.metadata.position
{ {
@ -1542,9 +1542,7 @@ impl DocumentMessageHandler {
}; };
// Downstream layer should always exist // Downstream layer should always exist
let Some((downstream_layer_node_id, downstream_layer_is_parent)) = downstream_layer else { let (downstream_layer_node_id, downstream_layer_is_parent) = downstream_layer?;
return None;
};
// Horizontal traversal if layer_to_move is the top of its layer stack, primary traversal if not // Horizontal traversal if layer_to_move is the top of its layer stack, primary traversal if not
let flow_type = if downstream_layer_is_parent { FlowType::HorizontalFlow } else { FlowType::PrimaryFlow }; let flow_type = if downstream_layer_is_parent { FlowType::HorizontalFlow } else { FlowType::PrimaryFlow };
@ -2105,11 +2103,12 @@ impl DocumentMessageHandler {
fn root_network() -> NodeNetwork { fn root_network() -> NodeNetwork {
{ {
let mut network = NodeNetwork::default(); NodeNetwork {
network.exports = vec![NodeInput::Value { exports: vec![NodeInput::Value {
tagged_value: TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY), tagged_value: TaggedValue::ArtboardGroup(graphene_core::ArtboardGroup::EMPTY),
exposed: true, exposed: true,
}]; }],
network ..Default::default()
}
} }
} }

View file

@ -91,7 +91,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
}), }),
(Some(downstream_node), None) => responses.add(GraphOperationMessage::SetNodeInput { (Some(downstream_node), None) => responses.add(GraphOperationMessage::SetNodeInput {
node_id: downstream_node, node_id: downstream_node,
input_index: input_index, input_index,
input: NodeInput::node(*new_layer_id, 0), input: NodeInput::node(*new_layer_id, 0),
}), }),
(None, Some(upstream_node)) => responses.add(GraphOperationMessage::InsertNodeBetween { (None, Some(upstream_node)) => responses.add(GraphOperationMessage::InsertNodeBetween {
@ -215,20 +215,20 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
}; };
responses.add(GraphOperationMessage::ShiftUpstream { responses.add(GraphOperationMessage::ShiftUpstream {
node_id: node_id, node_id,
shift: offset_to_post_node, shift: offset_to_post_node,
shift_self: true, shift_self: true,
}); });
match (post_node_id, pre_node_id) { match (post_node_id, pre_node_id) {
(Some(post_node_id), Some(pre_node_id)) => responses.add(GraphOperationMessage::InsertNodeBetween { (Some(post_node_id), Some(pre_node_id)) => responses.add(GraphOperationMessage::InsertNodeBetween {
post_node_id: post_node_id, post_node_id,
post_node_input_index: post_node_input_index, post_node_input_index,
insert_node_output_index: 0, insert_node_output_index: 0,
insert_node_id: node_id, insert_node_id: node_id,
insert_node_input_index: 0, insert_node_input_index: 0,
pre_node_output_index: 0, pre_node_output_index: 0,
pre_node_id: pre_node_id, pre_node_id,
}), }),
(None, Some(pre_node_id)) => responses.add(GraphOperationMessage::InsertNodeBetween { (None, Some(pre_node_id)) => responses.add(GraphOperationMessage::InsertNodeBetween {
post_node_id: document_network.exports_metadata.0, post_node_id: document_network.exports_metadata.0,
@ -237,7 +237,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
insert_node_id: node_id, insert_node_id: node_id,
insert_node_input_index: 0, insert_node_input_index: 0,
pre_node_output_index: 0, pre_node_output_index: 0,
pre_node_id: pre_node_id, pre_node_id,
}), }),
(Some(post_node_id), None) => responses.add(GraphOperationMessage::SetNodeInput { (Some(post_node_id), None) => responses.add(GraphOperationMessage::SetNodeInput {
node_id: post_node_id, node_id: post_node_id,
@ -253,13 +253,13 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
// Shift stack down, starting at the moved node. // Shift stack down, starting at the moved node.
responses.add(GraphOperationMessage::ShiftUpstream { responses.add(GraphOperationMessage::ShiftUpstream {
node_id: node_id, node_id,
shift: IVec2::new(0, 3), shift: IVec2::new(0, 3),
shift_self: true, shift_self: true,
}); });
} }
GraphOperationMessage::InsertBooleanOperation { operation } => { GraphOperationMessage::InsertBooleanOperation { operation } => {
let mut selected_layers = selected_nodes.selected_layers(&document_metadata); let mut selected_layers = selected_nodes.selected_layers(document_metadata);
let upper_layer = selected_layers.next(); let upper_layer = selected_layers.next();
let lower_layer = selected_layers.next(); let lower_layer = selected_layers.next();
@ -466,7 +466,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
} }
} }
GraphOperationMessage::MoveSelectedSiblingsToChild { new_parent } => { GraphOperationMessage::MoveSelectedSiblingsToChild { new_parent } => {
let Some(group_parent) = new_parent.parent(&document_metadata) else { let Some(group_parent) = new_parent.parent(document_metadata) else {
log::error!("Could not find parent for layer {:?}", new_parent); log::error!("Could not find parent for layer {:?}", new_parent);
return; return;
}; };
@ -475,7 +475,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
let mut selected_siblings = Vec::new(); let mut selected_siblings = Vec::new();
// Skip over horizontal non layer node chain that feeds into parent // Skip over horizontal non layer node chain that feeds into parent
let Some(mut current_stack_node_id) = group_parent.first_child(&document_metadata).and_then(|current_stack_node| Some(current_stack_node.to_node())) else { let Some(mut current_stack_node_id) = group_parent.first_child(document_metadata).map(|current_stack_node| current_stack_node.to_node()) else {
log::error!("Folder should always have child"); log::error!("Folder should always have child");
return; return;
}; };
@ -486,14 +486,14 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
// Check if the current stack node is a selected layer // Check if the current stack node is a selected layer
if selected_nodes if selected_nodes
.selected_layers(&document_metadata) .selected_layers(document_metadata)
.any(|selected_node_id| selected_node_id.to_node() == *current_stack_node_id) .any(|selected_node_id| selected_node_id.to_node() == *current_stack_node_id)
{ {
selected_siblings.push(*current_stack_node_id); selected_siblings.push(*current_stack_node_id);
// Push all non layer sibling nodes directly upstream of the selected layer // Push all non layer sibling nodes directly upstream of the selected layer
loop { loop {
let Some(NodeInput::Node { node_id, .. }) = current_stack_node.inputs.get(0) else { break }; let Some(NodeInput::Node { node_id, .. }) = current_stack_node.inputs.first() else { break };
let next_node = document_network.nodes.get(node_id).expect("Stack node id should always be a node"); let next_node = document_network.nodes.get(node_id).expect("Stack node id should always be a node");
@ -510,7 +510,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
} }
// Get next node // Get next node
let Some(NodeInput::Node { node_id, .. }) = current_stack_node.inputs.get(0) else { break }; let Some(NodeInput::Node { node_id, .. }) = current_stack_node.inputs.first() else { break };
*current_stack_node_id = *node_id; *current_stack_node_id = *node_id;
} }
@ -567,7 +567,7 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
let new_ids: HashMap<_, _> = nodes.iter().map(|(&id, _)| (id, NodeId(generate_uuid()))).collect(); let new_ids: HashMap<_, _> = nodes.iter().map(|(&id, _)| (id, NodeId(generate_uuid()))).collect();
if let Some(node) = modify_inputs.document_network.nodes.get_mut(&id) { if let Some(node) = modify_inputs.document_network.nodes.get_mut(&id) {
node.alias = alias.clone(); node.alias.clone_from(&alias);
} }
let shift = nodes let shift = nodes
@ -703,9 +703,9 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::StartTransaction);
// If any of the selected nodes are hidden, show them all. Otherwise, hide them all. // If any of the selected nodes are hidden, show them all. Otherwise, hide them all.
let visible = !selected_nodes.selected_layers(&document_metadata).all(|layer| document_metadata.node_is_visible(layer.to_node())); let visible = !selected_nodes.selected_layers(document_metadata).all(|layer| document_metadata.node_is_visible(layer.to_node()));
for layer in selected_nodes.selected_layers(&document_metadata) { for layer in selected_nodes.selected_layers(document_metadata) {
responses.add(GraphOperationMessage::SetVisibility { node_id: layer.to_node(), visible }); responses.add(GraphOperationMessage::SetVisibility { node_id: layer.to_node(), visible });
} }
} }
@ -738,9 +738,9 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageData<'_>> for Gr
responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::StartTransaction);
// If any of the selected nodes are locked, show them all. Otherwise, hide them all. // If any of the selected nodes are locked, show them all. Otherwise, hide them all.
let locked = !selected_nodes.selected_layers(&document_metadata).all(|layer| document_metadata.node_is_locked(layer.to_node())); let locked = !selected_nodes.selected_layers(document_metadata).all(|layer| document_metadata.node_is_locked(layer.to_node()));
for layer in selected_nodes.selected_layers(&document_metadata) { for layer in selected_nodes.selected_layers(document_metadata) {
responses.add(GraphOperationMessage::SetLocked { node_id: layer.to_node(), locked }); responses.add(GraphOperationMessage::SetLocked { node_id: layer.to_node(), locked });
} }
} }

View file

@ -75,6 +75,7 @@ impl<'a> ModifyInputsContext<'a> {
update_input(&mut document_node.inputs, node_id, self.document_metadata); update_input(&mut document_node.inputs, node_id, self.document_metadata);
} }
#[allow(clippy::too_many_arguments)]
pub fn insert_between( pub fn insert_between(
node_graph: &mut NodeGraphMessageHandler, node_graph: &mut NodeGraphMessageHandler,
document_network: &mut NodeNetwork, document_network: &mut NodeNetwork,
@ -154,7 +155,7 @@ impl<'a> ModifyInputsContext<'a> {
/// ↑ if skip_layer_nodes == 1, return (Layer1, Some(Layer2), 0) /// ↑ if skip_layer_nodes == 1, return (Layer1, Some(Layer2), 0)
/// -> Layer2 input_index: 2 /// -> Layer2 input_index: 2
/// ↑ /// ↑
/// -> NonLayerNode /// -> NonLayerNode
/// ↑ if skip_layer_nodes == 2, return (NonLayerNode, Some(Layer3), 0) /// ↑ if skip_layer_nodes == 2, return (NonLayerNode, Some(Layer3), 0)
/// -> Layer3 input_index: 3 /// -> Layer3 input_index: 3
/// if skip_layer_nodes == 3, return (Layer3, None, 0) /// if skip_layer_nodes == 3, return (Layer3, None, 0)
@ -189,7 +190,7 @@ impl<'a> ModifyInputsContext<'a> {
.expect("Post node should always exist") .expect("Post node should always exist")
.inputs .inputs
.get(post_node_input_index) .get(post_node_input_index)
.and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(node_id.clone()) } else { None }); .and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(*node_id) } else { None });
if let Some(next_node_in_stack_id) = next_node_in_stack_id { if let Some(next_node_in_stack_id) = next_node_in_stack_id {
// Only increment index for layer nodes // Only increment index for layer nodes
@ -213,7 +214,7 @@ impl<'a> ModifyInputsContext<'a> {
let mut pre_node_id = post_node let mut pre_node_id = post_node
.inputs .inputs
.get(post_node_input_index) .get(post_node_input_index)
.and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(node_id.clone()) } else { None }); .and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(*node_id) } else { None });
// Skip until pre_node is either a layer or does not exist // Skip until pre_node is either a layer or does not exist
while let Some(pre_node_id_value) = pre_node_id { while let Some(pre_node_id_value) = pre_node_id {
@ -223,8 +224,8 @@ impl<'a> ModifyInputsContext<'a> {
post_node_id = pre_node_id_value; post_node_id = pre_node_id_value;
pre_node_id = post_node pre_node_id = post_node
.inputs .inputs
.get(0) .first()
.and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(node_id.clone()) } else { None }); .and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(*node_id) } else { None });
post_node_input_index = 0; post_node_input_index = 0;
} else { } else {
break; break;
@ -246,7 +247,7 @@ impl<'a> ModifyInputsContext<'a> {
// If the current root node is the artboard, then the new layer should be a child of the artboard // If the current root node is the artboard, then the new layer should be a child of the artboard
let current_root_node = self.document_network.nodes.get(&root_node.id).expect("Root node should always exist"); let current_root_node = self.document_network.nodes.get(&root_node.id).expect("Root node should always exist");
if current_root_node.is_artboard() && current_root_node.is_layer { if current_root_node.is_artboard() && current_root_node.is_layer {
parent = LayerNodeIdentifier::new(root_node.id, &self.document_network); parent = LayerNodeIdentifier::new(root_node.id, self.document_network);
} }
} }
} }
@ -358,7 +359,7 @@ impl<'a> ModifyInputsContext<'a> {
responses.add(NodeGraphMessage::RunDocumentGraph); responses.add(NodeGraphMessage::RunDocumentGraph);
} }
pub fn shift_upstream(node_graph: &mut NodeGraphMessageHandler, document_network: &mut NodeNetwork, network_path: &Vec<NodeId>, node_id: NodeId, shift: IVec2, shift_self: bool) { pub fn shift_upstream(node_graph: &mut NodeGraphMessageHandler, document_network: &mut NodeNetwork, network_path: &[NodeId], node_id: NodeId, shift: IVec2, shift_self: bool) {
let Some(network) = document_network.nested_network(network_path) else { let Some(network) = document_network.nested_network(network_path) else {
log::error!("Could not get nested network for shift_upstream"); log::error!("Could not get nested network for shift_upstream");
return; return;
@ -383,7 +384,7 @@ impl<'a> ModifyInputsContext<'a> {
for node_id in shift_nodes { for node_id in shift_nodes {
if let Some(node) = document_network.nodes.get_mut(&node_id) { if let Some(node) = document_network.nodes.get_mut(&node_id) {
node.metadata.position += shift; node.metadata.position += shift;
node_graph.update_click_target(node_id, document_network, network_path.clone()); node_graph.update_click_target(node_id, document_network, network_path.to_owned());
} }
} }
} }
@ -391,7 +392,7 @@ impl<'a> ModifyInputsContext<'a> {
/// Inserts a new node and modifies the inputs /// Inserts a new node and modifies the inputs
pub fn modify_new_node(&mut self, name: &'static str, update_input: impl FnOnce(&mut Vec<NodeInput>, NodeId, &DocumentMetadata)) { pub fn modify_new_node(&mut self, name: &'static str, update_input: impl FnOnce(&mut Vec<NodeInput>, NodeId, &DocumentMetadata)) {
let output_node_id = self.layer_node.or_else(|| { let output_node_id = self.layer_node.or_else(|| {
if let Some(NodeInput::Node { node_id, .. }) = self.document_network.exports.get(0) { if let Some(NodeInput::Node { node_id, .. }) = self.document_network.exports.first() {
Some(*node_id) Some(*node_id)
} else { } else {
log::error!("Could not modify new node with empty network"); log::error!("Could not modify new node with empty network");
@ -489,7 +490,7 @@ impl<'a> ModifyInputsContext<'a> {
self.document_network self.document_network
.exports .exports
.iter() .iter()
.filter_map(|output| if let NodeInput::Node { node_id, .. } = output { Some(node_id.clone()) } else { None }) .filter_map(|output| if let NodeInput::Node { node_id, .. } = output { Some(*node_id) } else { None })
.collect() .collect()
}, },
|id| vec![id], |id| vec![id],
@ -516,7 +517,7 @@ impl<'a> ModifyInputsContext<'a> {
pub fn set_input( pub fn set_input(
node_graph: &mut NodeGraphMessageHandler, node_graph: &mut NodeGraphMessageHandler,
document_network: &mut NodeNetwork, document_network: &mut NodeNetwork,
network_path: &Vec<NodeId>, network_path: &[NodeId],
node_id: NodeId, node_id: NodeId,
input_index: usize, input_index: usize,
input: NodeInput, input: NodeInput,
@ -537,7 +538,7 @@ impl<'a> ModifyInputsContext<'a> {
*node_input = input; *node_input = input;
let currently_exposed = node_input.is_exposed(); let currently_exposed = node_input.is_exposed();
if previously_exposed != currently_exposed { if previously_exposed != currently_exposed {
node_graph.update_click_target(node_id, document_network, network_path.clone()); node_graph.update_click_target(node_id, document_network, network_path.to_owned());
} }
// Only load network structure for changes to document_network // Only load network structure for changes to document_network
@ -563,7 +564,7 @@ impl<'a> ModifyInputsContext<'a> {
} }
if previously_exposed != currently_exposed { if previously_exposed != currently_exposed {
node_graph.update_click_target(node_id, document_network, network_path.clone()); node_graph.update_click_target(node_id, document_network, network_path.to_owned());
} }
// Only load network structure for changes to document_network // Only load network structure for changes to document_network
@ -719,7 +720,7 @@ impl<'a> ModifyInputsContext<'a> {
if !reconnect { if !reconnect {
continue; continue;
}; };
let Some(node) = network.nodes.get(&node_id) else { let Some(node) = network.nodes.get(node_id) else {
continue; continue;
}; };
let child_id = node.inputs.get(1).and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(node_id) } else { None }); let child_id = node.inputs.get(1).and_then(|input| if let NodeInput::Node { node_id, .. } = input { Some(node_id) } else { None });
@ -750,8 +751,8 @@ impl<'a> ModifyInputsContext<'a> {
// Continue traversing over the downstream sibling, which happens if the current node is a sibling to a node in node_ids // Continue traversing over the downstream sibling, which happens if the current node is a sibling to a node in node_ids
else { else {
for deleted_node_id in &node_ids { for deleted_node_id in &node_ids {
let Some(output_node) = network.nodes.get(&deleted_node_id) else { continue }; let Some(output_node) = network.nodes.get(deleted_node_id) else { continue };
let Some(input) = output_node.inputs.get(0) else { continue }; let Some(input) = output_node.inputs.first() else { continue };
if let NodeInput::Node { node_id, .. } = input { if let NodeInput::Node { node_id, .. } = input {
if *node_id == current_node { if *node_id == current_node {
@ -793,24 +794,24 @@ impl<'a> ModifyInputsContext<'a> {
node_id: NodeId, node_id: NodeId,
reconnect: bool, reconnect: bool,
responses: &mut VecDeque<Message>, responses: &mut VecDeque<Message>,
network_path: &Vec<NodeId>, network_path: &[NodeId],
) -> bool { ) -> bool {
if !ModifyInputsContext::remove_references_from_network(node_graph, document_network, node_id, reconnect, &network_path) { if !ModifyInputsContext::remove_references_from_network(node_graph, document_network, node_id, reconnect, network_path) {
log::error!("could not remove_references_from_network"); log::error!("could not remove_references_from_network");
return false; return false;
} }
let Some(network) = document_network.nested_network_mut(&network_path) else { return false }; let Some(network) = document_network.nested_network_mut(network_path) else { return false };
network.nodes.remove(&node_id); network.nodes.remove(&node_id);
selected_nodes.retain_selected_nodes(|&id| id != node_id || id == network.exports_metadata.0 || id == network.imports_metadata.0); selected_nodes.retain_selected_nodes(|&id| id != node_id || id == network.exports_metadata.0 || id == network.imports_metadata.0);
node_graph.update_click_target(node_id, document_network, network_path.clone()); node_graph.update_click_target(node_id, document_network, network_path.to_owned());
responses.add(BroadcastEvent::SelectionChanged); responses.add(BroadcastEvent::SelectionChanged);
true true
} }
pub fn remove_references_from_network(node_graph: &mut NodeGraphMessageHandler, document_network: &mut NodeNetwork, deleting_node_id: NodeId, reconnect: bool, network_path: &Vec<NodeId>) -> bool { pub fn remove_references_from_network(node_graph: &mut NodeGraphMessageHandler, document_network: &mut NodeNetwork, deleting_node_id: NodeId, reconnect: bool, network_path: &[NodeId]) -> bool {
let Some(network) = document_network.nested_network(network_path) else { return false }; let Some(network) = document_network.nested_network(network_path) else { return false };
let mut reconnect_to_input: Option<NodeInput> = None; let mut reconnect_to_input: Option<NodeInput> = None;
@ -818,7 +819,7 @@ impl<'a> ModifyInputsContext<'a> {
// Check whether the being-deleted node's first (primary) input is a node // Check whether the being-deleted node's first (primary) input is a node
if let Some(node) = network.nodes.get(&deleting_node_id) { if let Some(node) = network.nodes.get(&deleting_node_id) {
// Reconnect to the node below when deleting a layer node. // Reconnect to the node below when deleting a layer node.
if matches!(&node.inputs.get(0), Some(NodeInput::Node { .. })) || matches!(&node.inputs.get(0), Some(NodeInput::Network { .. })) { if matches!(&node.inputs.first(), Some(NodeInput::Node { .. })) || matches!(&node.inputs.first(), Some(NodeInput::Network { .. })) {
reconnect_to_input = Some(node.inputs[0].clone()); reconnect_to_input = Some(node.inputs[0].clone());
} }
} }
@ -874,11 +875,12 @@ impl<'a> ModifyInputsContext<'a> {
//let Some(network) = document_network.nested_network(network_path) else { return false }; //let Some(network) = document_network.nested_network(network_path) else { return false };
if let Some(Previewing::Yes { root_node_to_restore }) = document_network.nested_network(network_path).map(|network| &network.previewing) { if let Some(Previewing::Yes {
if let Some(root_node_to_restore) = root_node_to_restore { root_node_to_restore: Some(root_node_to_restore),
if root_node_to_restore.id == deleting_node_id { }) = document_network.nested_network(network_path).map(|network| &network.previewing)
document_network.nested_network_mut(network_path).unwrap().start_previewing_without_restore(); {
} if root_node_to_restore.id == deleting_node_id {
document_network.nested_network_mut(network_path).unwrap().start_previewing_without_restore();
} }
} }
@ -942,14 +944,14 @@ impl<'a> ModifyInputsContext<'a> {
} }
/// Get the [`Type`] for any `node_id` and `input_index`. The `network_path` is the path to the encapsulating node (including the encapsulating node). The `node_id` is the selected node. /// Get the [`Type`] for any `node_id` and `input_index`. The `network_path` is the path to the encapsulating node (including the encapsulating node). The `node_id` is the selected node.
pub fn get_input_type(document_network: &NodeNetwork, network_path: &Vec<NodeId>, node_id: NodeId, resolved_types: &ResolvedDocumentNodeTypes, input_index: usize) -> Type { pub fn get_input_type(document_network: &NodeNetwork, network_path: &[NodeId], node_id: NodeId, resolved_types: &ResolvedDocumentNodeTypes, input_index: usize) -> Type {
let Some(network) = document_network.nested_network(&network_path) else { let Some(network) = document_network.nested_network(network_path) else {
log::error!("Could not get network in get_tagged_value"); log::error!("Could not get network in get_tagged_value");
return concrete!(()); return concrete!(());
}; };
// TODO: Store types for all document nodes, not just the compiled proto nodes, which currently skips isolated nodes // TODO: Store types for all document nodes, not just the compiled proto nodes, which currently skips isolated nodes
let node_id_path = &[&network_path[..], &[node_id]].concat(); let node_id_path = &[network_path, &[node_id]].concat();
let input_type = resolved_types.inputs.get(&graph_craft::document::Source { let input_type = resolved_types.inputs.get(&graph_craft::document::Source {
node: node_id_path.clone(), node: node_id_path.clone(),
index: input_index, index: input_index,
@ -959,18 +961,18 @@ impl<'a> ModifyInputsContext<'a> {
input_type.clone() input_type.clone()
} else if node_id == network.exports_metadata.0 { } else if node_id == network.exports_metadata.0 {
if let Some(parent_node_id) = network_path.last() { if let Some(parent_node_id) = network_path.last() {
let mut parent_path = network_path.clone(); let mut parent_path = network_path.to_owned();
parent_path.pop(); parent_path.pop();
let parent_node = document_network let parent_node = document_network
.nested_network(&parent_path) .nested_network(&parent_path)
.expect("Parent path should always exist") .expect("Parent path should always exist")
.nodes .nodes
.get(&parent_node_id) .get(parent_node_id)
.expect("Last path node should always exist in parent network"); .expect("Last path node should always exist in parent network");
let output_types = NodeGraphMessageHandler::get_output_types(parent_node, &resolved_types, network_path); let output_types = NodeGraphMessageHandler::get_output_types(parent_node, resolved_types, network_path);
output_types.iter().nth(input_index).map_or_else( output_types.get(input_index).map_or_else(
|| { || {
warn!("Could not find output type for export node {node_id}"); warn!("Could not find output type for export node {node_id}");
concrete!(()) concrete!(())
@ -992,7 +994,7 @@ impl<'a> ModifyInputsContext<'a> {
fn get_type_from_node(node: &DocumentNode, input_index: usize) -> Type { fn get_type_from_node(node: &DocumentNode, input_index: usize) -> Type {
match &node.implementation { match &node.implementation {
DocumentNodeImplementation::ProtoNode(protonode) => { DocumentNodeImplementation::ProtoNode(protonode) => {
let Some(node_io_hashmap) = NODE_REGISTRY.get(&protonode) else { let Some(node_io_hashmap) = NODE_REGISTRY.get(protonode) else {
log::error!("Could not get hashmap for proto node: {protonode:?}"); log::error!("Could not get hashmap for proto node: {protonode:?}");
return concrete!(()); return concrete!(());
}; };
@ -1010,10 +1012,7 @@ impl<'a> ModifyInputsContext<'a> {
let skip_footprint = if node.manual_composition.is_some() { 1 } else { 0 }; let skip_footprint = if node.manual_composition.is_some() { 1 } else { 0 };
let Some(input_type) = std::iter::once(node_types.input.clone()) let Some(input_type) = std::iter::once(node_types.input.clone()).chain(node_types.parameters.clone()).nth(input_index + skip_footprint) else {
.chain(node_types.parameters.clone().into_iter())
.nth(input_index + skip_footprint)
else {
log::error!("Could not get type"); log::error!("Could not get type");
return concrete!(()); return concrete!(());
}; };
@ -1025,7 +1024,7 @@ impl<'a> ModifyInputsContext<'a> {
for (network_node_input_index, input) in node.1.inputs.iter().enumerate() { for (network_node_input_index, input) in node.1.inputs.iter().enumerate() {
if let NodeInput::Network { import_index, .. } = input { if let NodeInput::Network { import_index, .. } = input {
if *import_index == input_index { if *import_index == input_index {
return get_type_from_node(&node.1, network_node_input_index); return get_type_from_node(node.1, network_node_input_index);
} }
} }
} }

View file

@ -139,7 +139,7 @@ impl MessageHandler<NavigationMessage, NavigationMessageData<'_>> for Navigation
NavigationMessage::CanvasPanMouseWheel { use_y_as_x } => { NavigationMessage::CanvasPanMouseWheel { use_y_as_x } => {
let delta = match use_y_as_x { let delta = match use_y_as_x {
false => -ipp.mouse.scroll_delta.as_dvec2(), false => -ipp.mouse.scroll_delta.as_dvec2(),
true => (-ipp.mouse.scroll_delta.y as f64, 0.).into(), true => (-ipp.mouse.scroll_delta.y, 0.).into(),
} * VIEWPORT_SCROLL_RATE; } * VIEWPORT_SCROLL_RATE;
responses.add(NavigationMessage::CanvasPan { delta }); responses.add(NavigationMessage::CanvasPan { delta });
} }

View file

@ -322,7 +322,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
// Select the new nodes // Select the new nodes
selected_nodes.retain_selected_nodes(|selected_node| network.nodes.contains_key(selected_node)); selected_nodes.retain_selected_nodes(|selected_node| network.nodes.contains_key(selected_node));
selected_nodes.add_selected_nodes(copied_nodes.iter().map(|(node_id, _)| *node_id).collect(), &document_network, &self.network); selected_nodes.add_selected_nodes(copied_nodes.iter().map(|(node_id, _)| *node_id).collect(), document_network, &self.network);
responses.add(BroadcastEvent::SelectionChanged); responses.add(BroadcastEvent::SelectionChanged);
for (node_id, mut document_node) in copied_nodes { for (node_id, mut document_node) in copied_nodes {
@ -342,7 +342,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}; };
if !self.eligible_to_be_layer(network, node_id) { if !self.eligible_to_be_layer(network, node_id) {
responses.add(NodeGraphMessage::SetToNodeOrLayer { node_id: node_id, is_layer: false }) responses.add(NodeGraphMessage::SetToNodeOrLayer { node_id, is_layer: false })
} }
} }
NodeGraphMessage::EnterNestedNetwork => { NodeGraphMessage::EnterNestedNetwork => {
@ -582,7 +582,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if right_click { if right_click {
let context_menu_data = if let Some((node_id, node)) = clicked_id.and_then(|node_id| network.nodes.get(&node_id).map(|node| (node_id, node))) { let context_menu_data = if let Some((node_id, node)) = clicked_id.and_then(|node_id| network.nodes.get(&node_id).map(|node| (node_id, node))) {
ContextMenuData::ToggleLayer { ContextMenuData::ToggleLayer {
node_id: node_id, node_id,
currently_is_node: !node.is_layer, currently_is_node: !node.is_layer,
} }
} else { } else {
@ -668,7 +668,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
.or(network.exports.get(input_index)) .or(network.exports.get(input_index))
{ {
self.disconnecting = Some((clicked_input.0, clicked_input.1)); self.disconnecting = Some((clicked_input.0, clicked_input.1));
let Some(output_node) = network.nodes.get(&node_id) else { let Some(output_node) = network.nodes.get(node_id) else {
log::error!("Could not find node {}", node_id); log::error!("Could not find node {}", node_id);
return; return;
}; };
@ -710,7 +710,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let Some(clicked_output_node) = network.nodes.get(&clicked_output.0) { if let Some(clicked_output_node) = network.nodes.get(&clicked_output.0) {
// Disallow creating additional vertical output wires from an already-connected layer // Disallow creating additional vertical output wires from an already-connected layer
if clicked_output_node.is_layer && clicked_output_node.has_primary_output { if clicked_output_node.is_layer && clicked_output_node.has_primary_output {
for (_, node) in &network.nodes { for node in network.nodes.values() {
if node if node
.inputs .inputs
.iter() .iter()
@ -925,15 +925,10 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
// TODO: Only loop through visible nodes // TODO: Only loop through visible nodes
let shift = ipp.keyboard.get(shift as usize); let shift = ipp.keyboard.get(shift as usize);
let mut nodes = if shift { selected_nodes.selected_nodes_ref().clone() } else { Vec::new() }; let mut nodes = if shift { selected_nodes.selected_nodes_ref().clone() } else { Vec::new() };
for node_id in network for node_id in network.nodes.keys().chain([network.exports_metadata.0, network.imports_metadata.0].iter()) {
.nodes
.iter()
.map(|(node_id, _)| node_id)
.chain(vec![network.exports_metadata.0, network.imports_metadata.0].iter())
{
if self if self
.node_metadata .node_metadata
.get(&node_id) .get(node_id)
.is_some_and(|node_metadata| node_metadata.node_click_target.intersect_rectangle(Quad::from_box([graph_start, point]), DAffine2::IDENTITY)) .is_some_and(|node_metadata| node_metadata.node_click_target.intersect_rectangle(Quad::from_box([graph_start, point]), DAffine2::IDENTITY))
{ {
nodes.push(*node_id); nodes.push(*node_id);
@ -992,7 +987,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
&& (selected_nodes.selected_nodes_ref().len() != 1 && (selected_nodes.selected_nodes_ref().len() != 1
|| selected_nodes || selected_nodes
.selected_nodes_ref() .selected_nodes_ref()
.get(0) .first()
.is_some_and(|first_selected_node| *first_selected_node != select_if_not_dragged)) .is_some_and(|first_selected_node| *first_selected_node != select_if_not_dragged))
{ {
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![select_if_not_dragged] }) responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![select_if_not_dragged] })
@ -1006,18 +1001,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let (selected_node_input, selected_node_is_layer) = network let (selected_node_input, selected_node_is_layer) = network
.nodes .nodes
.get(&selected_node_id) .get(&selected_node_id)
.map(|selected_node| (selected_node.inputs.get(0), selected_node.is_layer)) .map(|selected_node| (selected_node.inputs.first(), selected_node.is_layer))
.unwrap_or((network.exports.get(0), false)); .unwrap_or((network.exports.first(), false));
// Check if primary input is disconnected // Check if primary input is disconnected
if selected_node_input.is_some_and(|first_input| first_input.as_value().is_some()) { if selected_node_input.is_some_and(|first_input| first_input.as_value().is_some()) {
let has_primary_output_connection = network.nodes.iter().flat_map(|(_, node)| node.inputs.iter()).any(|input| { let has_primary_output_connection = network.nodes.iter().flat_map(|(_, node)| node.inputs.iter()).any(|input| {
if let NodeInput::Node { node_id, output_index, .. } = input { if let NodeInput::Node { node_id, output_index, .. } = input {
if *node_id == selected_node_id && *output_index == 0 { *node_id == selected_node_id && *output_index == 0
true
} else {
false
}
} else { } else {
false false
} }
@ -1351,10 +1342,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
let Some(node) = network_mut.nodes.get_mut(&node_id) else { continue }; let Some(node) = network_mut.nodes.get_mut(&node_id) else { continue };
if node.has_primary_output { if node.has_primary_output {
responses.add(NodeGraphMessage::SetToNodeOrLayer { responses.add(NodeGraphMessage::SetToNodeOrLayer { node_id, is_layer: !node.is_layer });
node_id: node_id,
is_layer: !node.is_layer,
});
} }
if network_mut.connected_to_output(node_id) { if network_mut.connected_to_output(node_id) {
@ -1612,7 +1600,7 @@ impl NodeGraphMessageHandler {
} }
// Inserts a node into the network and updates the click target // Inserts a node into the network and updates the click target
pub fn insert_node(&mut self, node_id: NodeId, node: DocumentNode, document_network: &mut NodeNetwork, network_path: &Vec<NodeId>) { pub fn insert_node(&mut self, node_id: NodeId, node: DocumentNode, document_network: &mut NodeNetwork, network_path: &[NodeId]) {
let Some(network) = document_network.nested_network_mut(network_path) else { let Some(network) = document_network.nested_network_mut(network_path) else {
log::error!("Network not found in update_click_target"); log::error!("Network not found in update_click_target");
return; return;
@ -1622,7 +1610,7 @@ impl NodeGraphMessageHandler {
"Cannot insert import/export node into network.nodes" "Cannot insert import/export node into network.nodes"
); );
network.nodes.insert(node_id, node); network.nodes.insert(node_id, node);
self.update_click_target(node_id, document_network, network_path.clone()); self.update_click_target(node_id, document_network, network_path.to_owned());
} }
/// Update the click targets when a DocumentNode's click target changes. network_path is the path to the encapsulating network /// Update the click targets when a DocumentNode's click target changes. network_path is the path to the encapsulating network
@ -1904,7 +1892,7 @@ impl NodeGraphMessageHandler {
.find_map(|(node_id, click_targets)| { .find_map(|(node_id, click_targets)| {
for (index, click_target) in click_targets.iter().enumerate() { for (index, click_target) in click_targets.iter().enumerate() {
if click_target.intersect_point(point, DAffine2::IDENTITY) { if click_target.intersect_point(point, DAffine2::IDENTITY) {
return Some((node_id.clone(), index)); return Some((*node_id, index));
} }
} }
None None
@ -1997,7 +1985,7 @@ impl NodeGraphMessageHandler {
// If the selected nodes are in the document network, use the document network. Otherwise, use the nested network // If the selected nodes are in the document network, use the document network. Otherwise, use the nested network
let Some(network) = context let Some(network) = context
.document_network .document_network
.nested_network_for_selected_nodes(&context.nested_path.to_vec(), selected_nodes.selected_nodes(context.document_network)) .nested_network_for_selected_nodes(context.nested_path, selected_nodes.selected_nodes(context.document_network))
else { else {
warn!("No network in collate_properties"); warn!("No network in collate_properties");
return Vec::new(); return Vec::new();
@ -2194,10 +2182,10 @@ impl NodeGraphMessageHandler {
.map(|(_, input_type)| input_type) .map(|(_, input_type)| input_type)
.collect(); .collect();
let output_types = Self::get_output_types(node, &self.resolved_types, &node_id_path); let output_types = Self::get_output_types(node, &self.resolved_types, node_id_path);
let primary_output_type = output_types.get(0).expect("Primary output should always exist"); let primary_output_type = output_types.first().expect("Primary output should always exist");
let frontend_data_type = if let Some(output_type) = primary_output_type { let frontend_data_type = if let Some(output_type) = primary_output_type {
FrontendGraphDataType::with_type(&output_type) FrontendGraphDataType::with_type(output_type)
} else { } else {
FrontendGraphDataType::General FrontendGraphDataType::General
}; };
@ -2241,7 +2229,7 @@ impl NodeGraphMessageHandler {
connected_index, connected_index,
}); });
} }
let is_export = network.exports.get(0).is_some_and(|export| export.as_node().is_some_and(|export_node_id| node_id == export_node_id)); let is_export = network.exports.first().is_some_and(|export| export.as_node().is_some_and(|export_node_id| node_id == export_node_id));
let is_root_node = network.get_root_node().is_some_and(|root_node| root_node.id == node_id); let is_root_node = network.get_root_node().is_some_and(|root_node| root_node.id == node_id);
let previewed = is_export && !is_root_node; let previewed = is_export && !is_root_node;
@ -2272,7 +2260,7 @@ impl NodeGraphMessageHandler {
previewed, previewed,
visible: node.visible, visible: node.visible,
locked: node.locked, locked: node.locked,
errors: errors, errors,
ui_only: false, ui_only: false,
}); });
} }
@ -2329,7 +2317,7 @@ impl NodeGraphMessageHandler {
let (frontend_data_type, input_type) = if let NodeInput::Node { node_id, output_index, .. } = export { let (frontend_data_type, input_type) = if let NodeInput::Node { node_id, output_index, .. } = export {
let node = network.nodes.get(node_id).expect("Node should always exist"); let node = network.nodes.get(node_id).expect("Node should always exist");
let node_id_path = &[&self.network[..], &[*node_id]].concat(); let node_id_path = &[&self.network[..], &[*node_id]].concat();
let output_types = Self::get_output_types(node, &self.resolved_types, &node_id_path); let output_types = Self::get_output_types(node, &self.resolved_types, node_id_path);
if let Some(output_type) = output_types.get(*output_index).cloned().flatten() { if let Some(output_type) = output_types.get(*output_index).cloned().flatten() {
(FrontendGraphDataType::with_type(&output_type), Some(output_type.clone())) (FrontendGraphDataType::with_type(&output_type), Some(output_type.clone()))
@ -2338,24 +2326,21 @@ impl NodeGraphMessageHandler {
} }
} else if let NodeInput::Value { tagged_value, .. } = export { } else if let NodeInput::Value { tagged_value, .. } = export {
(FrontendGraphDataType::with_type(&tagged_value.ty()), Some(tagged_value.ty())) (FrontendGraphDataType::with_type(&tagged_value.ty()), Some(tagged_value.ty()))
}
// TODO: Get type from parent node input when <https://github.com/GraphiteEditor/Graphite/issues/1762> is possible // TODO: Get type from parent node input when <https://github.com/GraphiteEditor/Graphite/issues/1762> is possible
// else if let NodeInput::Network { import_type, .. } = export { // else if let NodeInput::Network { import_type, .. } = export {
// (FrontendGraphDataType::with_type(import_type), Some(import_type.clone())) // (FrontendGraphDataType::with_type(import_type), Some(import_type.clone()))
// } // }
else { } else {
(FrontendGraphDataType::General, None) (FrontendGraphDataType::General, None)
}; };
// First import index is visually connected to the root node instead of its actual export input so previewing does not change the connection // First import index is visually connected to the root node instead of its actual export input so previewing does not change the connection
let connected = if index == 0 { let connected = if index == 0 {
network.get_root_node().map(|root_node| root_node.id) network.get_root_node().map(|root_node| root_node.id)
} else if let NodeInput::Node { node_id, .. } = export {
Some(*node_id)
} else { } else {
if let NodeInput::Node { node_id, .. } = export { None
Some(*node_id)
} else {
None
}
}; };
let definition_name = export_names[index].clone(); let definition_name = export_names[index].clone();
@ -2552,10 +2537,16 @@ impl NodeGraphMessageHandler {
} }
} }
pub fn get_output_types(node: &DocumentNode, resolved_types: &ResolvedDocumentNodeTypes, node_id_path: &Vec<NodeId>) -> Vec<Option<Type>> { pub fn get_output_types(node: &DocumentNode, resolved_types: &ResolvedDocumentNodeTypes, node_id_path: &[NodeId]) -> Vec<Option<Type>> {
let mut output_types = Vec::new(); let mut output_types = Vec::new();
let primary_output_type = resolved_types.outputs.get(&Source { node: node_id_path.clone(), index: 0 }).cloned(); let primary_output_type = resolved_types
.outputs
.get(&Source {
node: node_id_path.to_owned(),
index: 0,
})
.cloned();
output_types.push(primary_output_type); output_types.push(primary_output_type);
// If the node is not a protonode, get types by traversing across exports until a proto node is reached. // If the node is not a protonode, get types by traversing across exports until a proto node is reached.
@ -2563,7 +2554,7 @@ impl NodeGraphMessageHandler {
for export in internal_network.exports.iter().skip(1) { for export in internal_network.exports.iter().skip(1) {
let mut current_export = export; let mut current_export = export;
let mut current_network = internal_network; let mut current_network = internal_network;
let mut current_path = node_id_path.clone(); let mut current_path = node_id_path.to_owned();
while let NodeInput::Node { node_id, output_index, .. } = current_export { while let NodeInput::Node { node_id, output_index, .. } = current_export {
current_path.push(*node_id); current_path.push(*node_id);
@ -2588,7 +2579,7 @@ impl NodeGraphMessageHandler {
resolved_types resolved_types
.outputs .outputs
.get(&Source { .get(&Source {
node: node_id_path.clone(), node: node_id_path.to_owned(),
index: *import_index, index: *import_index,
}) })
.cloned() .cloned()
@ -2613,7 +2604,7 @@ impl NodeGraphMessageHandler {
/// Returns an iterator of nodes to be copied and their ids, excluding output and input nodes /// Returns an iterator of nodes to be copied and their ids, excluding output and input nodes
pub fn copy_nodes<'a>( pub fn copy_nodes<'a>(
document_network: &'a NodeNetwork, document_network: &'a NodeNetwork,
network_path: &'a Vec<NodeId>, network_path: &'a [NodeId],
resolved_types: &'a ResolvedDocumentNodeTypes, resolved_types: &'a ResolvedDocumentNodeTypes,
new_ids: &'a HashMap<NodeId, NodeId>, new_ids: &'a HashMap<NodeId, NodeId>,
) -> impl Iterator<Item = (NodeId, DocumentNode)> + 'a { ) -> impl Iterator<Item = (NodeId, DocumentNode)> + 'a {
@ -2630,7 +2621,7 @@ impl NodeGraphMessageHandler {
}) })
} }
pub fn get_default_inputs(document_network: &NodeNetwork, network_path: &Vec<NodeId>, node_id: NodeId, resolved_types: &ResolvedDocumentNodeTypes, node: &DocumentNode) -> Vec<NodeInput> { pub fn get_default_inputs(document_network: &NodeNetwork, network_path: &[NodeId], node_id: NodeId, resolved_types: &ResolvedDocumentNodeTypes, node: &DocumentNode) -> Vec<NodeInput> {
let mut default_inputs = Vec::new(); let mut default_inputs = Vec::new();
for (input_index, input) in node.inputs.iter().enumerate() { for (input_index, input) in node.inputs.iter().enumerate() {
@ -2674,9 +2665,13 @@ impl NodeGraphMessageHandler {
} }
fn untitled_layer_label(node: &DocumentNode) -> String { fn untitled_layer_label(node: &DocumentNode) -> String {
(node.alias != "") if !node.alias.is_empty() {
.then_some(node.alias.to_string()) node.alias.to_string()
.unwrap_or(if node.is_layer && node.name == "Merge" { "Untitled Layer".to_string() } else { node.name.clone() }) } else if node.is_layer && node.name == "Merge" {
"Untitled Layer".to_string()
} else {
node.name.clone()
}
} }
/// Get the actual input index from the visible input index where hidden inputs are skipped /// Get the actual input index from the visible input index where hidden inputs are skipped
@ -2750,7 +2745,7 @@ impl NodeGraphMessageHandler {
let horizontal_curve = horizontal_curve_amount * curve_length; let horizontal_curve = horizontal_curve_amount * curve_length;
let vertical_curve = vertical_curve_amount * curve_length; let vertical_curve = vertical_curve_amount * curve_length;
return vec![ vec![
output_position, output_position,
DVec2::new( DVec2::new(
if vertical_out { output_position.x } else { output_position.x + horizontal_curve }, if vertical_out { output_position.x } else { output_position.x + horizontal_curve },
@ -2761,7 +2756,7 @@ impl NodeGraphMessageHandler {
if vertical_in { input_position.y + vertical_curve } else { input_position.y }, if vertical_in { input_position.y + vertical_curve } else { input_position.y },
), ),
DVec2::new(input_position.x, input_position.y), DVec2::new(input_position.x, input_position.y),
]; ]
} }
} }

View file

@ -166,13 +166,13 @@ fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: usize)
.unit(" px") .unit(" px")
.on_update(update_value( .on_update(update_value(
move |x: &NumberInput| { move |x: &NumberInput| {
let (offset, scale) = (move |x: f64| -> (DVec2, DVec2) { let (offset, scale) = {
let diff = DVec2::new(top_left.x - x, 0.); let diff = DVec2::new(top_left.x - x.value.unwrap_or_default(), 0.);
(top_left - diff, bounds) (top_left - diff, bounds)
})(x.value.unwrap_or_default()); };
let footprint = Footprint { let footprint = Footprint {
transform: DAffine2::from_scale_angle_translation(scale.into(), 0., offset.into()), transform: DAffine2::from_scale_angle_translation(scale, 0., offset),
resolution: (oversample * scale).as_uvec2(), resolution: (oversample * scale).as_uvec2(),
..footprint ..footprint
}; };
@ -190,13 +190,13 @@ fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: usize)
.unit(" px") .unit(" px")
.on_update(update_value( .on_update(update_value(
move |x: &NumberInput| { move |x: &NumberInput| {
let (offset, scale) = (move |y: f64| -> (DVec2, DVec2) { let (offset, scale) = {
let diff = DVec2::new(0., top_left.y - y); let diff = DVec2::new(0., top_left.y - x.value.unwrap_or_default());
(top_left - diff, bounds) (top_left - diff, bounds)
})(x.value.unwrap_or_default()); };
let footprint = Footprint { let footprint = Footprint {
transform: DAffine2::from_scale_angle_translation(scale.into(), 0., offset.into()), transform: DAffine2::from_scale_angle_translation(scale, 0., offset),
resolution: (oversample * scale).as_uvec2(), resolution: (oversample * scale).as_uvec2(),
..footprint ..footprint
}; };
@ -216,10 +216,10 @@ fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: usize)
.unit(" px") .unit(" px")
.on_update(update_value( .on_update(update_value(
move |x: &NumberInput| { move |x: &NumberInput| {
let (offset, scale) = (move |x: f64| -> (DVec2, DVec2) { (top_left, DVec2::new(x, bounds.y)) })(x.value.unwrap_or_default()); let (offset, scale) = (top_left, DVec2::new(x.value.unwrap_or_default(), bounds.y));
let footprint = Footprint { let footprint = Footprint {
transform: DAffine2::from_scale_angle_translation(scale.into(), 0., offset.into()), transform: DAffine2::from_scale_angle_translation(scale, 0., offset),
resolution: (oversample * scale).as_uvec2(), resolution: (oversample * scale).as_uvec2(),
..footprint ..footprint
}; };
@ -237,10 +237,10 @@ fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: usize)
.unit(" px") .unit(" px")
.on_update(update_value( .on_update(update_value(
move |x: &NumberInput| { move |x: &NumberInput| {
let (offset, scale) = (move |y: f64| -> (DVec2, DVec2) { (top_left, DVec2::new(bounds.x, y)) })(x.value.unwrap_or_default()); let (offset, scale) = (top_left, DVec2::new(bounds.x, x.value.unwrap_or_default()));
let footprint = Footprint { let footprint = Footprint {
transform: DAffine2::from_scale_angle_translation(scale.into(), 0., offset.into()), transform: DAffine2::from_scale_angle_translation(scale, 0., offset),
resolution: (oversample * scale).as_uvec2(), resolution: (oversample * scale).as_uvec2(),
..footprint ..footprint
}; };
@ -255,7 +255,7 @@ fn footprint_widget(document_node: &DocumentNode, node_id: NodeId, index: usize)
]); ]);
resolution_widgets.push( resolution_widgets.push(
NumberInput::new(Some((footprint.resolution.as_dvec2() / bounds).x as f64 * 100.)) NumberInput::new(Some((footprint.resolution.as_dvec2() / bounds).x * 100.))
.label("Resolution") .label("Resolution")
.unit("%") .unit("%")
.on_update(update_value( .on_update(update_value(
@ -2003,8 +2003,7 @@ pub fn imaginate_properties(document_node: &DocumentNode, node_id: NodeId, conte
node.1 node.1
.inputs .inputs
.iter() .iter()
.find(|node_input| if let NodeInput::Network { import_index, .. } = node_input { *import_index == 0 } else { false }) .any(|node_input| if let NodeInput::Network { import_index, .. } = node_input { *import_index == 0 } else { false })
.is_some()
}) })
.map(|(node_id, _)| node_id) .map(|(node_id, _)| node_id)
.copied() .copied()
@ -2460,7 +2459,7 @@ pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context:
return vec![LayoutGroup::Row { widgets: widgets_first_row }]; return vec![LayoutGroup::Row { widgets: widgets_first_row }];
}; };
let fill2 = fill.clone(); let fill2 = fill.clone();
let backup_color_fill: Fill = backup_color.clone().into(); let backup_color_fill: Fill = (*backup_color).into();
let backup_gradient_fill: Fill = backup_gradient.clone().into(); let backup_gradient_fill: Fill = backup_gradient.clone().into();
widgets_first_row.push(Separator::new(SeparatorType::Unrelated).widget_holder()); widgets_first_row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
@ -2479,7 +2478,7 @@ pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context:
Fill::Solid(color) => NodeGraphMessage::SetInputValue { Fill::Solid(color) => NodeGraphMessage::SetInputValue {
node_id, node_id,
input_index: backup_color_index, input_index: backup_color_index,
value: TaggedValue::OptionalColor(Some(color.clone())), value: TaggedValue::OptionalColor(Some(*color)),
} }
.into(), .into(),
Fill::Gradient(gradient) => NodeGraphMessage::SetInputValue { Fill::Gradient(gradient) => NodeGraphMessage::SetInputValue {

View file

@ -196,7 +196,7 @@ impl OverlayContext {
} }
} }
pub fn outline<'a>(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2) { pub fn outline(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2) {
self.render_context.begin_path(); self.render_context.begin_path();
for subpath in subpaths { for subpath in subpaths {
let subpath = subpath.borrow(); let subpath = subpath.borrow();

View file

@ -233,8 +233,8 @@ impl Default for GridSnapping {
origin: DVec2::ZERO, origin: DVec2::ZERO,
grid_type: Default::default(), grid_type: Default::default(),
grid_color: COLOR_OVERLAY_GRAY grid_color: COLOR_OVERLAY_GRAY
.strip_prefix("#") .strip_prefix('#')
.and_then(|value| Color::from_rgb_str(value)) .and_then(Color::from_rgb_str)
.expect("Should create Color from prefixed hex string"), .expect("Should create Color from prefixed hex string"),
dot_display: false, dot_display: false,
} }

View file

@ -121,7 +121,7 @@ impl SelectedNodes {
} }
// TODO: This function is run when a node in the layer panel is currently selected, and a new node is selected in the graph, as well as when a node is currently selected in the graph and a node in the layer panel is selected. These are fundamentally different operations, since different nodes should be selected in each case, but cannot be distinguished. Currently it is not possible to shift+click a node in the node graph while a layer is selected. Instead of set_selected_nodes, add_selected_nodes should be used. // TODO: This function is run when a node in the layer panel is currently selected, and a new node is selected in the graph, as well as when a node is currently selected in the graph and a node in the layer panel is selected. These are fundamentally different operations, since different nodes should be selected in each case, but cannot be distinguished. Currently it is not possible to shift+click a node in the node graph while a layer is selected. Instead of set_selected_nodes, add_selected_nodes should be used.
pub fn set_selected_nodes(&mut self, new: Vec<NodeId>, document_network: &NodeNetwork, network_path: &Vec<NodeId>) { pub fn set_selected_nodes(&mut self, new: Vec<NodeId>, document_network: &NodeNetwork, network_path: &[NodeId]) {
let Some(network) = document_network.nested_network(network_path) else { return }; let Some(network) = document_network.nested_network(network_path) else { return };
let mut new_nodes = new; let mut new_nodes = new;
@ -140,7 +140,7 @@ impl SelectedNodes {
self.0 = new_nodes; self.0 = new_nodes;
} }
pub fn add_selected_nodes(&mut self, new: Vec<NodeId>, document_network: &NodeNetwork, network_path: &Vec<NodeId>) { pub fn add_selected_nodes(&mut self, new: Vec<NodeId>, document_network: &NodeNetwork, network_path: &[NodeId]) {
let Some(network) = document_network.nested_network(network_path) else { return }; let Some(network) = document_network.nested_network(network_path) else { return };
// If the nodes to add are in the document network, clear selected nodes in the current network // If the nodes to add are in the document network, clear selected nodes in the current network

View file

@ -352,6 +352,7 @@ pub struct Selected<'a> {
} }
impl<'a> Selected<'a> { impl<'a> Selected<'a> {
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
original_transforms: &'a mut OriginalTransforms, original_transforms: &'a mut OriginalTransforms,
pivot: &'a mut DVec2, pivot: &'a mut DVec2,

View file

@ -199,12 +199,12 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
let previous_alias = active_document.network().nodes.get(&layer_node_id).map(|node| node.alias.clone()).unwrap_or_default(); let previous_alias = active_document.network().nodes.get(&layer_node_id).map(|node| node.alias.clone()).unwrap_or_default();
let mut copy_ids = HashMap::new(); let mut copy_ids = HashMap::new();
copy_ids.insert(layer_node_id, NodeId(0 as u64)); copy_ids.insert(layer_node_id, NodeId(0_u64));
if let Some(input_node) = active_document if let Some(input_node) = active_document
.network() .network()
.nodes .nodes
.get(&layer_node_id) .get(&layer_node_id)
.and_then(|node| if node.is_layer { node.inputs.get(1) } else { node.inputs.get(0) }) .and_then(|node| if node.is_layer { node.inputs.get(1) } else { node.inputs.first() })
.and_then(|input| input.as_node()) .and_then(|input| input.as_node())
{ {
active_document active_document
@ -401,7 +401,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
// TODO: Eventually remove this (probably starting late 2024) // TODO: Eventually remove this (probably starting late 2024)
// Upgrade all old nodes to support editable subgraphs introduced in #1750 // Upgrade all old nodes to support editable subgraphs introduced in #1750
if upgrade_from_before_editable_subgraphs { if upgrade_from_before_editable_subgraphs {
for (_, node) in &mut document.network.nodes { for node in document.network.nodes.values_mut() {
let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap(); let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap();
let default_definition_node = node_definition.default_document_node(); let default_definition_node = node_definition.default_document_node();
@ -422,7 +422,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
// TODO: Eventually remove this (probably starting late 2024) // TODO: Eventually remove this (probably starting late 2024)
// Upgrade Fill nodes to the format change in #1778 // Upgrade Fill nodes to the format change in #1778
for (_, node) in &mut document.network.nodes { for node in document.network.nodes.values_mut() {
if node.name == "Fill" && node.inputs.len() == 8 { if node.name == "Fill" && node.inputs.len() == 8 {
let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap(); let node_definition = crate::messages::portfolio::document::node_graph::document_node_types::resolve_document_node_type(&node.name).unwrap();
let default_definition_node = node_definition.default_document_node(); let default_definition_node = node_definition.default_document_node();
@ -476,7 +476,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
// TODO: Eventually remove this (probably starting late 2024) // TODO: Eventually remove this (probably starting late 2024)
// Upgrade document to the new vector manipulation format introduced in #1676 // Upgrade document to the new vector manipulation format introduced in #1676
let document_serialized_content = document.serialize_document(); let document_serialized_content = document.serialize_document();
if upgrade_vector_manipulation_format && document_serialized_content != "" { if upgrade_vector_manipulation_format && !document_serialized_content.is_empty() {
responses.add(FrontendMessage::TriggerUpgradeDocumentToVectorManipulationFormat { responses.add(FrontendMessage::TriggerUpgradeDocumentToVectorManipulationFormat {
document_id, document_id,
document_name, document_name,
@ -707,7 +707,7 @@ impl PortfolioMessageHandler {
doc_title_numbers.sort_unstable(); doc_title_numbers.sort_unstable();
doc_title_numbers.iter_mut().enumerate().for_each(|(i, number)| *number = *number - i as isize - 2); doc_title_numbers.iter_mut().enumerate().for_each(|(i, number)| *number = *number - i as isize - 2);
// Uses binary search to find the index of the element where number is bigger than i // Uses binary search to find the index of the element where number is bigger than i
let new_doc_title_num = doc_title_numbers.binary_search(&0).map_or_else(|e| e, |v| v) + 1; let new_doc_title_num = doc_title_numbers.binary_search(&0).unwrap_or_else(|e| e) + 1;
match new_doc_title_num { match new_doc_title_num {
1 => DEFAULT_DOCUMENT_NAME.to_string(), 1 => DEFAULT_DOCUMENT_NAME.to_string(),
@ -721,7 +721,7 @@ impl PortfolioMessageHandler {
self.document_ids.push(document_id); self.document_ids.push(document_id);
new_document.update_layers_panel_options_bar_widgets(responses); new_document.update_layers_panel_options_bar_widgets(responses);
new_document.node_graph_handler.update_all_click_targets(&mut new_document.network, Vec::new()); new_document.node_graph_handler.update_all_click_targets(&new_document.network, Vec::new());
self.documents.insert(document_id, new_document); self.documents.insert(document_id, new_document);

View file

@ -507,14 +507,14 @@ impl ShapeState {
}; };
// Set the manipulator to have colinear handles // Set the manipulator to have colinear handles
if let (Some(a), Some(b)) = (handles.get(0), handles.get(1)) { if let (Some(a), Some(b)) = (handles.first(), handles.get(1)) {
let handles = [*a, *b]; let handles = [*a, *b];
let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: true }; let modification_type = VectorModificationType::SetG1Continuous { handles, enabled: true };
responses.add(GraphOperationMessage::Vector { layer, modification_type }); responses.add(GraphOperationMessage::Vector { layer, modification_type });
} }
// Flip the vector if it is not facing towards the same direction as the anchor // Flip the vector if it is not facing towards the same direction as the anchor
let [first, second] = [anchor_positions.get(0).copied().flatten(), anchor_positions.get(1).copied().flatten()]; let [first, second] = [anchor_positions.first().copied().flatten(), anchor_positions.get(1).copied().flatten()];
if first.is_some_and(|group| (group - anchor_position).normalize_or_zero().dot(handle_direction) < 0.) if first.is_some_and(|group| (group - anchor_position).normalize_or_zero().dot(handle_direction) < 0.)
|| second.is_some_and(|group| (group - anchor_position).normalize_or_zero().dot(handle_direction) > 0.) || second.is_some_and(|group| (group - anchor_position).normalize_or_zero().dot(handle_direction) > 0.)
{ {
@ -532,7 +532,7 @@ impl ShapeState {
responses.add(GraphOperationMessage::Vector { layer, modification_type }); responses.add(GraphOperationMessage::Vector { layer, modification_type });
// Create the opposite handle if it doesn't exist (if it is not a cubic segment) // Create the opposite handle if it doesn't exist (if it is not a cubic segment)
if handle.opposite().to_manipulator_point().get_position(&vector_data).is_none() { if handle.opposite().to_manipulator_point().get_position(vector_data).is_none() {
let modification_type = handle.opposite().set_relative_position(DVec2::ZERO); let modification_type = handle.opposite().set_relative_position(DVec2::ZERO);
responses.add(GraphOperationMessage::Vector { layer, modification_type }); responses.add(GraphOperationMessage::Vector { layer, modification_type });
} }
@ -784,7 +784,7 @@ impl ShapeState {
let mut handles = handles.map(Some); let mut handles = handles.map(Some);
for handle in &mut handles { for handle in &mut handles {
while let Some((point, connected)) = handle.clone().and_then(|(_, point)| missing_anchors.remove_entry(&point)) { while let Some((point, connected)) = (*handle).and_then(|(_, point)| missing_anchors.remove_entry(&point)) {
visited.push(point); visited.push(point);
*handle = connected.into_iter().find(|(_, point)| !visited.contains(point)); *handle = connected.into_iter().find(|(_, point)| !visited.contains(point));

View file

@ -70,7 +70,7 @@ impl LayerSnapper {
for subpath in document.metadata.layer_outline(layer) { for subpath in document.metadata.layer_outline(layer) {
for (start_index, curve) in subpath.iter().enumerate() { for (start_index, curve) in subpath.iter().enumerate() {
let document_curve = curve.apply_transformation(|p| transform.transform_point2(p)); let document_curve = curve.apply_transformation(|p| transform.transform_point2(p));
let start = subpath.manipulator_groups()[start_index].id.into(); let start = subpath.manipulator_groups()[start_index].id;
if snap_data.ignore_manipulator(layer, start) || snap_data.ignore_manipulator(layer, subpath.manipulator_groups()[(start_index + 1) % subpath.len()].id) { if snap_data.ignore_manipulator(layer, start) || snap_data.ignore_manipulator(layer, subpath.manipulator_groups()[(start_index + 1) % subpath.len()].id) {
continue; continue;
} }

View file

@ -144,8 +144,7 @@ impl ArtboardToolData {
fn hovered_artboard(document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) -> Option<LayerNodeIdentifier> { fn hovered_artboard(document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler) -> Option<LayerNodeIdentifier> {
document document
.click_xray(input.mouse.position) .click_xray(input.mouse.position)
.filter(|&layer| document.network.nodes.get(&layer.to_node()).map_or(false, |document_node| document_node.is_artboard())) .find(|&layer| document.network.nodes.get(&layer.to_node()).map_or(false, |document_node| document_node.is_artboard()))
.next()
} }
fn select_artboard(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> bool { fn select_artboard(&mut self, document: &DocumentMessageHandler, input: &InputPreprocessorMessageHandler, responses: &mut VecDeque<Message>) -> bool {

View file

@ -262,9 +262,7 @@ impl BrushToolData {
if document.selected_nodes.selected_layers(document.metadata()).count() != 1 { if document.selected_nodes.selected_layers(document.metadata()).count() != 1 {
return None; return None;
} }
let Some(layer) = document.selected_nodes.selected_layers(document.metadata()).next() else { let layer = document.selected_nodes.selected_layers(document.metadata()).next()?;
return None;
};
self.layer = Some(layer); self.layer = Some(layer);
for (node, node_id) in document.network().upstream_flow_back_from_nodes(vec![layer.to_node()], graph_craft::document::FlowType::HorizontalFlow) { for (node, node_id) in document.network().upstream_flow_back_from_nodes(vec![layer.to_node()], graph_craft::document::FlowType::HorizontalFlow) {
@ -277,7 +275,7 @@ impl BrushToolData {
else { else {
continue; continue;
}; };
self.strokes = strokes.clone(); self.strokes.clone_from(strokes);
return Some(layer); return Some(layer);
} else if node.name == "Transform" { } else if node.name == "Transform" {

View file

@ -406,10 +406,8 @@ impl PathToolData {
} }
self.alt_debounce = alt; self.alt_debounce = alt;
if shift { if shift && self.opposing_handle_lengths.is_none() {
if self.opposing_handle_lengths.is_none() { self.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(document));
self.opposing_handle_lengths = Some(shape_editor.opposing_handle_lengths(document));
}
} }
false false
} }
@ -419,7 +417,7 @@ impl PathToolData {
let previous_mouse = document.metadata.document_to_viewport.transform_point2(self.previous_mouse_position); let previous_mouse = document.metadata.document_to_viewport.transform_point2(self.previous_mouse_position);
let snapped_delta = shape_editor.snap(&mut self.snap_manager, document, input, previous_mouse); let snapped_delta = shape_editor.snap(&mut self.snap_manager, document, input, previous_mouse);
let handle_lengths = if equidistant { None } else { self.opposing_handle_lengths.take() }; let handle_lengths = if equidistant { None } else { self.opposing_handle_lengths.take() };
shape_editor.move_selected_points(handle_lengths, &document, snapped_delta, equidistant, responses); shape_editor.move_selected_points(handle_lengths, document, snapped_delta, equidistant, responses);
self.previous_mouse_position += document.metadata.document_to_viewport.inverse().transform_vector2(snapped_delta); self.previous_mouse_position += document.metadata.document_to_viewport.inverse().transform_vector2(snapped_delta);
} }
} }
@ -610,7 +608,7 @@ impl Fsm for PathToolFsmState {
(_, PathToolMessage::Delete) => { (_, PathToolMessage::Delete) => {
// Delete the selected points and clean up overlays // Delete the selected points and clean up overlays
responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::StartTransaction);
shape_editor.delete_selected_points(&document, responses); shape_editor.delete_selected_points(document, responses);
responses.add(PathToolMessage::SelectionChanged); responses.add(PathToolMessage::SelectionChanged);
PathToolFsmState::Ready PathToolFsmState::Ready
@ -636,7 +634,7 @@ impl Fsm for PathToolFsmState {
} }
(_, PathToolMessage::PointerMove { .. }) => self, (_, PathToolMessage::PointerMove { .. }) => self,
(_, PathToolMessage::NudgeSelectedPoints { delta_x, delta_y }) => { (_, PathToolMessage::NudgeSelectedPoints { delta_x, delta_y }) => {
shape_editor.move_selected_points(tool_data.opposing_handle_lengths.take(), &document, (delta_x, delta_y).into(), true, responses); shape_editor.move_selected_points(tool_data.opposing_handle_lengths.take(), document, (delta_x, delta_y).into(), true, responses);
PathToolFsmState::Ready PathToolFsmState::Ready
} }

View file

@ -251,7 +251,7 @@ impl Fsm for PolygonToolFsmState {
.to_document_node_default_inputs( .to_document_node_default_inputs(
[ [
None, None,
Some(NodeInput::value(TaggedValue::U32(tool_options.vertices as u32), false)), Some(NodeInput::value(TaggedValue::U32(tool_options.vertices), false)),
Some(NodeInput::value(TaggedValue::F64(0.5), false)), Some(NodeInput::value(TaggedValue::F64(0.5), false)),
], ],
Default::default(), Default::default(),
@ -259,7 +259,7 @@ impl Fsm for PolygonToolFsmState {
PolygonType::Star => resolve_document_node_type("Star").expect("Star node does not exist").to_document_node_default_inputs( PolygonType::Star => resolve_document_node_type("Star").expect("Star node does not exist").to_document_node_default_inputs(
[ [
None, None,
Some(NodeInput::value(TaggedValue::U32(tool_options.vertices as u32), false)), Some(NodeInput::value(TaggedValue::U32(tool_options.vertices), false)),
Some(NodeInput::value(TaggedValue::F64(0.5), false)), Some(NodeInput::value(TaggedValue::F64(0.5), false)),
Some(NodeInput::value(TaggedValue::F64(0.25), false)), Some(NodeInput::value(TaggedValue::F64(0.25), false)),
], ],

View file

@ -158,7 +158,7 @@ impl SelectTool {
let operations = BooleanOperation::list(); let operations = BooleanOperation::list();
let icons = BooleanOperation::icons(); let icons = BooleanOperation::icons();
operations.into_iter().zip(icons.into_iter()).map(move |(operation, icon)| { operations.into_iter().zip(icons).map(move |(operation, icon)| {
IconButton::new(icon, 24) IconButton::new(icon, 24)
.tooltip(operation.to_string()) .tooltip(operation.to_string())
.disabled(!enabled(operation)) .disabled(!enabled(operation))
@ -344,12 +344,12 @@ impl SelectToolData {
// Copy the layer // Copy the layer
let mut copy_ids = HashMap::new(); let mut copy_ids = HashMap::new();
let node = layer.to_node(); let node = layer.to_node();
copy_ids.insert(node, NodeId(0 as u64)); copy_ids.insert(node, NodeId(0_u64));
if let Some(input_node) = document if let Some(input_node) = document
.network() .network()
.nodes .nodes
.get(&node) .get(&node)
.and_then(|node| if node.is_layer { node.inputs.get(1) } else { node.inputs.get(0) }) .and_then(|node| if node.is_layer { node.inputs.get(1) } else { node.inputs.first() })
.and_then(|input| input.as_node()) .and_then(|input| input.as_node())
{ {
document document
@ -367,7 +367,7 @@ impl SelectToolData {
let new_ids: HashMap<_, _> = nodes.iter().map(|(&id, _)| (id, NodeId(generate_uuid()))).collect(); let new_ids: HashMap<_, _> = nodes.iter().map(|(&id, _)| (id, NodeId(generate_uuid()))).collect();
let layer_id = new_ids.get(&NodeId(0)).expect("Node Id 0 should be a layer").clone(); let layer_id = *new_ids.get(&NodeId(0)).expect("Node Id 0 should be a layer");
responses.add(GraphOperationMessage::AddNodesAsChild { nodes, new_ids, parent, insert_index }); responses.add(GraphOperationMessage::AddNodesAsChild { nodes, new_ids, parent, insert_index });
new_dragging.push(LayerNodeIdentifier::new_unchecked(layer_id)); new_dragging.push(LayerNodeIdentifier::new_unchecked(layer_id));
} }

View file

@ -243,7 +243,7 @@ impl TextToolData {
color: Some(color), color: Some(color),
transform, transform,
}); });
self.new_text = text.clone(); self.new_text.clone_from(text);
Some(()) Some(())
} }

View file

@ -287,11 +287,11 @@ impl NodeRuntime {
let introspected_data_output = introspected_data let introspected_data_output = introspected_data
.downcast_ref::<IORecord<Footprint, graphene_core::GraphicElement>>() .downcast_ref::<IORecord<Footprint, graphene_core::GraphicElement>>()
.and_then(|io_data| Some(IntrospectedData::GraphicElement(&io_data.output))) .map(|io_data| IntrospectedData::GraphicElement(&io_data.output))
.or_else(|| { .or_else(|| {
introspected_data introspected_data
.downcast_ref::<IORecord<Footprint, graphene_core::Artboard>>() .downcast_ref::<IORecord<Footprint, graphene_core::Artboard>>()
.and_then(|io_data| Some(IntrospectedData::Artboard(&io_data.output))) .map(|io_data| IntrospectedData::Artboard(&io_data.output))
}); });
let graphic_element = match introspected_data_output { let graphic_element = match introspected_data_output {

View file

@ -73,8 +73,10 @@ impl EditorTestUtils for Editor {
} }
fn move_mouse(&mut self, x: f64, y: f64) { fn move_mouse(&mut self, x: f64, y: f64) {
let mut editor_mouse_state = EditorMouseState::default(); let editor_mouse_state = EditorMouseState {
editor_mouse_state.editor_position = ViewportPosition::new(x, y); editor_position: ViewportPosition::new(x, y),
..Default::default()
};
let modifier_keys = ModifierKeys::default(); let modifier_keys = ModifierKeys::default();
self.input(InputPreprocessorMessage::PointerMove { editor_mouse_state, modifier_keys }); self.input(InputPreprocessorMessage::PointerMove { editor_mouse_state, modifier_keys });
} }

View file

@ -17,7 +17,7 @@ use std::cell::RefCell;
// use std::sync::Mutex; // use std::sync::Mutex;
thread_local! { thread_local! {
static EDITOR: RefCell<Option<Editor>> = RefCell::new(None); static EDITOR: RefCell<Option<Editor>> = const { RefCell::new(None) };
} }
// async fn respond_to(id: Path<String>) -> impl IntoResponse { // async fn respond_to(id: Path<String>) -> impl IntoResponse {

View file

@ -731,9 +731,9 @@ impl EditorHandle {
return; return;
} }
let transform = get_current_transform(&inputs); let transform = get_current_transform(inputs);
let upstream_transform = metadata.upstream_transform(node_id); let upstream_transform = metadata.upstream_transform(node_id);
let pivot_transform = glam::DAffine2::from_translation(upstream_transform.transform_point2(bounds.local_pivot(get_current_normalized_pivot(&inputs)))); let pivot_transform = glam::DAffine2::from_translation(upstream_transform.transform_point2(bounds.local_pivot(get_current_normalized_pivot(inputs))));
update_transform(inputs, pivot_transform * transform * pivot_transform.inverse()); update_transform(inputs, pivot_transform * transform * pivot_transform.inverse());
}); });
@ -894,7 +894,7 @@ fn editor<T: Default>(callback: impl FnOnce(&mut editor::application::Editor) ->
return T::default(); return T::default();
}; };
callback(&mut *editor) callback(&mut editor)
}) })
} }

View file

@ -18,8 +18,8 @@ use wasm_bindgen::prelude::*;
pub static EDITOR_HAS_CRASHED: AtomicBool = AtomicBool::new(false); pub static EDITOR_HAS_CRASHED: AtomicBool = AtomicBool::new(false);
pub static LOGGER: WasmLog = WasmLog; pub static LOGGER: WasmLog = WasmLog;
thread_local! { thread_local! {
pub static EDITOR: OnceCell<RefCell<editor::application::Editor>> = OnceCell::new(); pub static EDITOR: OnceCell<RefCell<editor::application::Editor>> = const { OnceCell::new() };
pub static EDITOR_HANDLE: OnceCell<RefCell<editor_api::EditorHandle>> = OnceCell::new(); pub static EDITOR_HANDLE: OnceCell<RefCell<editor_api::EditorHandle>> = const { OnceCell::new() };
} }
/// Initialize the backend /// Initialize the backend
@ -48,9 +48,9 @@ pub fn panic_hook(info: &panic::PanicInfo) {
}); });
} }
/// The JavaScript `Error` type
#[wasm_bindgen] #[wasm_bindgen]
extern "C" { extern "C" {
/// The JavaScript `Error` type
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub type Error; pub type Error;

View file

@ -30,7 +30,7 @@ pub fn decode<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
let image_width: usize = ifd.image_width.try_into().unwrap(); let image_width: usize = ifd.image_width.try_into().unwrap();
let image_height: usize = ifd.image_height.try_into().unwrap(); let image_height: usize = ifd.image_height.try_into().unwrap();
let bits_per_sample: usize = ifd.bits_per_sample.into(); let _bits_per_sample: usize = ifd.bits_per_sample.into();
let [cfa_pattern_width, cfa_pattern_height] = ifd.cfa_pattern_dim; let [cfa_pattern_width, cfa_pattern_height] = ifd.cfa_pattern_dim;
assert!(cfa_pattern_width == 2 && cfa_pattern_height == 2); assert!(cfa_pattern_width == 2 && cfa_pattern_height == 2);
@ -81,10 +81,10 @@ fn sony_arw2_load_raw<R: Read + Seek>(width: usize, height: usize, curve: CurveL
let max_minus_min = max as i32 - min as i32; let max_minus_min = max as i32 - min as i32;
let shift_by_bits = (0..4).find(|&shift| (0x80 << shift) > max_minus_min).unwrap_or(4); let shift_by_bits = (0..4).find(|&shift| (0x80 << shift) > max_minus_min).unwrap_or(4);
let mut pixel = [0_u16; 16]; let mut pixels = [0_u16; 16];
let mut bit = 30; let mut bit = 30;
for i in 0..16 { for (i, pixel) in pixels.iter_mut().enumerate() {
pixel[i] = match () { *pixel = match () {
_ if i as u32 == index_to_set_max => max, _ if i as u32 == index_to_set_max => max,
_ if i as u32 == index_to_set_min => min, _ if i as u32 == index_to_set_min => min,
_ => { _ => {
@ -98,7 +98,7 @@ fn sony_arw2_load_raw<R: Read + Seek>(width: usize, height: usize, curve: CurveL
}; };
} }
for value in pixel { for value in pixels {
image[row * width + column] = curve.get((value << 1).into()) >> 2; image[row * width + column] = curve.get((value << 1).into()) >> 2;
// Skip between interlaced columns // Skip between interlaced columns

View file

@ -29,7 +29,7 @@ pub fn decode<R: Read + Seek>(ifd: Ifd, file: &mut TiffRead<R>) -> RawImage {
let image_width: usize = ifd.image_width.try_into().unwrap(); let image_width: usize = ifd.image_width.try_into().unwrap();
let image_height: usize = ifd.image_height.try_into().unwrap(); let image_height: usize = ifd.image_height.try_into().unwrap();
let rows_per_strip: usize = ifd.rows_per_strip.try_into().unwrap(); let rows_per_strip: usize = ifd.rows_per_strip.try_into().unwrap();
let bits_per_sample: usize = ifd.bits_per_sample.into(); let _bits_per_sample: usize = ifd.bits_per_sample.into();
let [cfa_pattern_width, cfa_pattern_height] = ifd.cfa_pattern_dim; let [cfa_pattern_width, cfa_pattern_height] = ifd.cfa_pattern_dim;
assert!(cfa_pattern_width == 2 && cfa_pattern_height == 2); assert!(cfa_pattern_width == 2 && cfa_pattern_height == 2);

View file

@ -106,7 +106,7 @@ impl Ifd {
}) })
} }
fn next_ifd<R: Read + Seek>(&self, file: &mut TiffRead<R>) -> Result<Self, TiffError> { fn _next_ifd<R: Read + Seek>(&self, file: &mut TiffRead<R>) -> Result<Self, TiffError> {
Ifd::new_from_offset(file, self.next_ifd_offset.unwrap_or(0)) Ifd::new_from_offset(file, self.next_ifd_offset.unwrap_or(0))
} }

View file

@ -270,7 +270,7 @@ impl PrimitiveType for TypeIfd {
fn read_primitive<R: Read + Seek>(the_type: IfdTagType, file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> { fn read_primitive<R: Read + Seek>(the_type: IfdTagType, file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
let offset = TypeLong::read_primitive(the_type, file)?; let offset = TypeLong::read_primitive(the_type, file)?;
Ok(Ifd::new_from_offset(file, offset)?) Ifd::new_from_offset(file, offset)
} }
} }
@ -284,7 +284,7 @@ impl<T: PrimitiveType> TagType for T {
type Output = T::Output; type Output = T::Output;
fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> { fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
let the_type = IfdTagType::try_from(file.read_u16()?).map_err(|_| TiffError::InvalidType)?; let the_type = IfdTagType::from(file.read_u16()?);
let count = file.read_u32()?; let count = file.read_u32()?;
if count != 1 { if count != 1 {
@ -313,7 +313,7 @@ impl<T: PrimitiveType> TagType for Array<T> {
type Output = Vec<T::Output>; type Output = Vec<T::Output>;
fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> { fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
let the_type = IfdTagType::try_from(file.read_u16()?).map_err(|_| TiffError::InvalidType)?; let the_type = IfdTagType::from(file.read_u16()?);
let count = file.read_u32()?; let count = file.read_u32()?;
let size = T::get_size(the_type).ok_or(TiffError::InvalidType)?; let size = T::get_size(the_type).ok_or(TiffError::InvalidType)?;
@ -334,7 +334,7 @@ impl<T: PrimitiveType, const N: usize> TagType for ConstArray<T, N> {
type Output = [T::Output; N]; type Output = [T::Output; N];
fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> { fn read<R: Read + Seek>(file: &mut TiffRead<R>) -> Result<Self::Output, TiffError> {
let the_type = IfdTagType::try_from(file.read_u16()?).map_err(|_| TiffError::InvalidType)?; let the_type = IfdTagType::from(file.read_u16()?);
let count = file.read_u32()?; let count = file.read_u32()?;
if count != N.try_into()? { if count != N.try_into()? {

View file

@ -1,3 +1,4 @@
#![cfg(feature = "raw-rs-tests")]
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt::Write; use std::fmt::Write;
use std::fs::{read_dir, File}; use std::fs::{read_dir, File};
@ -13,7 +14,6 @@ const BASE_URL: &str = "https://static.graphite.rs/test-data/libraries/raw-rs/";
const BASE_PATH: &str = "./tests/images"; const BASE_PATH: &str = "./tests/images";
#[test] #[test]
#[cfg(feature = "raw-rs-tests")]
fn test_images_match_with_libraw() { fn test_images_match_with_libraw() {
download_images(); download_images();
@ -30,7 +30,7 @@ fn test_images_match_with_libraw() {
print!("{} => ", path.display()); print!("{} => ", path.display());
let raw_image = match test_raw_data(&content) { let _raw_image = match test_raw_data(&content) {
Err(err_msg) => { Err(err_msg) => {
failed_tests += 1; failed_tests += 1;
return println!("{}", err_msg); return println!("{}", err_msg);
@ -54,7 +54,6 @@ fn test_images_match_with_libraw() {
} }
} }
#[cfg(feature = "raw-rs-tests")]
fn download_images() { fn download_images() {
let mut path = Path::new(BASE_PATH).to_owned(); let mut path = Path::new(BASE_PATH).to_owned();
let mut downloads: Vec<Download> = Vec::new(); let mut downloads: Vec<Download> = Vec::new();
@ -75,7 +74,6 @@ fn download_images() {
} }
} }
#[cfg(feature = "raw-rs-tests")]
fn test_raw_data(content: &[u8]) -> Result<RawImage, String> { fn test_raw_data(content: &[u8]) -> Result<RawImage, String> {
let processor = libraw::Processor::new(); let processor = libraw::Processor::new();
let libraw_raw_image = processor.decode(content).unwrap(); let libraw_raw_image = processor.decode(content).unwrap();
@ -149,8 +147,7 @@ fn test_raw_data(content: &[u8]) -> Result<RawImage, String> {
Ok(raw_image) Ok(raw_image)
} }
#[cfg(feature = "raw-rs-tests")] fn _test_final_image(content: &[u8], raw_image: RawImage) -> Result<(), String> {
fn test_final_image(content: &[u8], raw_image: RawImage) -> Result<(), String> {
let processor = libraw::Processor::new(); let processor = libraw::Processor::new();
let libraw_image = processor.process_8bit(content).unwrap(); let libraw_image = processor.process_8bit(content).unwrap();

View file

@ -47,7 +47,7 @@ mod uuid_generation {
static RNG: Mutex<Option<ChaCha20Rng>> = Mutex::new(None); static RNG: Mutex<Option<ChaCha20Rng>> = Mutex::new(None);
thread_local! { thread_local! {
pub static UUID_SEED: Cell<Option<u64>> = Cell::new(None); pub static UUID_SEED: Cell<Option<u64>> = const { Cell::new(None) };
} }
pub fn set_uuid_seed(random_seed: u64) { pub fn set_uuid_seed(random_seed: u64) {

View file

@ -149,8 +149,7 @@ fn solidify_stroke(vector_data: VectorData) -> VectorData {
// Perform operation on all subpaths in this shape. // Perform operation on all subpaths in this shape.
for mut subpath in subpaths { for mut subpath in subpaths {
let stroke = style.stroke().unwrap(); let stroke = style.stroke().unwrap();
let transform = transform.clone(); subpath.apply_transform(*transform);
subpath.apply_transform(transform);
// Taking the existing stroke data and passing it to Bezier-rs to generate new paths. // Taking the existing stroke data and passing it to Bezier-rs to generate new paths.
let subpath_out = subpath.outline( let subpath_out = subpath.outline(

View file

@ -827,7 +827,7 @@ impl NodeNetwork {
} }
/// Get the network the selected nodes are part of, which is either self or the nested network from nested_path. Used to get nodes selected in the layer panel when viewing a nested network. /// Get the network the selected nodes are part of, which is either self or the nested network from nested_path. Used to get nodes selected in the layer panel when viewing a nested network.
pub fn nested_network_for_selected_nodes<'a>(&self, nested_path: &Vec<NodeId>, mut selected_nodes: impl Iterator<Item = &'a NodeId>) -> Option<&Self> { pub fn nested_network_for_selected_nodes<'a>(&self, nested_path: &[NodeId], mut selected_nodes: impl Iterator<Item = &'a NodeId>) -> Option<&Self> {
if selected_nodes.any(|node_id| self.nodes.contains_key(node_id) || self.exports_metadata.0 == *node_id || self.imports_metadata.0 == *node_id) { if selected_nodes.any(|node_id| self.nodes.contains_key(node_id) || self.exports_metadata.0 == *node_id || self.imports_metadata.0 == *node_id) {
Some(self) Some(self)
} else { } else {
@ -836,7 +836,7 @@ impl NodeNetwork {
} }
/// Get the mutable network the selected nodes are part of, which is either self or the nested network from nested_path. Used to modify nodes selected in the layer panel when viewing a nested network. /// Get the mutable network the selected nodes are part of, which is either self or the nested network from nested_path. Used to modify nodes selected in the layer panel when viewing a nested network.
pub fn nested_network_for_selected_nodes_mut<'a>(&mut self, nested_path: &Vec<NodeId>, mut selected_nodes: impl Iterator<Item = &'a NodeId>) -> Option<&mut Self> { pub fn nested_network_for_selected_nodes_mut<'a>(&mut self, nested_path: &[NodeId], mut selected_nodes: impl Iterator<Item = &'a NodeId>) -> Option<&mut Self> {
if selected_nodes.any(|node_id| self.nodes.contains_key(node_id)) { if selected_nodes.any(|node_id| self.nodes.contains_key(node_id)) {
Some(self) Some(self)
} else { } else {
@ -1215,7 +1215,7 @@ impl NodeNetwork {
for (nested_input_index, nested_input) in nested_node.clone().inputs.iter().enumerate() { for (nested_input_index, nested_input) in nested_node.clone().inputs.iter().enumerate() {
if let NodeInput::Network { import_index, .. } = nested_input { if let NodeInput::Network { import_index, .. } = nested_input {
let parent_input = node.inputs.get(*import_index).expect(&format!("Import index {} should always exist", import_index)); let parent_input = node.inputs.get(*import_index).unwrap_or_else(|| panic!("Import index {} should always exist", import_index));
match *parent_input { match *parent_input {
// If the input to self is a node, connect the corresponding output of the inner network to it // If the input to self is a node, connect the corresponding output of the inner network to it
NodeInput::Node { node_id, output_index, lambda } => { NodeInput::Node { node_id, output_index, lambda } => {

View file

@ -10,6 +10,7 @@ use graphene_core::{Color, Node, Type};
use dyn_any::DynAny; use dyn_any::DynAny;
pub use dyn_any::StaticType; pub use dyn_any::StaticType;
pub use glam::{DAffine2, DVec2, IVec2, UVec2}; pub use glam::{DAffine2, DVec2, IVec2, UVec2};
use std::fmt::Display;
use std::hash::Hash; use std::hash::Hash;
pub use std::sync::Arc; pub use std::sync::Arc;
@ -173,17 +174,7 @@ tagged_value! {
BooleanOperation(graphene_core::vector::misc::BooleanOperation), BooleanOperation(graphene_core::vector::misc::BooleanOperation),
} }
impl<'a> TaggedValue { impl TaggedValue {
pub fn to_string(&self) -> String {
match self {
TaggedValue::String(x) => x.to_string(),
TaggedValue::U32(x) => x.to_string(),
TaggedValue::U64(x) => x.to_string(),
TaggedValue::F64(x) => x.to_string(),
TaggedValue::Bool(x) => x.to_string(),
_ => panic!("Cannot convert to string"),
}
}
pub fn to_primitive_string(&self) -> String { pub fn to_primitive_string(&self) -> String {
match self { match self {
TaggedValue::None => "()".to_string(), TaggedValue::None => "()".to_string(),
@ -199,6 +190,19 @@ impl<'a> TaggedValue {
} }
} }
impl Display for TaggedValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TaggedValue::String(x) => f.write_str(x),
TaggedValue::U32(x) => f.write_fmt(format_args!("{x}")),
TaggedValue::U64(x) => f.write_fmt(format_args!("{x}")),
TaggedValue::F64(x) => f.write_fmt(format_args!("{x}")),
TaggedValue::Bool(x) => f.write_fmt(format_args!("{x}")),
_ => panic!("Cannot convert to string"),
}
}
}
pub struct UpcastNode { pub struct UpcastNode {
value: TaggedValue, value: TaggedValue,
} }

View file

@ -90,7 +90,7 @@ fn create_executor(_document_string: String) -> Result<DynamicExecutor, Box<dyn
// Ok(executor) // Ok(executor)
} }
fn begin_scope() -> DocumentNode { fn _begin_scope() -> DocumentNode {
DocumentNode { DocumentNode {
name: "Begin Scope".to_string(), name: "Begin Scope".to_string(),
implementation: DocumentNodeImplementation::Network(NodeNetwork { implementation: DocumentNodeImplementation::Network(NodeNetwork {

View file

@ -276,6 +276,12 @@ impl<I, O> PanicNode<I, O> {
} }
} }
impl<I, O> Default for PanicNode<I, O> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View file

@ -293,8 +293,8 @@ async fn brush(image: ImageFrame<Color>, bounds: ImageFrame<Color>, strokes: Vec
let image_bbox = Bbox::from_transform(image.transform).to_axis_aligned_bbox(); let image_bbox = Bbox::from_transform(image.transform).to_axis_aligned_bbox();
let bbox = if image_bbox.size().length() < 0.1 { stroke_bbox } else { stroke_bbox.union(&image_bbox) }; let bbox = if image_bbox.size().length() < 0.1 { stroke_bbox } else { stroke_bbox.union(&image_bbox) };
let mut draw_strokes: Vec<_> = strokes.iter().cloned().filter(|s| !matches!(s.style.blend_mode, BlendMode::Erase | BlendMode::Restore)).collect(); let mut draw_strokes: Vec<_> = strokes.iter().filter(|&s| !matches!(s.style.blend_mode, BlendMode::Erase | BlendMode::Restore)).cloned().collect();
let erase_restore_strokes: Vec<_> = strokes.iter().cloned().filter(|s| matches!(s.style.blend_mode, BlendMode::Erase | BlendMode::Restore)).collect(); let erase_restore_strokes: Vec<_> = strokes.iter().filter(|&s| matches!(s.style.blend_mode, BlendMode::Erase | BlendMode::Restore)).cloned().collect();
let mut brush_plan = cache.compute_brush_plan(image, &draw_strokes); let mut brush_plan = cache.compute_brush_plan(image, &draw_strokes);

View file

@ -590,8 +590,8 @@ pub struct NoisePatternNode<
cellular_jitter: CellularJitter, cellular_jitter: CellularJitter,
} }
#[allow(clippy::too_many_arguments)]
#[node_macro::node_fn(NoisePatternNode)] #[node_macro::node_fn(NoisePatternNode)]
#[allow(clippy::too_many_arguments)]
fn noise_pattern( fn noise_pattern(
_no_primary_input: (), _no_primary_input: (),
dimensions: UVec2, dimensions: UVec2,

View file

@ -31,7 +31,7 @@ use web_sys::window;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement}; use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
#[cfg(any(feature = "resvg", feature = "vello"))] #[cfg(any(feature = "resvg", feature = "vello"))]
pub struct Canvas(CanvasRenderingContext2d); pub struct Canvas(());
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct WasmApplicationIo { pub struct WasmApplicationIo {
@ -316,7 +316,7 @@ fn render_svg(data: impl GraphicElementRendered, mut render: SvgRender, render_p
} }
#[cfg(any(feature = "resvg", feature = "vello"))] #[cfg(any(feature = "resvg", feature = "vello"))]
fn render_canvas( fn _render_canvas(
data: impl GraphicElementRendered, data: impl GraphicElementRendered,
mut render: SvgRender, mut render: SvgRender,
render_params: RenderParams, render_params: RenderParams,
@ -331,13 +331,13 @@ fn render_canvas(
let max = footprint.transform.inverse().transform_point2(resolution.as_dvec2()); let max = footprint.transform.inverse().transform_point2(resolution.as_dvec2());
render.format_svg(min, max); render.format_svg(min, max);
let string = render.svg.to_svg_string(); let string = render.svg.to_svg_string();
let array = string.as_bytes(); let _array = string.as_bytes();
let canvas = &surface_handle.surface; let canvas = &surface_handle.surface;
canvas.set_width(resolution.x); canvas.set_width(resolution.x);
canvas.set_height(resolution.y); canvas.set_height(resolution.y);
let usvg_tree = data.to_usvg_tree(resolution, [min, max]); let usvg_tree = data.to_usvg_tree(resolution, [min, max]);
if let Some(exec) = editor.application_io.gpu_executor() { if let Some(_exec) = editor.application_io.gpu_executor() {
todo!() todo!()
} else { } else {
let pixmap_size = usvg_tree.size.to_int_size(); let pixmap_size = usvg_tree.size.to_int_size();

View file

@ -141,11 +141,14 @@ fn node_new_impl(attr: TokenStream, item: TokenStream) -> TokenStream {
args.push(Type::Verbatim(quote::quote!(#ident))); args.push(Type::Verbatim(quote::quote!(#ident)));
} }
let function_attributes = &function.attrs;
let struct_generics_iter = struct_generics.iter(); let struct_generics_iter = struct_generics.iter();
quote::quote! { quote::quote! {
#[automatically_derived] #[automatically_derived]
impl <#(#args),*> #node_name<#(#args),*> impl <#(#args),*> #node_name<#(#args),*>
{ {
#(#function_attributes)*
pub const fn new(#(#parameter_idents: #struct_generics_iter),*) -> Self{ pub const fn new(#(#parameter_idents: #struct_generics_iter),*) -> Self{
Self { Self {
#(#parameter_idents,)* #(#parameter_idents,)*

View file

@ -71,7 +71,7 @@ fn execute_shader<I: Pod + Send + Sync, O: Pod + Send + Sync>(
let dest_buffer = create_buffer(dest_data, alloc).expect("failed to create buffer"); let dest_buffer = create_buffer(dest_data, alloc).expect("failed to create buffer");
let compute_pipeline = ComputePipeline::new(device.clone(), entry_point, &(), None, |_| {}).expect("failed to create compute pipeline"); let compute_pipeline = ComputePipeline::new(device.clone(), entry_point, &(), None, |_| {}).expect("failed to create compute pipeline");
let layout = compute_pipeline.layout().set_layouts().get(0).unwrap(); let layout = compute_pipeline.layout().set_layouts().first().unwrap();
let dalloc = StandardDescriptorSetAllocator::new(device.clone()); let dalloc = StandardDescriptorSetAllocator::new(device.clone());
let set = PersistentDescriptorSet::new( let set = PersistentDescriptorSet::new(
&dalloc, &dalloc,

View file

@ -3,6 +3,9 @@ use syn::punctuated::Punctuated;
use syn::{Path, PathArguments, PathSegment, Token}; use syn::{Path, PathArguments, PathSegment, Token};
/// Returns `Ok(Vec<T>)` if all items are `Ok(T)`, else returns a combination of every error encountered (not just the first one) /// Returns `Ok(Vec<T>)` if all items are `Ok(T)`, else returns a combination of every error encountered (not just the first one)
// Allowing this lint because this is a false positive in this case. The fold can only be changed into a `try_fold` if the closure
// doesn't have an error case. See for details: https://rust-lang.github.io/rust-clippy/master/index.html#/manual_try_fold.
#[allow(clippy::manual_try_fold)]
pub fn fold_error_iter<T>(iter: impl Iterator<Item = syn::Result<T>>) -> syn::Result<Vec<T>> { pub fn fold_error_iter<T>(iter: impl Iterator<Item = syn::Result<T>>) -> syn::Result<Vec<T>> {
iter.fold(Ok(vec![]), |acc, x| match acc { iter.fold(Ok(vec![]), |acc, x| match acc {
Ok(mut v) => x.map(|x| { Ok(mut v) => x.map(|x| {

View file

@ -6,7 +6,7 @@ mod utils;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
pub static LOGGER: WasmLog = WasmLog; pub static LOGGER: WasmLog = WasmLog;
thread_local! { pub static HAS_CRASHED: std::cell::RefCell<bool> = std::cell::RefCell::new(false); } thread_local! { pub static HAS_CRASHED: std::cell::RefCell<bool> = const { std::cell::RefCell::new(false) } }
/// Initialize the backend /// Initialize the backend
#[wasm_bindgen(start)] #[wasm_bindgen(start)]