mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-04 16:08:11 +08:00
Fix assorted Clippy lints (#3390)
This commit is contained in:
@@ -290,11 +290,11 @@ impl Dispatcher {
|
|||||||
list.extend(self.message_handlers.input_preprocessor_message_handler.actions());
|
list.extend(self.message_handlers.input_preprocessor_message_handler.actions());
|
||||||
list.extend(self.message_handlers.key_mapping_message_handler.actions());
|
list.extend(self.message_handlers.key_mapping_message_handler.actions());
|
||||||
list.extend(self.message_handlers.debug_message_handler.actions());
|
list.extend(self.message_handlers.debug_message_handler.actions());
|
||||||
if let Some(document) = self.message_handlers.portfolio_message_handler.active_document() {
|
if let Some(document) = self.message_handlers.portfolio_message_handler.active_document()
|
||||||
if !document.graph_view_overlay_open {
|
&& !document.graph_view_overlay_open
|
||||||
|
{
|
||||||
list.extend(self.message_handlers.tool_message_handler.actions());
|
list.extend(self.message_handlers.tool_message_handler.actions());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
list.extend(self.message_handlers.portfolio_message_handler.actions());
|
list.extend(self.message_handlers.portfolio_message_handler.actions());
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,11 +156,11 @@ impl LayoutMessageHandler {
|
|||||||
let blue = color.get("blue").and_then(|x| x.as_f64()).map(|x| x as f32);
|
let blue = color.get("blue").and_then(|x| x.as_f64()).map(|x| x as f32);
|
||||||
let alpha = color.get("alpha").and_then(|x| x.as_f64()).map(|x| x as f32);
|
let alpha = color.get("alpha").and_then(|x| x.as_f64()).map(|x| x as f32);
|
||||||
|
|
||||||
if let (Some(red), Some(green), Some(blue), Some(alpha)) = (red, green, blue, alpha) {
|
if let (Some(red), Some(green), Some(blue), Some(alpha)) = (red, green, blue, alpha)
|
||||||
if let Some(color) = Color::from_rgbaf32(red, green, blue, alpha) {
|
&& let Some(color) = Color::from_rgbaf32(red, green, blue, alpha)
|
||||||
|
{
|
||||||
return Some(color);
|
return Some(color);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -508,8 +508,8 @@ impl WidgetHolder {
|
|||||||
|
|
||||||
/// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so.
|
/// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so.
|
||||||
pub fn diff(&mut self, new: Self, widget_path: &mut [usize], widget_diffs: &mut Vec<WidgetDiff>) {
|
pub fn diff(&mut self, new: Self, widget_path: &mut [usize], widget_diffs: &mut Vec<WidgetDiff>) {
|
||||||
if let (Widget::PopoverButton(button1), Widget::PopoverButton(button2)) = (&mut self.widget, &new.widget) {
|
if let (Widget::PopoverButton(button1), Widget::PopoverButton(button2)) = (&mut self.widget, &new.widget)
|
||||||
if button1.disabled == button2.disabled
|
&& button1.disabled == button2.disabled
|
||||||
&& button1.style == button2.style
|
&& button1.style == button2.style
|
||||||
&& button1.menu_direction == button2.menu_direction
|
&& button1.menu_direction == button2.menu_direction
|
||||||
&& button1.icon == button2.icon
|
&& button1.icon == button2.icon
|
||||||
@@ -525,7 +525,6 @@ impl WidgetHolder {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If there have been changes to the actual widget (not just the id)
|
// If there have been changes to the actual widget (not just the id)
|
||||||
if self.widget != new.widget {
|
if self.widget != new.widget {
|
||||||
@@ -621,8 +620,9 @@ impl DiffUpdate {
|
|||||||
let apply_shortcut_to_tooltip = |tooltip_shortcut: &mut ActionKeys, tooltip: &mut String| {
|
let apply_shortcut_to_tooltip = |tooltip_shortcut: &mut ActionKeys, tooltip: &mut String| {
|
||||||
let shortcut_text = tooltip_shortcut.to_keys(action_input_mapping);
|
let shortcut_text = tooltip_shortcut.to_keys(action_input_mapping);
|
||||||
|
|
||||||
if let ActionKeys::Keys(_keys) = tooltip_shortcut {
|
if let ActionKeys::Keys(_keys) = tooltip_shortcut
|
||||||
if !shortcut_text.is_empty() {
|
&& !shortcut_text.is_empty()
|
||||||
|
{
|
||||||
if !tooltip.is_empty() {
|
if !tooltip.is_empty() {
|
||||||
tooltip.push(' ');
|
tooltip.push(' ');
|
||||||
}
|
}
|
||||||
@@ -630,7 +630,6 @@ impl DiffUpdate {
|
|||||||
tooltip.push_str(&shortcut_text);
|
tooltip.push_str(&shortcut_text);
|
||||||
tooltip.push(')');
|
tooltip.push(')');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Go through each widget to convert `ActionKeys::Action` to `ActionKeys::Keys` and append the key combination to the widget tooltip
|
// Go through each widget to convert `ActionKeys::Action` to `ActionKeys::Keys` and append the key combination to the widget tooltip
|
||||||
|
|||||||
+3
-3
@@ -14,10 +14,10 @@ pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec
|
|||||||
..
|
..
|
||||||
} = node_template;
|
} = node_template;
|
||||||
|
|
||||||
if let DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier { name }) = implementation {
|
if let DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier { name }) = implementation
|
||||||
if let Some((new_name, _suffix)) = name.rsplit_once("<") {
|
&& let Some((new_name, _suffix)) = name.rsplit_once("<")
|
||||||
|
{
|
||||||
*name = Cow::Owned(new_name.to_string())
|
*name = Cow::Owned(new_name.to_string())
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1011,11 +1011,12 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
// Disconnect if the wire was previously connected to an input
|
// Disconnect if the wire was previously connected to an input
|
||||||
if let Some(disconnecting) = &self.disconnecting {
|
if let Some(disconnecting) = &self.disconnecting {
|
||||||
let mut disconnect_root_node = false;
|
let mut disconnect_root_node = false;
|
||||||
if let Previewing::Yes { root_node_to_restore } = network_interface.previewing(selection_network_path) {
|
if let Previewing::Yes { root_node_to_restore } = network_interface.previewing(selection_network_path)
|
||||||
if root_node_to_restore.is_some() && *disconnecting == InputConnector::Export(0) {
|
&& root_node_to_restore.is_some()
|
||||||
|
&& *disconnecting == InputConnector::Export(0)
|
||||||
|
{
|
||||||
disconnect_root_node = true;
|
disconnect_root_node = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if disconnect_root_node {
|
if disconnect_root_node {
|
||||||
responses.add(NodeGraphMessage::DisconnectRootNode);
|
responses.add(NodeGraphMessage::DisconnectRootNode);
|
||||||
} else {
|
} else {
|
||||||
@@ -1168,14 +1169,14 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
responses.add(NodeGraphMessage::TogglePreview { node_id: preview_node });
|
responses.add(NodeGraphMessage::TogglePreview { node_id: preview_node });
|
||||||
self.preview_on_mouse_up = None;
|
self.preview_on_mouse_up = None;
|
||||||
}
|
}
|
||||||
if let Some(node_to_deselect) = self.deselect_on_pointer_up.take() {
|
if let Some(node_to_deselect) = self.deselect_on_pointer_up.take()
|
||||||
if !self.drag_start.as_ref().is_some_and(|t| t.1) {
|
&& !self.drag_start.as_ref().is_some_and(|t| t.1)
|
||||||
|
{
|
||||||
let mut new_selected_nodes = selected_nodes.selected_nodes_ref().clone();
|
let mut new_selected_nodes = selected_nodes.selected_nodes_ref().clone();
|
||||||
new_selected_nodes.remove(node_to_deselect);
|
new_selected_nodes.remove(node_to_deselect);
|
||||||
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes });
|
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let point = network_metadata
|
let point = network_metadata
|
||||||
.persistent_metadata
|
.persistent_metadata
|
||||||
.navigation_metadata
|
.navigation_metadata
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ pub fn footprint_widget(parameter_widgets_info: ParameterWidgetsInfo, extra_widg
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let widgets = vec![
|
let widgets = [
|
||||||
LayoutGroup::Row { widgets: location_widgets },
|
LayoutGroup::Row { widgets: location_widgets },
|
||||||
LayoutGroup::Row { widgets: scale_widgets },
|
LayoutGroup::Row { widgets: scale_widgets },
|
||||||
LayoutGroup::Row { widgets: resolution_widgets },
|
LayoutGroup::Row { widgets: resolution_widgets },
|
||||||
|
|||||||
@@ -213,11 +213,11 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
|
|||||||
}
|
}
|
||||||
let update_origin = |grid, update: fn(&mut GridSnapping) -> Option<&mut f64>| {
|
let update_origin = |grid, update: fn(&mut GridSnapping) -> Option<&mut f64>| {
|
||||||
update_val::<NumberInput, _>(grid, move |grid, val| {
|
update_val::<NumberInput, _>(grid, move |grid, val| {
|
||||||
if let Some(val) = val.value {
|
if let Some(val) = val.value
|
||||||
if let Some(update) = update(grid) {
|
&& let Some(update) = update(grid)
|
||||||
|
{
|
||||||
*update = val;
|
*update = val;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
|
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
|
||||||
|
|||||||
@@ -91,17 +91,15 @@ impl DocumentMetadata {
|
|||||||
|
|
||||||
let mut use_local = true;
|
let mut use_local = true;
|
||||||
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, network_interface);
|
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, network_interface);
|
||||||
if let Some(path_node) = graph_layer.upstream_visible_node_id_from_name_in_layer("Path") {
|
if let Some(path_node) = graph_layer.upstream_visible_node_id_from_name_in_layer("Path")
|
||||||
if let Some(&source) = self.first_element_source_ids.get(&layer.to_node()) {
|
&& let Some(&source) = self.first_element_source_ids.get(&layer.to_node())
|
||||||
if !network_interface
|
&& !network_interface
|
||||||
.upstream_flow_back_from_nodes(vec![path_node], &[], FlowType::HorizontalFlow)
|
.upstream_flow_back_from_nodes(vec![path_node], &[], FlowType::HorizontalFlow)
|
||||||
.any(|upstream| Some(upstream) == source)
|
.any(|upstream| Some(upstream) == source)
|
||||||
{
|
{
|
||||||
use_local = false;
|
use_local = false;
|
||||||
info!("Local transform is invalid — using the identity for the local transform instead")
|
info!("Local transform is invalid — using the identity for the local transform instead")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
let local_transform = use_local.then(|| self.local_transforms.get(&layer.to_node()).copied()).flatten().unwrap_or_default();
|
let local_transform = use_local.then(|| self.local_transforms.get(&layer.to_node()).copied()).flatten().unwrap_or_default();
|
||||||
|
|
||||||
footprint * local_transform
|
footprint * local_transform
|
||||||
|
|||||||
@@ -79,15 +79,16 @@ impl NodeNetworkInterface {
|
|||||||
if let Some(network) = node.implementation.get_network_mut() {
|
if let Some(network) = node.implementation.get_network_mut() {
|
||||||
fix_network(network);
|
fix_network(network);
|
||||||
}
|
}
|
||||||
if let DocumentNodeImplementation::ProtoNode(protonode) = &node.implementation {
|
if let DocumentNodeImplementation::ProtoNode(protonode) = &node.implementation
|
||||||
if protonode.name.contains("PathModifyNode") && node.inputs.len() < 3 {
|
&& protonode.name.contains("PathModifyNode")
|
||||||
|
&& node.inputs.len() < 3
|
||||||
|
{
|
||||||
node.inputs.push(NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath));
|
node.inputs.push(NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Public immutable getters for the network interface
|
// Public immutable getters for the network interface
|
||||||
impl NodeNetworkInterface {
|
impl NodeNetworkInterface {
|
||||||
@@ -1450,23 +1451,22 @@ impl NodeNetworkInterface {
|
|||||||
.all_layers()
|
.all_layers()
|
||||||
.filter(|layer| include_artboards || !self.is_artboard(&layer.to_node(), &[]))
|
.filter(|layer| include_artboards || !self.is_artboard(&layer.to_node(), &[]))
|
||||||
.filter_map(|layer| {
|
.filter_map(|layer| {
|
||||||
if !self.is_artboard(&layer.to_node(), &[]) {
|
if !self.is_artboard(&layer.to_node(), &[])
|
||||||
if let Some(artboard_node_identifier) = layer
|
&& let Some(artboard_node_identifier) = layer
|
||||||
.ancestors(self.document_metadata())
|
.ancestors(self.document_metadata())
|
||||||
.find(|ancestor| *ancestor != LayerNodeIdentifier::ROOT_PARENT && self.is_artboard(&ancestor.to_node(), &[]))
|
.find(|ancestor| *ancestor != LayerNodeIdentifier::ROOT_PARENT && self.is_artboard(&ancestor.to_node(), &[]))
|
||||||
{
|
{
|
||||||
let artboard = self.document_node(&artboard_node_identifier.to_node(), &[]);
|
let artboard = self.document_node(&artboard_node_identifier.to_node(), &[]);
|
||||||
let clip_input = artboard.unwrap().inputs.get(5).unwrap();
|
let clip_input = artboard.unwrap().inputs.get(5).unwrap();
|
||||||
if let NodeInput::Value { tagged_value, .. } = clip_input {
|
if let NodeInput::Value { tagged_value, .. } = clip_input
|
||||||
if tagged_value.clone().deref() == &TaggedValue::Bool(true) {
|
&& tagged_value.clone().deref() == &TaggedValue::Bool(true)
|
||||||
|
{
|
||||||
return Some(Quad::clip(
|
return Some(Quad::clip(
|
||||||
self.document_metadata.bounding_box_document(layer).unwrap_or_default(),
|
self.document_metadata.bounding_box_document(layer).unwrap_or_default(),
|
||||||
self.document_metadata.bounding_box_document(artboard_node_identifier).unwrap_or_default(),
|
self.document_metadata.bounding_box_document(artboard_node_identifier).unwrap_or_default(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
self.document_metadata.bounding_box_document(layer)
|
self.document_metadata.bounding_box_document(layer)
|
||||||
})
|
})
|
||||||
.reduce(Quad::combine_bounds)
|
.reduce(Quad::combine_bounds)
|
||||||
@@ -1557,7 +1557,7 @@ impl NodeNetworkInterface {
|
|||||||
log::error!("Could not get network or network_metadata in upstream_flow_back_from_nodes");
|
log::error!("Could not get network or network_metadata in upstream_flow_back_from_nodes");
|
||||||
return FlowIter {
|
return FlowIter {
|
||||||
stack: Vec::new(),
|
stack: Vec::new(),
|
||||||
network: &self.document_network(),
|
network: self.document_network(),
|
||||||
network_metadata: &self.network_metadata,
|
network_metadata: &self.network_metadata,
|
||||||
flow_type: FlowType::UpstreamFlow,
|
flow_type: FlowType::UpstreamFlow,
|
||||||
};
|
};
|
||||||
@@ -2535,12 +2535,10 @@ impl NodeNetworkInterface {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If the node is a layer, then the width and click targets need to be recalculated
|
// If the node is a layer, then the width and click targets need to be recalculated
|
||||||
if is_layer {
|
if is_layer && let NodeTypeTransientMetadata::Layer(layer_metadata) = &mut node_metadata.transient_metadata.node_type_metadata {
|
||||||
if let NodeTypeTransientMetadata::Layer(layer_metadata) = &mut node_metadata.transient_metadata.node_type_metadata {
|
|
||||||
layer_metadata.layer_width.unload();
|
layer_metadata.layer_width.unload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_input_center(&mut self, input: &InputConnector, network_path: &[NodeId]) -> Option<DVec2> {
|
pub fn get_input_center(&mut self, input: &InputConnector, network_path: &[NodeId]) -> Option<DVec2> {
|
||||||
let (ports, index) = match input {
|
let (ports, index) = match input {
|
||||||
@@ -3484,8 +3482,9 @@ impl NodeNetworkInterface {
|
|||||||
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<Vector> {
|
pub fn compute_modified_vector(&self, layer: LayerNodeIdentifier) -> Option<Vector> {
|
||||||
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, self);
|
let graph_layer = graph_modification_utils::NodeGraphLayer::new(layer, self);
|
||||||
|
|
||||||
if let Some(path_node) = graph_layer.upstream_visible_node_id_from_name_in_layer("Path") {
|
if let Some(path_node) = graph_layer.upstream_visible_node_id_from_name_in_layer("Path")
|
||||||
if let Some(vector) = self.document_metadata.vector_modify.get(&path_node) {
|
&& let Some(vector) = self.document_metadata.vector_modify.get(&path_node)
|
||||||
|
{
|
||||||
let mut modified = vector.clone();
|
let mut modified = vector.clone();
|
||||||
|
|
||||||
let path_node = self.document_network().nodes.get(&path_node);
|
let path_node = self.document_network().nodes.get(&path_node);
|
||||||
@@ -3495,7 +3494,6 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
return Some(modified);
|
return Some(modified);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.document_metadata
|
self.document_metadata
|
||||||
.click_targets
|
.click_targets
|
||||||
@@ -3701,10 +3699,11 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
let mut encapsulating_path = network_path.to_vec();
|
let mut encapsulating_path = network_path.to_vec();
|
||||||
// Set the parent node (if it exists) to be a non layer if it is no longer eligible to be a layer
|
// Set the parent node (if it exists) to be a non layer if it is no longer eligible to be a layer
|
||||||
if let Some(parent_id) = encapsulating_path.pop() {
|
if let Some(parent_id) = encapsulating_path.pop()
|
||||||
if !self.is_eligible_to_be_layer(&parent_id, &encapsulating_path) && self.is_layer(&parent_id, &encapsulating_path) {
|
&& !self.is_eligible_to_be_layer(&parent_id, &encapsulating_path)
|
||||||
|
&& self.is_layer(&parent_id, &encapsulating_path)
|
||||||
|
{
|
||||||
self.set_to_node_or_layer(&parent_id, &encapsulating_path, false);
|
self.set_to_node_or_layer(&parent_id, &encapsulating_path, false);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// There will not be an encapsulating node if the network is the document network
|
// There will not be an encapsulating node if the network is the document network
|
||||||
@@ -4170,15 +4169,15 @@ impl NodeNetworkInterface {
|
|||||||
/// Used to ensure the display name is the reference name in case it is empty.
|
/// Used to ensure the display name is the reference name in case it is empty.
|
||||||
pub fn validate_display_name_metadata(&mut self, node_id: &NodeId, network_path: &[NodeId]) {
|
pub fn validate_display_name_metadata(&mut self, node_id: &NodeId, network_path: &[NodeId]) {
|
||||||
let Some(metadata) = self.node_metadata_mut(node_id, network_path) else { return };
|
let Some(metadata) = self.node_metadata_mut(node_id, network_path) else { return };
|
||||||
if metadata.persistent_metadata.display_name.is_empty() {
|
if metadata.persistent_metadata.display_name.is_empty()
|
||||||
if let Some(reference) = metadata.persistent_metadata.reference.clone() {
|
&& let Some(reference) = metadata.persistent_metadata.reference.clone()
|
||||||
|
{
|
||||||
// Keep the name for merge nodes as empty
|
// Keep the name for merge nodes as empty
|
||||||
if reference != "Merge" {
|
if reference != "Merge" {
|
||||||
metadata.persistent_metadata.display_name = reference;
|
metadata.persistent_metadata.display_name = reference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// When opening an old document to ensure the output names match the number of exports
|
// When opening an old document to ensure the output names match the number of exports
|
||||||
pub fn validate_output_names(&mut self, node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId]) {
|
pub fn validate_output_names(&mut self, node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId]) {
|
||||||
@@ -4245,11 +4244,11 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the previous input is connected to a chain node, then set all upstream chain nodes to absolute position
|
// If the previous input is connected to a chain node, then set all upstream chain nodes to absolute position
|
||||||
if let NodeInput::Node { node_id: previous_upstream_id, .. } = &previous_input {
|
if let NodeInput::Node { node_id: previous_upstream_id, .. } = &previous_input
|
||||||
if self.is_chain(previous_upstream_id, network_path) {
|
&& self.is_chain(previous_upstream_id, network_path)
|
||||||
|
{
|
||||||
self.set_upstream_chain_to_absolute(previous_upstream_id, network_path);
|
self.set_upstream_chain_to_absolute(previous_upstream_id, network_path);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let NodeInput::Node { node_id: new_upstream_id, .. } = &new_input {
|
if let NodeInput::Node { node_id: new_upstream_id, .. } = &new_input {
|
||||||
// If the new input is connected to a chain node, then break its chain
|
// If the new input is connected to a chain node, then break its chain
|
||||||
if self.is_chain(new_upstream_id, network_path) {
|
if self.is_chain(new_upstream_id, network_path) {
|
||||||
@@ -4424,13 +4423,13 @@ impl NodeNetworkInterface {
|
|||||||
};
|
};
|
||||||
// If it is a layer and is connected to a single layer, set its position to stack at its previous y position
|
// If it is a layer and is connected to a single layer, set its position to stack at its previous y position
|
||||||
if old_upstream_node_is_layer && outward_wires.len() == 1 && outward_wires[0].input_index() == 0 {
|
if old_upstream_node_is_layer && outward_wires.len() == 1 && outward_wires[0].input_index() == 0 {
|
||||||
if let Some(downstream_node_id) = outward_wires[0].node_id() {
|
if let Some(downstream_node_id) = outward_wires[0].node_id()
|
||||||
if self.is_layer(&downstream_node_id, network_path) {
|
&& self.is_layer(&downstream_node_id, network_path)
|
||||||
|
{
|
||||||
self.set_stack_position_calculated_offset(&old_upstream_node_id, &downstream_node_id, network_path);
|
self.set_stack_position_calculated_offset(&old_upstream_node_id, &downstream_node_id, network_path);
|
||||||
self.unload_upstream_node_click_targets(vec![old_upstream_node_id], network_path);
|
self.unload_upstream_node_click_targets(vec![old_upstream_node_id], network_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// If it is a node and is eligible to be in a chain, then set it to chain positioning
|
// If it is a node and is eligible to be in a chain, then set it to chain positioning
|
||||||
else if !old_upstream_node_is_layer {
|
else if !old_upstream_node_is_layer {
|
||||||
self.try_set_node_to_chain(&old_upstream_node_id, network_path);
|
self.try_set_node_to_chain(&old_upstream_node_id, network_path);
|
||||||
@@ -4488,21 +4487,19 @@ impl NodeNetworkInterface {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let mut other_outward_wires = outward_wires.iter().filter(|outward_wire| *outward_wire != input_connector);
|
let mut other_outward_wires = outward_wires.iter().filter(|outward_wire| *outward_wire != input_connector);
|
||||||
if let Some(other_outward_wire) = other_outward_wires.next().cloned() {
|
if let Some(other_outward_wire) = other_outward_wires.next().cloned()
|
||||||
if other_outward_wires.next().is_none() {
|
&& other_outward_wires.next().is_none()
|
||||||
if let InputConnector::Node {
|
&& let InputConnector::Node {
|
||||||
node_id: downstream_node_id,
|
node_id: downstream_node_id,
|
||||||
input_index,
|
input_index,
|
||||||
} = other_outward_wire
|
} = other_outward_wire
|
||||||
|
&& self.is_layer(&downstream_node_id, network_path)
|
||||||
|
&& input_index == 0
|
||||||
{
|
{
|
||||||
if self.is_layer(&downstream_node_id, network_path) && input_index == 0 {
|
|
||||||
self.set_stack_position_calculated_offset(upstream_node_id, &downstream_node_id, network_path);
|
self.set_stack_position_calculated_offset(upstream_node_id, &downstream_node_id, network_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let tagged_value = TaggedValue::from_type_or_none(&self.input_type(input_connector, network_path).0);
|
let tagged_value = TaggedValue::from_type_or_none(&self.input_type(input_connector, network_path).0);
|
||||||
|
|
||||||
@@ -4625,14 +4622,14 @@ impl NodeNetworkInterface {
|
|||||||
let Some(downstream_node) = self.document_node(deleted_node_id, network_path) else { continue };
|
let Some(downstream_node) = self.document_node(deleted_node_id, network_path) else { continue };
|
||||||
let Some(input) = downstream_node.inputs.first() else { continue };
|
let Some(input) = downstream_node.inputs.first() else { continue };
|
||||||
|
|
||||||
if let NodeInput::Node { node_id, .. } = input {
|
if let NodeInput::Node { node_id, .. } = input
|
||||||
if *node_id == current_node_id {
|
&& *node_id == current_node_id
|
||||||
|
{
|
||||||
stack.push(OutputConnector::node(*deleted_node_id, 0));
|
stack.push(OutputConnector::node(*deleted_node_id, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// If the traversal reaches the export, then the current node is not a sole dependent
|
// If the traversal reaches the export, then the current node is not a sole dependent
|
||||||
else {
|
else {
|
||||||
can_delete = false;
|
can_delete = false;
|
||||||
@@ -4719,14 +4716,14 @@ impl NodeNetworkInterface {
|
|||||||
for downstream_input in &downstream_inputs_to_disconnect {
|
for downstream_input in &downstream_inputs_to_disconnect {
|
||||||
self.disconnect_input(downstream_input, network_path);
|
self.disconnect_input(downstream_input, network_path);
|
||||||
// Prevent reconnecting export to import until https://github.com/GraphiteEditor/Graphite/issues/1762 is solved
|
// Prevent reconnecting export to import until https://github.com/GraphiteEditor/Graphite/issues/1762 is solved
|
||||||
if !(matches!(reconnect_to_input, Some(NodeInput::Import { .. })) && matches!(downstream_input, InputConnector::Export(_))) {
|
if !(matches!(reconnect_to_input, Some(NodeInput::Import { .. })) && matches!(downstream_input, InputConnector::Export(_)))
|
||||||
if let Some(reconnect_input) = &reconnect_to_input {
|
&& let Some(reconnect_input) = &reconnect_to_input
|
||||||
|
{
|
||||||
reconnect_node = reconnect_input.as_node().and_then(|node_id| if self.is_stack(&node_id, network_path) { Some(node_id) } else { None });
|
reconnect_node = reconnect_input.as_node().and_then(|node_id| if self.is_stack(&node_id, network_path) { Some(node_id) } else { None });
|
||||||
self.disconnect_input(&InputConnector::node(*node_id, 0), network_path);
|
self.disconnect_input(&InputConnector::node(*node_id, 0), network_path);
|
||||||
self.set_input(downstream_input, reconnect_input.clone(), network_path);
|
self.set_input(downstream_input, reconnect_input.clone(), network_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Shift the reconnected node up to collapse space
|
// Shift the reconnected node up to collapse space
|
||||||
if let Some(reconnect_node) = &reconnect_node {
|
if let Some(reconnect_node) = &reconnect_node {
|
||||||
@@ -5296,13 +5293,11 @@ impl NodeNetworkInterface {
|
|||||||
if let Some(outward_wires) = self
|
if let Some(outward_wires) = self
|
||||||
.outward_wires(network_path)
|
.outward_wires(network_path)
|
||||||
.and_then(|outward_wires| outward_wires.get(&OutputConnector::node(*node_id, 0)))
|
.and_then(|outward_wires| outward_wires.get(&OutputConnector::node(*node_id, 0)))
|
||||||
.cloned()
|
.cloned() && outward_wires.len() == 1
|
||||||
{
|
{
|
||||||
if outward_wires.len() == 1 {
|
|
||||||
self.try_set_upstream_to_chain(&outward_wires[0], network_path)
|
self.try_set_upstream_to_chain(&outward_wires[0], network_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn force_set_upstream_to_chain(&mut self, node_id: &NodeId, network_path: &[NodeId]) {
|
pub fn force_set_upstream_to_chain(&mut self, node_id: &NodeId, network_path: &[NodeId]) {
|
||||||
for upstream_id in self.upstream_flow_back_from_nodes(vec![*node_id], network_path, FlowType::HorizontalFlow).collect::<Vec<_>>().iter() {
|
for upstream_id in self.upstream_flow_back_from_nodes(vec![*node_id], network_path, FlowType::HorizontalFlow).collect::<Vec<_>>().iter() {
|
||||||
@@ -5400,15 +5395,15 @@ impl NodeNetworkInterface {
|
|||||||
};
|
};
|
||||||
if !shift_without_push {
|
if !shift_without_push {
|
||||||
for node_id in node_ids.clone() {
|
for node_id in node_ids.clone() {
|
||||||
if self.is_layer(&node_id, network_path) {
|
if self.is_layer(&node_id, network_path)
|
||||||
if let Some(owned_nodes) = self.owned_nodes(&node_id, network_path) {
|
&& let Some(owned_nodes) = self.owned_nodes(&node_id, network_path)
|
||||||
|
{
|
||||||
for owned_node in owned_nodes {
|
for owned_node in owned_nodes {
|
||||||
node_ids.remove(owned_node);
|
node_ids.remove(owned_node);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for selected_node in &node_ids.clone() {
|
for selected_node in &node_ids.clone() {
|
||||||
// Deselect chain nodes upstream from a selected layer
|
// Deselect chain nodes upstream from a selected layer
|
||||||
@@ -5428,18 +5423,19 @@ impl NodeNetworkInterface {
|
|||||||
log::error!("Could not get node metadata for node {node_id} in shift_selected_nodes");
|
log::error!("Could not get node metadata for node {node_id} in shift_selected_nodes");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let NodeTypePersistentMetadata::Layer(layer_metadata) = &node_metadata.persistent_metadata.node_type_metadata {
|
if let NodeTypePersistentMetadata::Layer(layer_metadata) = &node_metadata.persistent_metadata.node_type_metadata
|
||||||
if let LayerPosition::Stack(offset) = layer_metadata.position {
|
&& let LayerPosition::Stack(offset) = layer_metadata.position
|
||||||
|
{
|
||||||
// If the upstream layer is selected, then skip
|
// If the upstream layer is selected, then skip
|
||||||
let Some(outward_wires) = self.outward_wires(network_path).and_then(|outward_wires| outward_wires.get(&OutputConnector::node(*node_id, 0))) else {
|
let Some(outward_wires) = self.outward_wires(network_path).and_then(|outward_wires| outward_wires.get(&OutputConnector::node(*node_id, 0))) else {
|
||||||
log::error!("Could not get outward wires in shift_selected_nodes");
|
log::error!("Could not get outward wires in shift_selected_nodes");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let Some(upstream_node) = outward_wires.first() {
|
if let Some(upstream_node) = outward_wires.first()
|
||||||
if node_ids.contains(&upstream_node.node_id().expect("Stack layer should have downstream layer")) {
|
&& node_ids.contains(&upstream_node.node_id().expect("Stack layer should have downstream layer"))
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Offset cannot be negative, so cancel the shift
|
// Offset cannot be negative, so cancel the shift
|
||||||
if offset == 0 {
|
if offset == 0 {
|
||||||
return;
|
return;
|
||||||
@@ -5447,7 +5443,6 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let Some(mut sorted_node_ids) = self.nodes_sorted_top_to_bottom(node_ids.iter(), network_path) else {
|
let Some(mut sorted_node_ids) = self.nodes_sorted_top_to_bottom(node_ids.iter(), network_path) else {
|
||||||
return;
|
return;
|
||||||
@@ -5528,12 +5523,12 @@ impl NodeNetworkInterface {
|
|||||||
log::error!("Could not get nested network_metadata in export_ports");
|
log::error!("Could not get nested network_metadata in export_ports");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let TransientMetadata::Loaded(stack_dependents) = &mut network_metadata.transient_metadata.stack_dependents {
|
if let TransientMetadata::Loaded(stack_dependents) = &mut network_metadata.transient_metadata.stack_dependents
|
||||||
if let Some(LayerOwner::None(offset)) = stack_dependents.get_mut(node_id) {
|
&& let Some(LayerOwner::None(offset)) = stack_dependents.get_mut(node_id)
|
||||||
|
{
|
||||||
*offset += shift_sign;
|
*offset += shift_sign;
|
||||||
self.transaction_modified();
|
self.transaction_modified();
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// Shift the upstream layer so that it stays in the same place
|
// Shift the upstream layer so that it stays in the same place
|
||||||
if self.is_layer(node_id, network_path) {
|
if self.is_layer(node_id, network_path) {
|
||||||
@@ -5804,15 +5799,14 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
// A layer is considered to be the height of that layer plus the height to the upstream layer sibling
|
// A layer is considered to be the height of that layer plus the height to the upstream layer sibling
|
||||||
// If a non artboard layer is attempted to be connected to the exports, and there is already an artboard connected, then connect the layer to the artboard.
|
// If a non artboard layer is attempted to be connected to the exports, and there is already an artboard connected, then connect the layer to the artboard.
|
||||||
if let Some(first_layer) = LayerNodeIdentifier::ROOT_PARENT.children(&self.document_metadata).next() {
|
if let Some(first_layer) = LayerNodeIdentifier::ROOT_PARENT.children(&self.document_metadata).next()
|
||||||
if parent == LayerNodeIdentifier::ROOT_PARENT
|
&& parent == LayerNodeIdentifier::ROOT_PARENT
|
||||||
&& self.reference(&layer.to_node(), network_path).is_none_or(|reference| *reference != Some("Artboard".to_string()))
|
&& self.reference(&layer.to_node(), network_path).is_none_or(|reference| *reference != Some("Artboard".to_string()))
|
||||||
&& self.is_artboard(&first_layer.to_node(), network_path)
|
&& self.is_artboard(&first_layer.to_node(), network_path)
|
||||||
{
|
{
|
||||||
parent = first_layer;
|
parent = first_layer;
|
||||||
insert_index = 0;
|
insert_index = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let Some(layer_to_move_position) = self.position(&layer.to_node(), network_path) else {
|
let Some(layer_to_move_position) = self.position(&layer.to_node(), network_path) else {
|
||||||
log::error!("Could not get layer_to_move_position in move_layer_to_stack");
|
log::error!("Could not get layer_to_move_position in move_layer_to_stack");
|
||||||
@@ -5870,8 +5864,7 @@ impl NodeNetworkInterface {
|
|||||||
let mut downstream_height = 0;
|
let mut downstream_height = 0;
|
||||||
let inserting_into_stack =
|
let inserting_into_stack =
|
||||||
!(post_node.input_index() == 1 || matches!(post_node, InputConnector::Export(_)) || !post_node.node_id().is_some_and(|post_node_id| self.is_layer(&post_node_id, network_path)));
|
!(post_node.input_index() == 1 || matches!(post_node, InputConnector::Export(_)) || !post_node.node_id().is_some_and(|post_node_id| self.is_layer(&post_node_id, network_path)));
|
||||||
if inserting_into_stack {
|
if inserting_into_stack && let Some(downstream_node) = post_node.node_id() {
|
||||||
if let Some(downstream_node) = post_node.node_id() {
|
|
||||||
let Some(downstream_node_position) = self.position(&downstream_node, network_path) else {
|
let Some(downstream_node_position) = self.position(&downstream_node, network_path) else {
|
||||||
log::error!("Could not get downstream node position in move_layer_to_stack");
|
log::error!("Could not get downstream node position in move_layer_to_stack");
|
||||||
return;
|
return;
|
||||||
@@ -5886,7 +5879,6 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
downstream_height = lowest_y_position - (downstream_node_position.y + 3);
|
downstream_height = lowest_y_position - (downstream_node_position.y + 3);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut highest_y_position = layer_to_move_position.y;
|
let mut highest_y_position = layer_to_move_position.y;
|
||||||
let mut lowest_y_position = layer_to_move_position.y;
|
let mut lowest_y_position = layer_to_move_position.y;
|
||||||
@@ -5933,8 +5925,9 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If inserting into a stack with a parent, ensure the parent stack has enough space for the child stack
|
// If inserting into a stack with a parent, ensure the parent stack has enough space for the child stack
|
||||||
if parent != LayerNodeIdentifier::ROOT_PARENT {
|
if parent != LayerNodeIdentifier::ROOT_PARENT
|
||||||
if let Some(upstream_sibling) = parent.next_sibling(&self.document_metadata) {
|
&& let Some(upstream_sibling) = parent.next_sibling(&self.document_metadata)
|
||||||
|
{
|
||||||
let Some(parent_position) = self.position(&parent.to_node(), network_path) else {
|
let Some(parent_position) = self.position(&parent.to_node(), network_path) else {
|
||||||
log::error!("Could not get parent position in move_layer_to_stack");
|
log::error!("Could not get parent position in move_layer_to_stack");
|
||||||
return;
|
return;
|
||||||
@@ -5980,7 +5973,6 @@ impl NodeNetworkInterface {
|
|||||||
|
|
||||||
let _ = self.selected_nodes_mut(network_path).unwrap().replace_with(old_selected_nodes);
|
let _ = self.selected_nodes_mut(network_path).unwrap().replace_with(old_selected_nodes);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Connect the layer to a parent layer/node at the top of the stack, or a non layer node midway down the stack
|
// Connect the layer to a parent layer/node at the top of the stack, or a non layer node midway down the stack
|
||||||
if !inserting_into_stack {
|
if !inserting_into_stack {
|
||||||
|
|||||||
@@ -581,12 +581,10 @@ pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], document: &mut DocumentMessageHandler, reset_node_definitions_on_open: bool) -> Option<()> {
|
fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], document: &mut DocumentMessageHandler, reset_node_definitions_on_open: bool) -> Option<()> {
|
||||||
if reset_node_definitions_on_open {
|
if reset_node_definitions_on_open && let Some(Some(reference)) = document.network_interface.reference(node_id, network_path) {
|
||||||
if let Some(Some(reference)) = document.network_interface.reference(node_id, network_path) {
|
|
||||||
let node_definition = resolve_document_node_type(reference)?;
|
let node_definition = resolve_document_node_type(reference)?;
|
||||||
document.network_interface.replace_implementation(node_id, network_path, &mut node_definition.default_node_template());
|
document.network_interface.replace_implementation(node_id, network_path, &mut node_definition.default_node_template());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Upgrade old nodes to use `Context` instead of `()` or `Footprint` as their call argument
|
// Upgrade old nodes to use `Context` instead of `()` or `Footprint` as their call argument
|
||||||
if node.call_argument == graph_craft::concrete!(()) || node.call_argument == graph_craft::concrete!(graphene_std::transform::Footprint) {
|
if node.call_argument == graph_craft::concrete!(()) || node.call_argument == graph_craft::concrete!(graphene_std::transform::Footprint) {
|
||||||
@@ -1018,13 +1016,13 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
.network_interface
|
.network_interface
|
||||||
.input_from_connector(&InputConnector::Node { node_id: *node_id, input_index: 3 }, network_path)?;
|
.input_from_connector(&InputConnector::Node { node_id: *node_id, input_index: 3 }, network_path)?;
|
||||||
|
|
||||||
if let NodeInput::Value { tagged_value, exposed } = quantity_value {
|
if let NodeInput::Value { tagged_value, exposed } = quantity_value
|
||||||
if let TaggedValue::F64(value) = **tagged_value {
|
&& let TaggedValue::F64(value) = **tagged_value
|
||||||
|
{
|
||||||
let new_quantity_value = NodeInput::value(TaggedValue::U32(value as u32), *exposed);
|
let new_quantity_value = NodeInput::value(TaggedValue::U32(value as u32), *exposed);
|
||||||
document.network_interface.set_input(&InputConnector::node(*node_id, 3), new_quantity_value, network_path);
|
document.network_interface.set_input(&InputConnector::node(*node_id, 3), new_quantity_value, network_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Make the "Grid" node, if its input of index 3 is a DVec2 for "angles" instead of a u32 for the "columns" input that now succeeds "angles", move the angle to index 5 (after "columns" and "rows")
|
// Make the "Grid" node, if its input of index 3 is a DVec2 for "angles" instead of a u32 for the "columns" input that now succeeds "angles", move the angle to index 5 (after "columns" and "rows")
|
||||||
if reference == "Grid" && inputs_count == 6 {
|
if reference == "Grid" && inputs_count == 6 {
|
||||||
@@ -1037,8 +1035,9 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
|
|
||||||
let mut upgraded = false;
|
let mut upgraded = false;
|
||||||
|
|
||||||
if let Some(NodeInput::Value { tagged_value, exposed: _ }) = index_3_value {
|
if let Some(NodeInput::Value { tagged_value, exposed: _ }) = index_3_value
|
||||||
if matches!(*tagged_value, TaggedValue::DVec2(_)) {
|
&& matches!(*tagged_value, TaggedValue::DVec2(_))
|
||||||
|
{
|
||||||
// Move index 3 to the end
|
// Move index 3 to the end
|
||||||
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
|
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
|
||||||
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
||||||
@@ -1049,7 +1048,6 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
|
|
||||||
upgraded = true;
|
upgraded = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !upgraded {
|
if !upgraded {
|
||||||
let _ = document.network_interface.replace_inputs(node_id, network_path, &mut current_node_template);
|
let _ = document.network_interface.replace_inputs(node_id, network_path, &mut current_node_template);
|
||||||
|
|||||||
@@ -116,8 +116,9 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
|||||||
self.menu_bar_message_handler.process_message(message, responses, ());
|
self.menu_bar_message_handler.process_message(message, responses, ());
|
||||||
}
|
}
|
||||||
PortfolioMessage::Document(message) => {
|
PortfolioMessage::Document(message) => {
|
||||||
if let Some(document_id) = self.active_document_id {
|
if let Some(document_id) = self.active_document_id
|
||||||
if let Some(document) = self.documents.get_mut(&document_id) {
|
&& let Some(document) = self.documents.get_mut(&document_id)
|
||||||
|
{
|
||||||
let document_inputs = DocumentMessageContext {
|
let document_inputs = DocumentMessageContext {
|
||||||
document_id,
|
document_id,
|
||||||
ipp,
|
ipp,
|
||||||
@@ -133,7 +134,6 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
|||||||
document.process_message(message, responses, document_inputs)
|
document.process_message(message, responses, document_inputs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
PortfolioMessage::Init => {
|
PortfolioMessage::Init => {
|
||||||
@@ -175,13 +175,13 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
PortfolioMessage::AutoSaveActiveDocument => {
|
PortfolioMessage::AutoSaveActiveDocument => {
|
||||||
if let Some(document_id) = self.active_document_id {
|
if let Some(document_id) = self.active_document_id
|
||||||
if let Some(document) = self.active_document_mut() {
|
&& let Some(document) = self.active_document_mut()
|
||||||
|
{
|
||||||
document.set_auto_save_state(true);
|
document.set_auto_save_state(true);
|
||||||
responses.add(PortfolioMessage::AutoSaveDocument { document_id });
|
responses.add(PortfolioMessage::AutoSaveDocument { document_id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
PortfolioMessage::AutoSaveAllDocuments => {
|
PortfolioMessage::AutoSaveAllDocuments => {
|
||||||
for (document_id, document) in self.documents.iter_mut() {
|
for (document_id, document) in self.documents.iter_mut() {
|
||||||
if !document.is_auto_saved() {
|
if !document.is_auto_saved() {
|
||||||
|
|||||||
+2
-2
@@ -272,7 +272,7 @@ fn calculate_isometric_top_line_points(columns: u32, rows: u32, spacing: DVec2,
|
|||||||
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) };
|
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) };
|
||||||
let isometric_spacing = calculate_isometric_offset(spacing, angles);
|
let isometric_spacing = calculate_isometric_offset(spacing, angles);
|
||||||
let isometric_offset = DVec2::new(0., isometric_spacing.y);
|
let isometric_offset = DVec2::new(0., isometric_spacing.y);
|
||||||
let end_isometric_offset = if columns % 2 == 0 { DVec2::ZERO } else { DVec2::new(0., isometric_spacing.y) };
|
let end_isometric_offset = if columns.is_multiple_of(2) { DVec2::ZERO } else { DVec2::new(0., isometric_spacing.y) };
|
||||||
|
|
||||||
(top_left + offset - isometric_offset, top_right - offset - end_isometric_offset)
|
(top_left + offset - isometric_offset, top_right - offset - end_isometric_offset)
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ fn calculate_isometric_bottom_line_points(columns: u32, rows: u32, spacing: DVec
|
|||||||
let bottom_right = calculate_isometric_point(columns - 1, rows - 1, angles, spacing);
|
let bottom_right = calculate_isometric_point(columns - 1, rows - 1, angles, spacing);
|
||||||
|
|
||||||
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) };
|
let offset = if columns == 1 || rows == 1 { DVec2::ZERO } else { DVec2::new(spacing.x * 0.5, 0.) };
|
||||||
let isometric_offset = if columns % 2 == 0 {
|
let isometric_offset = if columns.is_multiple_of(2) {
|
||||||
let offset = calculate_isometric_offset(spacing, angles);
|
let offset = calculate_isometric_offset(spacing, angles);
|
||||||
DVec2::new(0., offset.y)
|
DVec2::new(0., offset.y)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+6
-6
@@ -108,11 +108,11 @@ impl NumberOfPointsDial {
|
|||||||
let viewport = document.metadata().transform_to_viewport(layer);
|
let viewport = document.metadata().transform_to_viewport(layer);
|
||||||
let center = viewport.transform_point2(DVec2::ZERO);
|
let center = viewport.transform_point2(DVec2::ZERO);
|
||||||
|
|
||||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, mouse_position, POINT_RADIUS_HANDLE_SEGMENT_THRESHOLD) {
|
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, mouse_position, POINT_RADIUS_HANDLE_SEGMENT_THRESHOLD)
|
||||||
if closest_segment.layer() == layer {
|
&& closest_segment.layer() == layer
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let point_on_max_radius = star_vertex_position(viewport, 0, sides, radius1, radius2);
|
let point_on_max_radius = star_vertex_position(viewport, 0, sides, radius1, radius2);
|
||||||
|
|
||||||
if inside_star(viewport, sides, radius1, radius2, mouse_position) && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
|
if inside_star(viewport, sides, radius1, radius2, mouse_position) && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
|
||||||
@@ -126,11 +126,11 @@ impl NumberOfPointsDial {
|
|||||||
let viewport = document.metadata().transform_to_viewport(layer);
|
let viewport = document.metadata().transform_to_viewport(layer);
|
||||||
let center = viewport.transform_point2(DVec2::ZERO);
|
let center = viewport.transform_point2(DVec2::ZERO);
|
||||||
|
|
||||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, mouse_position, POINT_RADIUS_HANDLE_SEGMENT_THRESHOLD) {
|
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, mouse_position, POINT_RADIUS_HANDLE_SEGMENT_THRESHOLD)
|
||||||
if closest_segment.layer() == layer {
|
&& closest_segment.layer() == layer
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let point_on_max_radius = polygon_vertex_position(viewport, 0, sides, radius);
|
let point_on_max_radius = polygon_vertex_position(viewport, 0, sides, radius);
|
||||||
|
|
||||||
if inside_polygon(viewport, sides, radius, mouse_position) && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
|
if inside_polygon(viewport, sides, radius, mouse_position) && point_on_max_radius.distance(center) > GIZMO_HIDE_THRESHOLD {
|
||||||
|
|||||||
@@ -691,12 +691,12 @@ impl ShapeState {
|
|||||||
let mut selected_stack = Vec::new();
|
let mut selected_stack = Vec::new();
|
||||||
// Find all subpaths that have been clicked
|
// Find all subpaths that have been clicked
|
||||||
for stroke in vector.stroke_bezier_paths() {
|
for stroke in vector.stroke_bezier_paths() {
|
||||||
if stroke.contains_point(layer_mouse) {
|
if stroke.contains_point(layer_mouse)
|
||||||
if let Some(first) = stroke.manipulator_groups().first() {
|
&& let Some(first) = stroke.manipulator_groups().first()
|
||||||
|
{
|
||||||
selected_stack.push(first.id);
|
selected_stack.push(first.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
state.clear_points();
|
state.clear_points();
|
||||||
|
|
||||||
if selected_stack.is_empty() {
|
if selected_stack.is_empty() {
|
||||||
@@ -929,23 +929,23 @@ impl ShapeState {
|
|||||||
ManipulatorPointId::Anchor(point) => self.move_anchor(point, &vector, delta, layer, None, responses),
|
ManipulatorPointId::Anchor(point) => self.move_anchor(point, &vector, delta, layer, None, responses),
|
||||||
ManipulatorPointId::PrimaryHandle(segment) => {
|
ManipulatorPointId::PrimaryHandle(segment) => {
|
||||||
self.move_primary(segment, delta, layer, responses);
|
self.move_primary(segment, delta, layer, responses);
|
||||||
if let Some(handle) = point.as_handle() {
|
if let Some(handle) = point.as_handle()
|
||||||
if let Some(handles) = vector.colinear_manipulators.iter().find(|handles| handles[0] == handle || handles[1] == handle) {
|
&& let Some(handles) = vector.colinear_manipulators.iter().find(|handles| handles[0] == handle || handles[1] == handle)
|
||||||
|
{
|
||||||
let modification_type = VectorModificationType::SetG1Continuous { handles: *handles, enabled: false };
|
let modification_type = VectorModificationType::SetG1Continuous { handles: *handles, enabled: false };
|
||||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
ManipulatorPointId::EndHandle(segment) => {
|
ManipulatorPointId::EndHandle(segment) => {
|
||||||
self.move_end(segment, delta, layer, responses);
|
self.move_end(segment, delta, layer, responses);
|
||||||
if let Some(handle) = point.as_handle() {
|
if let Some(handle) = point.as_handle()
|
||||||
if let Some(handles) = vector.colinear_manipulators.iter().find(|handles| handles[0] == handle || handles[1] == handle) {
|
&& let Some(handles) = vector.colinear_manipulators.iter().find(|handles| handles[0] == handle || handles[1] == handle)
|
||||||
|
{
|
||||||
let modification_type = VectorModificationType::SetG1Continuous { handles: *handles, enabled: false };
|
let modification_type = VectorModificationType::SetG1Continuous { handles: *handles, enabled: false };
|
||||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
@@ -1078,11 +1078,11 @@ impl ShapeState {
|
|||||||
|
|
||||||
for &point in layer_state.selected_points.iter() {
|
for &point in layer_state.selected_points.iter() {
|
||||||
// Skip a point which has more than 2 segments connected (vector meshes)
|
// Skip a point which has more than 2 segments connected (vector meshes)
|
||||||
if let ManipulatorPointId::Anchor(anchor) = point {
|
if let ManipulatorPointId::Anchor(anchor) = point
|
||||||
if vector.all_connected(anchor).count() > 2 {
|
&& vector.all_connected(anchor).count() > 2
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Here we take handles as the current handle and the most opposite non-colinear-handle
|
// Here we take handles as the current handle and the most opposite non-colinear-handle
|
||||||
|
|
||||||
@@ -1409,11 +1409,12 @@ impl ShapeState {
|
|||||||
|
|
||||||
match point {
|
match point {
|
||||||
ManipulatorPointId::Anchor(anchor) => {
|
ManipulatorPointId::Anchor(anchor) => {
|
||||||
if let Some(handles) = Self::dissolve_anchor(anchor, responses, layer, &vector) {
|
if let Some(handles) = Self::dissolve_anchor(anchor, responses, layer, &vector)
|
||||||
if !vector.all_connected(anchor).any(|a| selected_segments.contains(&a.segment)) && vector.all_connected(anchor).count() <= 2 {
|
&& !vector.all_connected(anchor).any(|a| selected_segments.contains(&a.segment))
|
||||||
|
&& vector.all_connected(anchor).count() <= 2
|
||||||
|
{
|
||||||
missing_anchors.insert(anchor, handles);
|
missing_anchors.insert(anchor, handles);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
deleted_anchors.insert(anchor);
|
deleted_anchors.insert(anchor);
|
||||||
}
|
}
|
||||||
ManipulatorPointId::PrimaryHandle(_) | ManipulatorPointId::EndHandle(_) => {
|
ManipulatorPointId::PrimaryHandle(_) | ManipulatorPointId::EndHandle(_) => {
|
||||||
@@ -1643,15 +1644,15 @@ impl ShapeState {
|
|||||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(handle) = point.as_handle() {
|
} else if let Some(handle) = point.as_handle()
|
||||||
if let Some(handles) = vector.colinear_manipulators.iter().find(|handles| handles[0] == handle || handles[1] == handle) {
|
&& let Some(handles) = vector.colinear_manipulators.iter().find(|handles| handles[0] == handle || handles[1] == handle)
|
||||||
|
{
|
||||||
let modification_type = VectorModificationType::SetG1Continuous { handles: *handles, enabled: false };
|
let modification_type = VectorModificationType::SetG1Continuous { handles: *handles, enabled: false };
|
||||||
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
responses.add(GraphOperationMessage::Vector { layer, modification_type });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a [ManipulatorPoint] that is within the selection threshold and return the layer path, an index to the [ManipulatorGroup], and an enum index for [ManipulatorPoint].
|
/// Find a [ManipulatorPoint] that is within the selection threshold and return the layer path, an index to the [ManipulatorGroup], and an enum index for [ManipulatorPoint].
|
||||||
pub fn find_nearest_point_indices(&mut self, network_interface: &NodeNetworkInterface, mouse_position: DVec2, select_threshold: f64) -> Option<(LayerNodeIdentifier, ManipulatorPointId)> {
|
pub fn find_nearest_point_indices(&mut self, network_interface: &NodeNetworkInterface, mouse_position: DVec2, select_threshold: f64) -> Option<(LayerNodeIdentifier, ManipulatorPointId)> {
|
||||||
@@ -1728,19 +1729,22 @@ impl ShapeState {
|
|||||||
let bezier = bezier.apply_transformation(|point| viewspace.transform_point2(point));
|
let bezier = bezier.apply_transformation(|point| viewspace.transform_point2(point));
|
||||||
let valid = |handle: DVec2, control: DVec2| handle.distance_squared(control) > crate::consts::HIDE_HANDLE_DISTANCE.powi(2);
|
let valid = |handle: DVec2, control: DVec2| handle.distance_squared(control) > crate::consts::HIDE_HANDLE_DISTANCE.powi(2);
|
||||||
|
|
||||||
if let Some(primary_handle) = bezier.handle_start() {
|
if let Some(primary_handle) = bezier.handle_start()
|
||||||
if valid(primary_handle, bezier.start) && (bezier.handle_end().is_some() || valid(primary_handle, bezier.end)) && primary_handle.distance_squared(pos) <= closest_distance_squared {
|
&& valid(primary_handle, bezier.start)
|
||||||
|
&& (bezier.handle_end().is_some() || valid(primary_handle, bezier.end))
|
||||||
|
&& primary_handle.distance_squared(pos) <= closest_distance_squared
|
||||||
|
{
|
||||||
closest_distance_squared = primary_handle.distance_squared(pos);
|
closest_distance_squared = primary_handle.distance_squared(pos);
|
||||||
manipulator_point = Some(ManipulatorPointId::PrimaryHandle(segment_id));
|
manipulator_point = Some(ManipulatorPointId::PrimaryHandle(segment_id));
|
||||||
}
|
}
|
||||||
}
|
if let Some(end_handle) = bezier.handle_end()
|
||||||
if let Some(end_handle) = bezier.handle_end() {
|
&& valid(end_handle, bezier.end)
|
||||||
if valid(end_handle, bezier.end) && end_handle.distance_squared(pos) <= closest_distance_squared {
|
&& end_handle.distance_squared(pos) <= closest_distance_squared
|
||||||
|
{
|
||||||
closest_distance_squared = end_handle.distance_squared(pos);
|
closest_distance_squared = end_handle.distance_squared(pos);
|
||||||
manipulator_point = Some(ManipulatorPointId::EndHandle(segment_id));
|
manipulator_point = Some(ManipulatorPointId::EndHandle(segment_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Anchors
|
// Anchors
|
||||||
for (&id, &point) in vector.point_domain.ids().iter().zip(vector.point_domain.positions()) {
|
for (&id, &point) in vector.point_domain.ids().iter().zip(vector.point_domain.positions()) {
|
||||||
|
|||||||
@@ -276,24 +276,24 @@ impl SnapManager {
|
|||||||
snapped_points.push(closest_curve.clone());
|
snapped_points.push(closest_curve.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if document.snapping_state.target_enabled(SnapTarget::Grid(GridSnapTarget::Line)) {
|
if document.snapping_state.target_enabled(SnapTarget::Grid(GridSnapTarget::Line))
|
||||||
if let Some(closest_line) = get_closest_line(&snap_results.grid_lines) {
|
&& let Some(closest_line) = get_closest_line(&snap_results.grid_lines)
|
||||||
|
{
|
||||||
snapped_points.push(closest_line.clone());
|
snapped_points.push(closest_line.clone());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !constrained {
|
if !constrained {
|
||||||
if document.snapping_state.target_enabled(SnapTarget::Path(PathSnapTarget::IntersectionPoint)) {
|
if document.snapping_state.target_enabled(SnapTarget::Path(PathSnapTarget::IntersectionPoint))
|
||||||
if let Some(closest_curves_intersection) = get_closest_intersection(point.document_point, &snap_results.curves) {
|
&& let Some(closest_curves_intersection) = get_closest_intersection(point.document_point, &snap_results.curves)
|
||||||
|
{
|
||||||
snapped_points.push(closest_curves_intersection);
|
snapped_points.push(closest_curves_intersection);
|
||||||
}
|
}
|
||||||
}
|
if document.snapping_state.target_enabled(SnapTarget::Grid(GridSnapTarget::Intersection))
|
||||||
if document.snapping_state.target_enabled(SnapTarget::Grid(GridSnapTarget::Intersection)) {
|
&& let Some(closest_grid_intersection) = get_grid_intersection(point.document_point, &snap_results.grid_lines)
|
||||||
if let Some(closest_grid_intersection) = get_grid_intersection(point.document_point, &snap_results.grid_lines) {
|
{
|
||||||
snapped_points.push(closest_grid_intersection);
|
snapped_points.push(closest_grid_intersection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if to_path {
|
if to_path {
|
||||||
snapped_points.retain(|i| matches!(i.target, SnapTarget::Path(_)));
|
snapped_points.retain(|i| matches!(i.target, SnapTarget::Path(_)));
|
||||||
|
|||||||
@@ -67,8 +67,11 @@ impl AlignmentSnapper {
|
|||||||
let target_position = target_point.document_point;
|
let target_position = target_point.document_point;
|
||||||
|
|
||||||
// Perpendicular snap for line's endpoints
|
// Perpendicular snap for line's endpoints
|
||||||
if let Some(quad) = target_point.quad.map(|q| q.0) {
|
if let Some(quad) = target_point.quad.map(|q| q.0)
|
||||||
if quad[0] == quad[3] && quad[1] == quad[2] && quad[0] == target_point.document_point {
|
&& quad[0] == quad[3]
|
||||||
|
&& quad[1] == quad[2]
|
||||||
|
&& quad[0] == target_point.document_point
|
||||||
|
{
|
||||||
let [p1, p2, ..] = quad;
|
let [p1, p2, ..] = quad;
|
||||||
let Some(direction) = (p2 - p1).try_normalize() else { return };
|
let Some(direction) = (p2 - p1).try_normalize() else { return };
|
||||||
let normal = DVec2::new(-direction.y, direction.x);
|
let normal = DVec2::new(-direction.y, direction.x);
|
||||||
@@ -98,7 +101,6 @@ impl AlignmentSnapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let [point_on_x, point_on_y] = if let SnapConstraint::Line { origin, direction } = constraint {
|
let [point_on_x, point_on_y] = if let SnapConstraint::Line { origin, direction } = constraint {
|
||||||
[
|
[
|
||||||
Quad::intersect_rays(target_point.document_point, DVec2::Y, origin, direction),
|
Quad::intersect_rays(target_point.document_point, DVec2::Y, origin, direction),
|
||||||
|
|||||||
@@ -769,17 +769,17 @@ impl BoundingBoxManager {
|
|||||||
let edges = self.check_selected_edges(input.mouse.position);
|
let edges = self.check_selected_edges(input.mouse.position);
|
||||||
|
|
||||||
let is_near_square = edges.is_some_and(|hover_edge| self.over_extended_edge_midpoint(input.mouse.position, hover_edge));
|
let is_near_square = edges.is_some_and(|hover_edge| self.over_extended_edge_midpoint(input.mouse.position, hover_edge));
|
||||||
if dragging_bounds && is_near_square {
|
if dragging_bounds
|
||||||
if let Some(skew_edge) = skew_edge {
|
&& is_near_square
|
||||||
if self.check_skew_handle(input.mouse.position, skew_edge) {
|
&& let Some(skew_edge) = skew_edge
|
||||||
|
&& self.check_skew_handle(input.mouse.position, skew_edge)
|
||||||
|
{
|
||||||
if skew_edge.0 || skew_edge.1 {
|
if skew_edge.0 || skew_edge.1 {
|
||||||
return MouseCursorIcon::EWResize;
|
return MouseCursorIcon::EWResize;
|
||||||
} else if skew_edge.2 || skew_edge.3 {
|
} else if skew_edge.2 || skew_edge.3 {
|
||||||
return MouseCursorIcon::NSResize;
|
return MouseCursorIcon::NSResize;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
match edges {
|
match edges {
|
||||||
Some((top, bottom, left, right)) => match (top, bottom, left, right) {
|
Some((top, bottom, left, right)) => match (top, bottom, left, right) {
|
||||||
|
|||||||
@@ -588,11 +588,11 @@ pub fn make_path_editable_is_allowed(network_interface: &mut NodeNetworkInterfac
|
|||||||
|
|
||||||
// Must not already have an existing Path node, in the right-most part of the layer chain, which has an empty set of modifications
|
// Must not already have an existing Path node, in the right-most part of the layer chain, which has an empty set of modifications
|
||||||
// (otherwise users could repeatedly keep running this command and stacking up empty Path nodes)
|
// (otherwise users could repeatedly keep running this command and stacking up empty Path nodes)
|
||||||
if let Some(TaggedValue::VectorModification(modifications)) = NodeGraphLayer::new(first_layer, network_interface).find_input("Path", 1) {
|
if let Some(TaggedValue::VectorModification(modifications)) = NodeGraphLayer::new(first_layer, network_interface).find_input("Path", 1)
|
||||||
if modifications.as_ref() == &VectorModification::default() {
|
&& modifications.as_ref() == &VectorModification::default()
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Some(first_layer)
|
Some(first_layer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -411,8 +411,9 @@ impl Fsm for BrushToolFsmState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
(BrushToolFsmState::Drawing, BrushToolMessage::PointerMove) => {
|
(BrushToolFsmState::Drawing, BrushToolMessage::PointerMove) => {
|
||||||
if let Some(layer) = tool_data.layer {
|
if let Some(layer) = tool_data.layer
|
||||||
if let Some(stroke) = tool_data.strokes.last_mut() {
|
&& let Some(stroke) = tool_data.strokes.last_mut()
|
||||||
|
{
|
||||||
let layer_position = document
|
let layer_position = document
|
||||||
.network_interface
|
.network_interface
|
||||||
.document_metadata()
|
.document_metadata()
|
||||||
@@ -423,7 +424,6 @@ impl Fsm for BrushToolFsmState {
|
|||||||
|
|
||||||
stroke.trace.push(BrushInputSample { position: layer_position })
|
stroke.trace.push(BrushInputSample { position: layer_position })
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tool_data.update_strokes(responses);
|
tool_data.update_strokes(responses);
|
||||||
|
|
||||||
BrushToolFsmState::Drawing
|
BrushToolFsmState::Drawing
|
||||||
|
|||||||
@@ -367,8 +367,7 @@ fn extend_path_with_next_segment(tool_data: &mut FreehandToolData, position: DVe
|
|||||||
modification_type: VectorModificationType::InsertPoint { id, position },
|
modification_type: VectorModificationType::InsertPoint { id, position },
|
||||||
});
|
});
|
||||||
|
|
||||||
if extend {
|
if extend && let Some((_, previous_position)) = tool_data.end_point {
|
||||||
if let Some((_, previous_position)) = tool_data.end_point {
|
|
||||||
let next_id = SegmentId::generate();
|
let next_id = SegmentId::generate();
|
||||||
let points = [previous_position, id];
|
let points = [previous_position, id];
|
||||||
|
|
||||||
@@ -381,7 +380,6 @@ fn extend_path_with_next_segment(tool_data: &mut FreehandToolData, position: DVe
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tool_data.dragged = true;
|
tool_data.dragged = true;
|
||||||
tool_data.end_point = Some((position, id));
|
tool_data.end_point = Some((position, id));
|
||||||
|
|||||||
@@ -474,11 +474,11 @@ impl Fsm for GradientToolFsmState {
|
|||||||
}
|
}
|
||||||
(GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => {
|
(GradientToolFsmState::Drawing, GradientToolMessage::PointerOutsideViewport { .. }) => {
|
||||||
// Auto-panning
|
// Auto-panning
|
||||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses)
|
||||||
if let Some(selected_gradient) = &mut tool_data.selected_gradient {
|
&& let Some(selected_gradient) = &mut tool_data.selected_gradient
|
||||||
|
{
|
||||||
selected_gradient.transform.translation += shift;
|
selected_gradient.transform.translation += shift;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
GradientToolFsmState::Drawing
|
GradientToolFsmState::Drawing
|
||||||
}
|
}
|
||||||
@@ -497,13 +497,12 @@ impl Fsm for GradientToolFsmState {
|
|||||||
tool_data.snap_manager.cleanup(responses);
|
tool_data.snap_manager.cleanup(responses);
|
||||||
let was_dragging = tool_data.selected_gradient.is_some();
|
let was_dragging = tool_data.selected_gradient.is_some();
|
||||||
|
|
||||||
if !was_dragging {
|
if !was_dragging
|
||||||
if let Some(selected_layer) = document.click(input, viewport) {
|
&& let Some(selected_layer) = document.click(input, viewport)
|
||||||
if let Some(gradient) = get_gradient(selected_layer, &document.network_interface) {
|
&& let Some(gradient) = get_gradient(selected_layer, &document.network_interface)
|
||||||
|
{
|
||||||
tool_data.selected_gradient = Some(SelectedGradient::new(gradient, selected_layer, document));
|
tool_data.selected_gradient = Some(SelectedGradient::new(gradient, selected_layer, document));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
GradientToolFsmState::Ready
|
GradientToolFsmState::Ready
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -750,8 +750,8 @@ impl PathToolData {
|
|||||||
|
|
||||||
// If the point is already selected and shift (`extend_selection`) is used, keep the selection unchanged.
|
// If the point is already selected and shift (`extend_selection`) is used, keep the selection unchanged.
|
||||||
// Otherwise, select the first point within the threshold.
|
// Otherwise, select the first point within the threshold.
|
||||||
if !(already_selected && extend_selection) {
|
if !(already_selected && extend_selection)
|
||||||
if let Some(updated_selection_info) = shape_editor.change_point_selection(
|
&& let Some(updated_selection_info) = shape_editor.change_point_selection(
|
||||||
&document.network_interface,
|
&document.network_interface,
|
||||||
input.mouse.position,
|
input.mouse.position,
|
||||||
SELECTION_THRESHOLD,
|
SELECTION_THRESHOLD,
|
||||||
@@ -761,7 +761,6 @@ impl PathToolData {
|
|||||||
) {
|
) {
|
||||||
selection_info = updated_selection_info;
|
selection_info = updated_selection_info;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(selected_points) = selection_info {
|
if let Some(selected_points) = selection_info {
|
||||||
self.drag_start_pos = input.mouse.position;
|
self.drag_start_pos = input.mouse.position;
|
||||||
@@ -778,8 +777,7 @@ impl PathToolData {
|
|||||||
self.saved_selection_before_handle_drag = old_selection;
|
self.saved_selection_before_handle_drag = old_selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
if handle_drag_from_anchor {
|
if handle_drag_from_anchor && let Some((layer, point)) = shape_editor.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD) {
|
||||||
if let Some((layer, point)) = shape_editor.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD) {
|
|
||||||
// Check that selected point is an anchor
|
// Check that selected point is an anchor
|
||||||
if let (Some(point_id), Some(vector)) = (point.as_anchor(), document.network_interface.compute_modified_vector(layer)) {
|
if let (Some(point_id), Some(vector)) = (point.as_anchor(), document.network_interface.compute_modified_vector(layer)) {
|
||||||
let handles = vector.all_connected(point_id).collect::<Vec<_>>();
|
let handles = vector.all_connected(point_id).collect::<Vec<_>>();
|
||||||
@@ -801,7 +799,6 @@ impl PathToolData {
|
|||||||
responses.add(PathToolMessage::SelectedPointUpdated);
|
responses.add(PathToolMessage::SelectedPointUpdated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if let Some((Some(point), Some(vector), layer)) = shape_editor
|
if let Some((Some(point), Some(vector), layer)) = shape_editor
|
||||||
.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD)
|
.find_nearest_point_indices(&document.network_interface, input.mouse.position, SELECTION_THRESHOLD)
|
||||||
@@ -2098,8 +2095,9 @@ impl Fsm for PathToolFsmState {
|
|||||||
let break_molding = input.keyboard.get(break_colinear_molding as usize);
|
let break_molding = input.keyboard.get(break_colinear_molding as usize);
|
||||||
|
|
||||||
// Logic for molding segment
|
// Logic for molding segment
|
||||||
if let Some(segment) = &mut tool_data.segment {
|
if let Some(segment) = &mut tool_data.segment
|
||||||
if let Some(molding_segment_handles) = tool_data.molding_info {
|
&& let Some(molding_segment_handles) = tool_data.molding_info
|
||||||
|
{
|
||||||
tool_data.temporary_adjacent_handles_while_molding = segment.mold_handle_positions(
|
tool_data.temporary_adjacent_handles_while_molding = segment.mold_handle_positions(
|
||||||
document,
|
document,
|
||||||
responses,
|
responses,
|
||||||
@@ -2111,7 +2109,6 @@ impl Fsm for PathToolFsmState {
|
|||||||
|
|
||||||
return PathToolFsmState::Dragging(tool_data.dragging_state);
|
return PathToolFsmState::Dragging(tool_data.dragging_state);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let anchor_and_handle_toggled = input.keyboard.get(move_anchor_with_handles as usize);
|
let anchor_and_handle_toggled = input.keyboard.get(move_anchor_with_handles as usize);
|
||||||
let initial_press = anchor_and_handle_toggled && !tool_data.select_anchor_toggled;
|
let initial_press = anchor_and_handle_toggled && !tool_data.select_anchor_toggled;
|
||||||
@@ -3384,16 +3381,14 @@ fn update_dynamic_hints(
|
|||||||
let at_least_one_point_selected = shape_editor.selected_points().count() >= 1;
|
let at_least_one_point_selected = shape_editor.selected_points().count() >= 1;
|
||||||
|
|
||||||
let mut single_colinear_anchor_selected = false;
|
let mut single_colinear_anchor_selected = false;
|
||||||
if single_anchor_selected {
|
if single_anchor_selected
|
||||||
if let (Some(anchor), Some(layer)) = (
|
&& let (Some(anchor), Some(layer)) = (
|
||||||
shape_editor.selected_points().next(),
|
shape_editor.selected_points().next(),
|
||||||
document.network_interface.selected_nodes().selected_layers(document.metadata()).next(),
|
document.network_interface.selected_nodes().selected_layers(document.metadata()).next(),
|
||||||
) {
|
) && let Some(vector) = document.network_interface.compute_modified_vector(layer)
|
||||||
if let Some(vector) = document.network_interface.compute_modified_vector(layer) {
|
{
|
||||||
single_colinear_anchor_selected = vector.colinear(*anchor)
|
single_colinear_anchor_selected = vector.colinear(*anchor)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let drag_selected_hints = vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")];
|
let drag_selected_hints = vec![HintInfo::mouse(MouseMotion::LmbDrag, "Drag Selected")];
|
||||||
let mut delete_selected_hints = vec![HintInfo::keys([Key::Delete], "Delete Selected")];
|
let mut delete_selected_hints = vec![HintInfo::keys([Key::Delete], "Delete Selected")];
|
||||||
|
|||||||
@@ -728,8 +728,8 @@ impl PenToolData {
|
|||||||
|
|
||||||
// Store the segment
|
// Store the segment
|
||||||
let id = SegmentId::generate();
|
let id = SegmentId::generate();
|
||||||
if self.path_closed {
|
if self.path_closed
|
||||||
if let Some((handles, handle1_pos)) = match self.get_opposite_handle_type(TargetHandle::PreviewInHandle, &vector) {
|
&& let Some((handles, handle1_pos)) = match self.get_opposite_handle_type(TargetHandle::PreviewInHandle, &vector) {
|
||||||
TargetHandle::PriorOutHandle(segment) => {
|
TargetHandle::PriorOutHandle(segment) => {
|
||||||
let handles = [HandleId::end(id), HandleId::primary(segment)];
|
let handles = [HandleId::end(id), HandleId::primary(segment)];
|
||||||
let handle1_pos = handles[1].to_manipulator_point().get_position(&vector);
|
let handle1_pos = handles[1].to_manipulator_point().get_position(&vector);
|
||||||
@@ -751,7 +751,6 @@ impl PenToolData {
|
|||||||
});
|
});
|
||||||
self.cleanup(responses);
|
self.cleanup(responses);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.prior_segment = Some(id);
|
self.prior_segment = Some(id);
|
||||||
|
|
||||||
@@ -938,11 +937,11 @@ impl PenToolData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn move_anchor_and_handles(&mut self, delta: DVec2, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>, vector: &Vector) {
|
fn move_anchor_and_handles(&mut self, delta: DVec2, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>, vector: &Vector) {
|
||||||
if self.handle_end.is_none() {
|
if self.handle_end.is_none()
|
||||||
if let Some(latest_pt) = self.latest_point_mut() {
|
&& let Some(latest_pt) = self.latest_point_mut()
|
||||||
|
{
|
||||||
latest_pt.pos += delta;
|
latest_pt.pos += delta;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let Some(end_point) = self.prior_segment_endpoint else { return };
|
let Some(end_point) = self.prior_segment_endpoint else { return };
|
||||||
|
|
||||||
@@ -1210,11 +1209,12 @@ impl PenToolData {
|
|||||||
snap.update_indicator(snapped);
|
snap.update_indicator(snapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(relative) = relative.map(|layer| transform.transform_point2(layer)) {
|
if let Some(relative) = relative.map(|layer| transform.transform_point2(layer))
|
||||||
if (relative - document_pos) != DVec2::ZERO && (relative - document_pos).length_squared() > f64::EPSILON * 100. {
|
&& (relative - document_pos) != DVec2::ZERO
|
||||||
|
&& (relative - document_pos).length_squared() > f64::EPSILON * 100.
|
||||||
|
{
|
||||||
self.angle = -(relative - document_pos).angle_to(DVec2::X)
|
self.angle = -(relative - document_pos).angle_to(DVec2::X)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
transform.inverse().transform_point2(document_pos)
|
transform.inverse().transform_point2(document_pos)
|
||||||
}
|
}
|
||||||
@@ -1245,8 +1245,9 @@ impl PenToolData {
|
|||||||
self.current_layer = Some(layer);
|
self.current_layer = Some(layer);
|
||||||
self.extend_existing_path(document, layer, point, position);
|
self.extend_existing_path(document, layer, point, position);
|
||||||
return;
|
return;
|
||||||
} else if preferences.vector_meshes {
|
} else if preferences.vector_meshes
|
||||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance) {
|
&& let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance)
|
||||||
|
{
|
||||||
let (point, segments) = closest_segment.adjusted_insert(responses);
|
let (point, segments) = closest_segment.adjusted_insert(responses);
|
||||||
let layer = closest_segment.layer();
|
let layer = closest_segment.layer();
|
||||||
let position = closest_segment.closest_point_document();
|
let position = closest_segment.closest_point_document();
|
||||||
@@ -1259,7 +1260,6 @@ impl PenToolData {
|
|||||||
self.extend_existing_path(document, layer, point, position);
|
self.extend_existing_path(document, layer, point, position);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if append {
|
if append {
|
||||||
if let Some((layer, point, _)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
if let Some((layer, point, _)) = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences) {
|
||||||
@@ -1629,14 +1629,15 @@ impl Fsm for PenToolFsmState {
|
|||||||
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
let viewport_vec = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||||
|
|
||||||
let close_to_point = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
let close_to_point = closest_point(document, viewport_vec, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
||||||
if preferences.vector_meshes && !close_to_point {
|
if preferences.vector_meshes
|
||||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance) {
|
&& !close_to_point
|
||||||
|
&& let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport_vec, tolerance)
|
||||||
|
{
|
||||||
let pos = closest_segment.closest_point_to_viewport();
|
let pos = closest_segment.closest_point_to_viewport();
|
||||||
let perp = closest_segment.calculate_perp(document);
|
let perp = closest_segment.calculate_perp(document);
|
||||||
overlay_context.manipulator_anchor(pos, true, None);
|
overlay_context.manipulator_anchor(pos, true, None);
|
||||||
overlay_context.line(pos - perp * SEGMENT_OVERLAY_SIZE, pos + perp * SEGMENT_OVERLAY_SIZE, Some(COLOR_OVERLAY_BLUE), None);
|
overlay_context.line(pos - perp * SEGMENT_OVERLAY_SIZE, pos + perp * SEGMENT_OVERLAY_SIZE, Some(COLOR_OVERLAY_BLUE), None);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
tool_data.snap_manager.draw_overlays(SnapData::new(document, input, viewport), &mut overlay_context);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -1758,15 +1759,13 @@ impl Fsm for PenToolFsmState {
|
|||||||
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
let snapped = tool_data.snap_manager.free_snap(&SnapData::new(document, input, viewport), &point, SnapTypeConfiguration::default());
|
||||||
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
let viewport = document.metadata().document_to_viewport.transform_point2(snapped.snapped_point_document);
|
||||||
let close_to_point = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
let close_to_point = closest_point(document, viewport, tolerance, document.metadata().all_layers(), |_| false, preferences).is_some();
|
||||||
if !close_to_point {
|
if !close_to_point && let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport, tolerance) {
|
||||||
if let Some(closest_segment) = shape_editor.upper_closest_segment(&document.network_interface, viewport, tolerance) {
|
|
||||||
let pos = closest_segment.closest_point_to_viewport();
|
let pos = closest_segment.closest_point_to_viewport();
|
||||||
let perp = closest_segment.calculate_perp(document);
|
let perp = closest_segment.calculate_perp(document);
|
||||||
overlay_context.manipulator_anchor(pos, true, None);
|
overlay_context.manipulator_anchor(pos, true, None);
|
||||||
overlay_context.line(pos - perp * SEGMENT_OVERLAY_SIZE, pos + perp * SEGMENT_OVERLAY_SIZE, Some(COLOR_OVERLAY_BLUE), None);
|
overlay_context.line(pos - perp * SEGMENT_OVERLAY_SIZE, pos + perp * SEGMENT_OVERLAY_SIZE, Some(COLOR_OVERLAY_BLUE), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Display a filled overlay of the shape if the new point closes the path
|
// Display a filled overlay of the shape if the new point closes the path
|
||||||
if let Some(latest_point) = tool_data.latest_point() {
|
if let Some(latest_point) = tool_data.latest_point() {
|
||||||
|
|||||||
@@ -776,21 +776,21 @@ impl Fsm for SelectToolFsmState {
|
|||||||
|
|
||||||
let is_resizing_or_rotating = matches!(self, SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. } | SelectToolFsmState::RotatingBounds);
|
let is_resizing_or_rotating = matches!(self, SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. } | SelectToolFsmState::RotatingBounds);
|
||||||
|
|
||||||
if overlay_context.visibility_settings.transform_cage() {
|
if overlay_context.visibility_settings.transform_cage()
|
||||||
if let Some(bounds) = tool_data.bounding_box_manager.as_mut() {
|
&& let Some(bounds) = tool_data.bounding_box_manager.as_mut()
|
||||||
|
{
|
||||||
let edges = bounds.check_selected_edges(input.mouse.position);
|
let edges = bounds.check_selected_edges(input.mouse.position);
|
||||||
let is_skewing = matches!(self, SelectToolFsmState::SkewingBounds { .. });
|
let is_skewing = matches!(self, SelectToolFsmState::SkewingBounds { .. });
|
||||||
let is_near_square = edges.is_some_and(|hover_edge| bounds.over_extended_edge_midpoint(input.mouse.position, hover_edge));
|
let is_near_square = edges.is_some_and(|hover_edge| bounds.over_extended_edge_midpoint(input.mouse.position, hover_edge));
|
||||||
if is_skewing || (dragging_bounds && is_near_square && !is_resizing_or_rotating) {
|
if is_skewing || (dragging_bounds && is_near_square && !is_resizing_or_rotating) {
|
||||||
bounds.render_skew_gizmos(&mut overlay_context, tool_data.skew_edge);
|
bounds.render_skew_gizmos(&mut overlay_context, tool_data.skew_edge);
|
||||||
}
|
}
|
||||||
if !is_skewing && dragging_bounds {
|
if !is_skewing
|
||||||
if let Some(edges) = edges {
|
&& dragging_bounds && let Some(edges) = edges
|
||||||
|
{
|
||||||
tool_data.skew_edge = bounds.get_closest_edge(edges, input.mouse.position);
|
tool_data.skew_edge = bounds.get_closest_edge(edges, input.mouse.position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let might_resize_or_rotate = dragging_bounds || rotating_bounds;
|
let might_resize_or_rotate = dragging_bounds || rotating_bounds;
|
||||||
let can_get_into_other_states = might_resize_or_rotate && !matches!(self, SelectToolFsmState::Dragging { .. });
|
let can_get_into_other_states = might_resize_or_rotate && !matches!(self, SelectToolFsmState::Dragging { .. });
|
||||||
@@ -887,9 +887,10 @@ impl Fsm for SelectToolFsmState {
|
|||||||
compass_rose_state.axis_type().and_then(|axis| axis.is_constraint().then_some((axis, true)))
|
compass_rose_state.axis_type().and_then(|axis| axis.is_constraint().then_some((axis, true)))
|
||||||
};
|
};
|
||||||
|
|
||||||
if show_compass_with_ring.is_some() {
|
if show_compass_with_ring.is_some()
|
||||||
if let Some((axis, hover)) = axis_state {
|
&& let Some((axis, hover)) = axis_state
|
||||||
if axis.is_constraint() {
|
&& axis.is_constraint()
|
||||||
|
{
|
||||||
let e0 = tool_data
|
let e0 = tool_data
|
||||||
.bounding_box_manager
|
.bounding_box_manager
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -913,8 +914,6 @@ impl Fsm for SelectToolFsmState {
|
|||||||
let line_center = tool_data.line_center;
|
let line_center = tool_data.line_center;
|
||||||
overlay_context.line(line_center - direction * viewport_diagonal, line_center + direction * viewport_diagonal, Some(color), None);
|
overlay_context.line(line_center - direction * viewport_diagonal, line_center + direction * viewport_diagonal, Some(color), None);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if axis_state.is_none_or(|(axis, _)| !axis.is_constraint()) && tool_data.axis_align {
|
if axis_state.is_none_or(|(axis, _)| !axis.is_constraint()) && tool_data.axis_align {
|
||||||
let mouse_position = mouse_position - tool_data.drag_start;
|
let mouse_position = mouse_position - tool_data.drag_start;
|
||||||
@@ -1369,12 +1368,12 @@ impl Fsm for SelectToolFsmState {
|
|||||||
}
|
}
|
||||||
(SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => {
|
(SelectToolFsmState::ResizingBounds | SelectToolFsmState::SkewingBounds { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => {
|
||||||
// Auto-panning
|
// Auto-panning
|
||||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses)
|
||||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
&& let Some(bounds) = &mut tool_data.bounding_box_manager
|
||||||
|
{
|
||||||
bounds.center_of_transformation += shift;
|
bounds.center_of_transformation += shift;
|
||||||
bounds.original_bound_transform.translation += shift;
|
bounds.original_bound_transform.translation += shift;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -1499,11 +1498,11 @@ impl Fsm for SelectToolFsmState {
|
|||||||
tool_data.axis_align = false;
|
tool_data.axis_align = false;
|
||||||
tool_data.snap_manager.cleanup(responses);
|
tool_data.snap_manager.cleanup(responses);
|
||||||
|
|
||||||
if !matches!(self, SelectToolFsmState::DraggingPivot) {
|
if !matches!(self, SelectToolFsmState::DraggingPivot)
|
||||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
&& let Some(bounds) = &mut tool_data.bounding_box_manager
|
||||||
|
{
|
||||||
bounds.original_transforms.clear();
|
bounds.original_transforms.clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let selection = tool_data.nested_selection_behavior;
|
let selection = tool_data.nested_selection_behavior;
|
||||||
SelectToolFsmState::Ready { selection }
|
SelectToolFsmState::Ready { selection }
|
||||||
|
|||||||
@@ -560,11 +560,11 @@ impl Fsm for TextToolFsmState {
|
|||||||
bounding_box_manager.render_quad(&mut overlay_context);
|
bounding_box_manager.render_quad(&mut overlay_context);
|
||||||
// Draw red overlay if text is clipped
|
// Draw red overlay if text is clipped
|
||||||
let transformed_quad = layer_transform * bounds;
|
let transformed_quad = layer_transform * bounds;
|
||||||
if let Some((text, font, typesetting, _)) = graph_modification_utils::get_text(layer.unwrap(), &document.network_interface) {
|
if let Some((text, font, typesetting, _)) = graph_modification_utils::get_text(layer.unwrap(), &document.network_interface)
|
||||||
if lines_clipping(text.as_str(), font, font_cache, typesetting) {
|
&& lines_clipping(text.as_str(), font, font_cache, typesetting)
|
||||||
|
{
|
||||||
overlay_context.line(transformed_quad.0[2], transformed_quad.0[3], Some(COLOR_OVERLAY_RED), Some(3.));
|
overlay_context.line(transformed_quad.0[2], transformed_quad.0[3], Some(COLOR_OVERLAY_RED), Some(3.));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bounding_box_manager.render_overlays(&mut overlay_context, false);
|
bounding_box_manager.render_overlays(&mut overlay_context, false);
|
||||||
}
|
}
|
||||||
@@ -697,8 +697,9 @@ impl Fsm for TextToolFsmState {
|
|||||||
TextToolFsmState::Dragging
|
TextToolFsmState::Dragging
|
||||||
}
|
}
|
||||||
(TextToolFsmState::ResizingBounds, TextToolMessage::PointerMove { center, lock_ratio }) => {
|
(TextToolFsmState::ResizingBounds, TextToolMessage::PointerMove { center, lock_ratio }) => {
|
||||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
if let Some(bounds) = &mut tool_data.bounding_box_manager
|
||||||
if let Some(movement) = &mut bounds.selected_edges {
|
&& let Some(movement) = &mut bounds.selected_edges
|
||||||
|
{
|
||||||
let (centered, constrain) = (input.keyboard.key(center), input.keyboard.key(lock_ratio));
|
let (centered, constrain) = (input.keyboard.key(center), input.keyboard.key(lock_ratio));
|
||||||
let center_position = centered.then_some(bounds.center_of_transformation);
|
let center_position = centered.then_some(bounds.center_of_transformation);
|
||||||
|
|
||||||
@@ -754,7 +755,6 @@ impl Fsm for TextToolFsmState {
|
|||||||
];
|
];
|
||||||
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
tool_data.auto_panning.setup_by_mouse_position(input, viewport, &messages, responses);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
TextToolFsmState::ResizingBounds
|
TextToolFsmState::ResizingBounds
|
||||||
}
|
}
|
||||||
(_, TextToolMessage::PointerMove { .. }) => {
|
(_, TextToolMessage::PointerMove { .. }) => {
|
||||||
@@ -771,12 +771,12 @@ impl Fsm for TextToolFsmState {
|
|||||||
}
|
}
|
||||||
(TextToolFsmState::ResizingBounds | TextToolFsmState::Dragging, TextToolMessage::PointerOutsideViewport { .. }) => {
|
(TextToolFsmState::ResizingBounds | TextToolFsmState::Dragging, TextToolMessage::PointerOutsideViewport { .. }) => {
|
||||||
// Auto-panning
|
// Auto-panning
|
||||||
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
|
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses)
|
||||||
if let Some(bounds) = &mut tool_data.bounding_box_manager {
|
&& let Some(bounds) = &mut tool_data.bounding_box_manager
|
||||||
|
{
|
||||||
bounds.center_of_transformation += shift;
|
bounds.center_of_transformation += shift;
|
||||||
bounds.original_bound_transform.translation += shift;
|
bounds.original_bound_transform.translation += shift;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -808,12 +808,10 @@ impl Fsm for TextToolFsmState {
|
|||||||
let has_dragged = (start - end).length_squared() > DRAG_THRESHOLD * DRAG_THRESHOLD;
|
let has_dragged = (start - end).length_squared() > DRAG_THRESHOLD * DRAG_THRESHOLD;
|
||||||
|
|
||||||
// Check if the user has clicked (no dragging) on some existing text
|
// Check if the user has clicked (no dragging) on some existing text
|
||||||
if !has_dragged {
|
if !has_dragged && let Some(clicked_text_layer_path) = TextToolData::check_click(document, input, font_cache) {
|
||||||
if let Some(clicked_text_layer_path) = TextToolData::check_click(document, input, font_cache) {
|
|
||||||
tool_data.start_editing_layer(clicked_text_layer_path, self, document, font_cache, responses);
|
tool_data.start_editing_layer(clicked_text_layer_path, self, document, font_cache, responses);
|
||||||
return TextToolFsmState::Editing;
|
return TextToolFsmState::Editing;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise create some new text
|
// Otherwise create some new text
|
||||||
let constraint_size = has_dragged.then_some((start - end).abs());
|
let constraint_size = has_dragged.then_some((start - end).abs());
|
||||||
@@ -846,12 +844,10 @@ impl Fsm for TextToolFsmState {
|
|||||||
bounds.original_transforms.clear();
|
bounds.original_transforms.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if drag_too_small {
|
if drag_too_small && let Some(layer_info) = &tool_data.layer_dragging {
|
||||||
if let Some(layer_info) = &tool_data.layer_dragging {
|
|
||||||
tool_data.start_editing_layer(layer_info.id, self, document, font_cache, responses);
|
tool_data.start_editing_layer(layer_info.id, self, document, font_cache, responses);
|
||||||
return TextToolFsmState::Editing;
|
return TextToolFsmState::Editing;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tool_data.layer_dragging.take();
|
tool_data.layer_dragging.take();
|
||||||
|
|
||||||
TextToolFsmState::Ready
|
TextToolFsmState::Ready
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ impl NodeGraphExecutor {
|
|||||||
use image::{ImageFormat, RgbImage, RgbaImage};
|
use image::{ImageFormat, RgbImage, RgbaImage};
|
||||||
|
|
||||||
let Some(image) = RgbaImage::from_raw(width, height, data) else {
|
let Some(image) = RgbaImage::from_raw(width, height, data) else {
|
||||||
return Err(format!("Failed to create image buffer for export"));
|
return Err("Failed to create image buffer for export".to_string());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut encoded = Vec::new();
|
let mut encoded = Vec::new();
|
||||||
@@ -298,7 +298,7 @@ impl NodeGraphExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileType::Svg => {
|
FileType::Svg => {
|
||||||
return Err(format!("SVG cannot be exported from an image buffer"));
|
return Err("SVG cannot be exported from an image buffer".to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -686,11 +686,11 @@ impl NodeNetwork {
|
|||||||
fn replace_node_inputs(&mut self, node_id: NodeId, old_input: (NodeId, usize), new_input: (NodeId, usize)) {
|
fn replace_node_inputs(&mut self, node_id: NodeId, old_input: (NodeId, usize), new_input: (NodeId, usize)) {
|
||||||
let Some(node) = self.nodes.get_mut(&node_id) else { return };
|
let Some(node) = self.nodes.get_mut(&node_id) else { return };
|
||||||
node.inputs.iter_mut().for_each(|input| {
|
node.inputs.iter_mut().for_each(|input| {
|
||||||
if let NodeInput::Node { node_id: input_id, output_index, .. } = input {
|
if let NodeInput::Node { node_id: input_id, output_index, .. } = input
|
||||||
if (*input_id, *output_index) == old_input {
|
&& (*input_id, *output_index) == old_input
|
||||||
|
{
|
||||||
(*input_id, *output_index) = new_input;
|
(*input_id, *output_index) = new_input;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -738,13 +738,13 @@ impl NodeNetwork {
|
|||||||
let mut are_inputs_used = vec![false; number_of_inputs];
|
let mut are_inputs_used = vec![false; number_of_inputs];
|
||||||
for node in &self.nodes {
|
for node in &self.nodes {
|
||||||
for node_input in &node.1.inputs {
|
for node_input in &node.1.inputs {
|
||||||
if let NodeInput::Import { import_index, .. } = node_input {
|
if let NodeInput::Import { import_index, .. } = node_input
|
||||||
if let Some(is_used) = are_inputs_used.get_mut(*import_index) {
|
&& let Some(is_used) = are_inputs_used.get_mut(*import_index)
|
||||||
|
{
|
||||||
*is_used = true;
|
*is_used = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
are_inputs_used
|
are_inputs_used
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,8 +937,9 @@ impl NodeNetwork {
|
|||||||
|
|
||||||
fn remove_id_node(&mut self, id: NodeId) -> Result<(), String> {
|
fn remove_id_node(&mut self, id: NodeId) -> Result<(), String> {
|
||||||
let node = self.nodes.get(&id).ok_or_else(|| format!("Node with id {id} does not exist"))?.clone();
|
let node = self.nodes.get(&id).ok_or_else(|| format!("Node with id {id} does not exist"))?.clone();
|
||||||
if let DocumentNodeImplementation::ProtoNode(ident) = &node.implementation {
|
if let DocumentNodeImplementation::ProtoNode(ident) = &node.implementation
|
||||||
if ident.name == "graphene_core::ops::IdentityNode" {
|
&& *ident == graphene_core::ops::identity::IDENTIFIER
|
||||||
|
{
|
||||||
assert_eq!(node.inputs.len(), 1, "Id node has more than one input");
|
assert_eq!(node.inputs.len(), 1, "Id node has more than one input");
|
||||||
if let NodeInput::Node { node_id, output_index, .. } = node.inputs[0] {
|
if let NodeInput::Node { node_id, output_index, .. } = node.inputs[0] {
|
||||||
let node_input_output_index = output_index;
|
let node_input_output_index = output_index;
|
||||||
@@ -956,9 +957,8 @@ impl NodeNetwork {
|
|||||||
node_id: output_node_id,
|
node_id: output_node_id,
|
||||||
output_index: output_output_index,
|
output_index: output_output_index,
|
||||||
..
|
..
|
||||||
} = input
|
} = input && *output_node_id == id
|
||||||
{
|
{
|
||||||
if *output_node_id == id {
|
|
||||||
*output_node_id = input_node_id;
|
*output_node_id = input_node_id;
|
||||||
*output_output_index = node_input_output_index;
|
*output_output_index = node_input_output_index;
|
||||||
|
|
||||||
@@ -968,20 +968,18 @@ impl NodeNetwork {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for node_input in self.exports.iter_mut() {
|
for node_input in self.exports.iter_mut() {
|
||||||
if let NodeInput::Node { node_id, output_index, .. } = node_input {
|
if let NodeInput::Node { node_id, output_index, .. } = node_input
|
||||||
if *node_id == id {
|
&& *node_id == id
|
||||||
|
{
|
||||||
*node_id = input_node_id;
|
*node_id = input_node_id;
|
||||||
*output_index = node_input_output_index;
|
*output_index = node_input_output_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.nodes.remove(&id);
|
self.nodes.remove(&id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1047,8 +1045,9 @@ impl NodeNetwork {
|
|||||||
let nodes: Vec<_> = self.nodes.into_iter().map(|(id, node)| (id, node.resolve_proto_node())).collect();
|
let nodes: Vec<_> = self.nodes.into_iter().map(|(id, node)| (id, node.resolve_proto_node())).collect();
|
||||||
|
|
||||||
// Create a network to evaluate each output
|
// Create a network to evaluate each output
|
||||||
if self.exports.len() == 1 {
|
if self.exports.len() == 1
|
||||||
if let NodeInput::Node { node_id, .. } = self.exports[0] {
|
&& let NodeInput::Node { node_id, .. } = self.exports[0]
|
||||||
|
{
|
||||||
return vec![ProtoNetwork {
|
return vec![ProtoNetwork {
|
||||||
inputs: Vec::new(),
|
inputs: Vec::new(),
|
||||||
output: node_id,
|
output: node_id,
|
||||||
@@ -1056,7 +1055,6 @@ impl NodeNetwork {
|
|||||||
}]
|
}]
|
||||||
.into_iter();
|
.into_iter();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Create a network to evaluate each output
|
// Create a network to evaluate each output
|
||||||
let networks: Vec<_> = self
|
let networks: Vec<_> = self
|
||||||
|
|||||||
@@ -308,11 +308,11 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||||||
let mut new_name = id.name.replace('\n', " ");
|
let mut new_name = id.name.replace('\n', " ");
|
||||||
|
|
||||||
// Remove struct generics for all nodes except for the IntoNode and ConvertNode
|
// Remove struct generics for all nodes except for the IntoNode and ConvertNode
|
||||||
if !(new_name.contains("IntoNode") || new_name.contains("ConvertNode")) {
|
if !(new_name.contains("IntoNode") || new_name.contains("ConvertNode"))
|
||||||
if let Some((path, _generics)) = new_name.split_once("<") {
|
&& let Some((path, _generics)) = new_name.split_once("<")
|
||||||
|
{
|
||||||
new_name = path.to_string();
|
new_name = path.to_string();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let nid = ProtoNodeIdentifier { name: Cow::Owned(new_name) };
|
let nid = ProtoNodeIdentifier { name: Cow::Owned(new_name) };
|
||||||
map.entry(nid).or_default().insert(types.clone(), c);
|
map.entry(nid).or_default().insert(types.clone(), c);
|
||||||
|
|||||||
@@ -50,15 +50,13 @@ impl BasicItem {
|
|||||||
let token: LitStr = attribute.parse_args()?;
|
let token: LitStr = attribute.parse_args()?;
|
||||||
self.icon = Some(token.value());
|
self.icon = Some(token.value());
|
||||||
}
|
}
|
||||||
if attribute.path().is_ident("doc") {
|
if attribute.path().is_ident("doc")
|
||||||
if let Meta::NameValue(meta_name_value) = &attribute.meta {
|
&& let Meta::NameValue(meta_name_value) = &attribute.meta
|
||||||
if let Expr::Lit(el) = &meta_name_value.value {
|
&& let Expr::Lit(el) = &meta_name_value.value
|
||||||
if let syn::Lit::Str(token) = &el.lit {
|
&& let syn::Lit::Str(token) = &el.lit
|
||||||
|
{
|
||||||
self.description = Some(token.value());
|
self.description = Some(token.value());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -530,11 +530,11 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
if let Some(range) = &number_mode_range {
|
if let Some(range) = &number_mode_range
|
||||||
if range.elems.len() != 2 {
|
&& range.elems.len() != 2
|
||||||
|
{
|
||||||
return Err(Error::new_spanned(range, "Expected a tuple of two values for `range` for the min and max, respectively"));
|
return Err(Error::new_spanned(range, "Expected a tuple of two values for `range` for the min and max, respectively"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let unit = extract_attribute(attrs, "unit")
|
let unit = extract_attribute(attrs, "unit")
|
||||||
.map(|attr| attr.parse_args::<LitStr>().map_err(|_e| Error::new_spanned(attr, "Expected a unit type as string".to_string())))
|
.map(|attr| attr.parse_args::<LitStr>().map_err(|_e| Error::new_spanned(attr, "Expected a unit type as string".to_string())))
|
||||||
@@ -641,9 +641,10 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
|||||||
fn parse_node_type(ty: &Type) -> (bool, Option<Type>, Option<Type>) {
|
fn parse_node_type(ty: &Type) -> (bool, Option<Type>, Option<Type>) {
|
||||||
if let Type::ImplTrait(impl_trait) = ty {
|
if let Type::ImplTrait(impl_trait) = ty {
|
||||||
for bound in &impl_trait.bounds {
|
for bound in &impl_trait.bounds {
|
||||||
if let syn::TypeParamBound::Trait(trait_bound) = bound {
|
if let syn::TypeParamBound::Trait(trait_bound) = bound
|
||||||
if trait_bound.path.segments.last().is_some_and(|seg| seg.ident == "Node") {
|
&& trait_bound.path.segments.last().is_some_and(|seg| seg.ident == "Node")
|
||||||
if let syn::PathArguments::AngleBracketed(args) = &trait_bound.path.segments.last().unwrap().arguments {
|
&& let syn::PathArguments::AngleBracketed(args) = &trait_bound.path.segments.last().unwrap().arguments
|
||||||
|
{
|
||||||
let input_type = args.args.iter().find_map(|arg| if let syn::GenericArgument::Type(ty) = arg { Some(ty.clone()) } else { None });
|
let input_type = args.args.iter().find_map(|arg| if let syn::GenericArgument::Type(ty) = arg { Some(ty.clone()) } else { None });
|
||||||
let output_type = args.args.iter().find_map(|arg| {
|
let output_type = args.args.iter().find_map(|arg| {
|
||||||
if let syn::GenericArgument::AssocType(assoc_type) = arg {
|
if let syn::GenericArgument::AssocType(assoc_type) = arg {
|
||||||
@@ -656,8 +657,6 @@ fn parse_node_type(ty: &Type) -> (bool, Option<Type>, Option<Type>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
(false, None, None)
|
(false, None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user