Fix clippy warnings (#3085)
* Run clippy fix * Clippy v2 * Make const item static * Cargo fmt
This commit is contained in:
parent
c6ec3a27ca
commit
7377871106
|
|
@ -442,7 +442,7 @@ mod test {
|
||||||
assert_eq!(layers_before_copy.len(), 3);
|
assert_eq!(layers_before_copy.len(), 3);
|
||||||
assert_eq!(layers_after_copy.len(), 6);
|
assert_eq!(layers_after_copy.len(), 6);
|
||||||
|
|
||||||
println!("{:?} {:?}", layers_after_copy, layers_before_copy);
|
println!("{layers_after_copy:?} {layers_before_copy:?}");
|
||||||
|
|
||||||
assert_eq!(layers_after_copy[5], shape_id);
|
assert_eq!(layers_after_copy[5], shape_id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -479,7 +479,7 @@ impl<const LENGTH: usize> Iterator for BitVectorIter<'_, LENGTH> {
|
||||||
impl<const LENGTH: usize> Display for BitVector<LENGTH> {
|
impl<const LENGTH: usize> Display for BitVector<LENGTH> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
for storage in self.0.iter().rev() {
|
for storage in self.0.iter().rev() {
|
||||||
write!(f, "{:0width$b}", storage, width = STORAGE_SIZE_BITS)?;
|
write!(f, "{storage:0STORAGE_SIZE_BITS$b}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,11 @@ mod test {
|
||||||
fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool, file: &mut std::fs::File) {
|
fn print_tree_node(tree: &DebugMessageTree, prefix: &str, is_last: bool, file: &mut std::fs::File) {
|
||||||
// Print the current node
|
// Print the current node
|
||||||
let (branch, child_prefix) = if tree.message_handler_data_fields().is_some() || tree.message_handler_fields().is_some() {
|
let (branch, child_prefix) = if tree.message_handler_data_fields().is_some() || tree.message_handler_fields().is_some() {
|
||||||
("├── ", format!("{}│ ", prefix))
|
("├── ", format!("{prefix}│ "))
|
||||||
|
} else if is_last {
|
||||||
|
("└── ", format!("{prefix} "))
|
||||||
} else {
|
} else {
|
||||||
if is_last {
|
("├── ", format!("{prefix}│ "))
|
||||||
("└── ", format!("{} ", prefix))
|
|
||||||
} else {
|
|
||||||
("├── ", format!("{}│ ", prefix))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if tree.path().is_empty() {
|
if tree.path().is_empty() {
|
||||||
|
|
@ -101,7 +99,7 @@ mod test {
|
||||||
let is_last_field = i == len - 1;
|
let is_last_field = i == len - 1;
|
||||||
let branch = if is_last_field { "└── " } else { "├── " };
|
let branch = if is_last_field { "└── " } else { "├── " };
|
||||||
|
|
||||||
file.write_all(format!("{}{}{}\n", child_prefix, branch, field).as_bytes()).unwrap();
|
file.write_all(format!("{child_prefix}{branch}{field}\n").as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,9 +107,9 @@ mod test {
|
||||||
if let Some(data) = tree.message_handler_fields() {
|
if let Some(data) = tree.message_handler_fields() {
|
||||||
let len = data.fields().len();
|
let len = data.fields().len();
|
||||||
let (branch, child_prefix) = if tree.message_handler_data_fields().is_some() {
|
let (branch, child_prefix) = if tree.message_handler_data_fields().is_some() {
|
||||||
("├── ", format!("{}│ ", prefix))
|
("├── ", format!("{prefix}│ "))
|
||||||
} else {
|
} else {
|
||||||
("└── ", format!("{} ", prefix))
|
("└── ", format!("{prefix} "))
|
||||||
};
|
};
|
||||||
|
|
||||||
const FRONTEND_MESSAGE_STR: &str = "FrontendMessage";
|
const FRONTEND_MESSAGE_STR: &str = "FrontendMessage";
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,32 @@ pub fn get_current_normalized_pivot(inputs: &[NodeInput]) -> DVec2 {
|
||||||
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { pivot } else { DVec2::splat(0.5) }
|
if let Some(&TaggedValue::DVec2(pivot)) = inputs[5].as_value() { pivot } else { DVec2::splat(0.5) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand a bounds to avoid div zero errors
|
||||||
|
fn clamp_bounds(bounds_min: DVec2, mut bounds_max: DVec2) -> [DVec2; 2] {
|
||||||
|
let bounds_size = bounds_max - bounds_min;
|
||||||
|
if bounds_size.x < 1e-10 {
|
||||||
|
bounds_max.x = bounds_min.x + 1.;
|
||||||
|
}
|
||||||
|
if bounds_size.y < 1e-10 {
|
||||||
|
bounds_max.y = bounds_min.y + 1.;
|
||||||
|
}
|
||||||
|
[bounds_min, bounds_max]
|
||||||
|
}
|
||||||
|
/// Returns corners of all subpaths
|
||||||
|
fn subpath_bounds(subpaths: &[Subpath<PointId>]) -> [DVec2; 2] {
|
||||||
|
subpaths
|
||||||
|
.iter()
|
||||||
|
.filter_map(|subpath| subpath.bounding_box())
|
||||||
|
.reduce(|b1, b2| [b1[0].min(b2[0]), b1[1].max(b2[1])])
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns corners of all subpaths (but expanded to avoid division-by-zero errors)
|
||||||
|
pub fn nonzero_subpath_bounds(subpaths: &[Subpath<PointId>]) -> [DVec2; 2] {
|
||||||
|
let [bounds_min, bounds_max] = subpath_bounds(subpaths);
|
||||||
|
clamp_bounds(bounds_min, bounds_max)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -138,29 +164,3 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand a bounds to avoid div zero errors
|
|
||||||
fn clamp_bounds(bounds_min: DVec2, mut bounds_max: DVec2) -> [DVec2; 2] {
|
|
||||||
let bounds_size = bounds_max - bounds_min;
|
|
||||||
if bounds_size.x < 1e-10 {
|
|
||||||
bounds_max.x = bounds_min.x + 1.;
|
|
||||||
}
|
|
||||||
if bounds_size.y < 1e-10 {
|
|
||||||
bounds_max.y = bounds_min.y + 1.;
|
|
||||||
}
|
|
||||||
[bounds_min, bounds_max]
|
|
||||||
}
|
|
||||||
/// Returns corners of all subpaths
|
|
||||||
fn subpath_bounds(subpaths: &[Subpath<PointId>]) -> [DVec2; 2] {
|
|
||||||
subpaths
|
|
||||||
.iter()
|
|
||||||
.filter_map(|subpath| subpath.bounding_box())
|
|
||||||
.reduce(|b1, b2| [b1[0].min(b2[0]), b1[1].max(b2[1])])
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns corners of all subpaths (but expanded to avoid division-by-zero errors)
|
|
||||||
pub fn nonzero_subpath_bounds(subpaths: &[Subpath<PointId>]) -> [DVec2; 2] {
|
|
||||||
let [bounds_min, bounds_max] = subpath_bounds(subpaths);
|
|
||||||
clamp_bounds(bounds_min, bounds_max)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ impl NodePropertiesContext<'_> {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
widget_override_lambda(*node_id, index, self)
|
widget_override_lambda(*node_id, index, self)
|
||||||
.map_err(|error| log::error!("Error in widget override lambda: {}", error))
|
.map_err(|error| log::error!("Error in widget override lambda: {error}"))
|
||||||
.ok()
|
.ok()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -1944,10 +1944,10 @@ fn static_input_properties() -> InputProperties {
|
||||||
"string".to_string(),
|
"string".to_string(),
|
||||||
Box::new(|node_id, index, context| {
|
Box::new(|node_id, index, context| {
|
||||||
let Some(value) = context.network_interface.input_data(&node_id, index, "string_properties", context.selection_network_path) else {
|
let Some(value) = context.network_interface.input_data(&node_id, index, "string_properties", context.selection_network_path) else {
|
||||||
return Err(format!("Could not get string properties for node {}", node_id));
|
return Err(format!("Could not get string properties for node {node_id}"));
|
||||||
};
|
};
|
||||||
let Some(string) = value.as_str() else {
|
let Some(string) = value.as_str() else {
|
||||||
return Err(format!("Could not downcast string properties for node {}", node_id));
|
return Err(format!("Could not downcast string properties for node {node_id}"));
|
||||||
};
|
};
|
||||||
Ok(node_properties::string_properties(string))
|
Ok(node_properties::string_properties(string))
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec
|
||||||
document_node: DocumentNode {
|
document_node: DocumentNode {
|
||||||
inputs,
|
inputs,
|
||||||
manual_composition: Some(input_type.clone()),
|
manual_composition: Some(input_type.clone()),
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(id.clone().into()),
|
implementation: DocumentNodeImplementation::ProtoNode(id.clone()),
|
||||||
visible: true,
|
visible: true,
|
||||||
skip_deduplication: false,
|
skip_deduplication: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -1516,7 +1516,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||||
let mut nodes = Vec::new();
|
let mut nodes = Vec::new();
|
||||||
for node_id in &self.frontend_nodes {
|
for node_id in &self.frontend_nodes {
|
||||||
let Some(node_bbox) = network_interface.node_bounding_box(node_id, breadcrumb_network_path) else {
|
let Some(node_bbox) = network_interface.node_bounding_box(node_id, breadcrumb_network_path) else {
|
||||||
log::error!("Could not get bbox for node: {:?}", node_id);
|
log::error!("Could not get bbox for node: {node_id:?}");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1721,7 +1721,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
||||||
}
|
}
|
||||||
NodeGraphMessage::ToggleLocked { node_id } => {
|
NodeGraphMessage::ToggleLocked { node_id } => {
|
||||||
let Some(node_metadata) = network_interface.document_network_metadata().persistent_metadata.node_metadata.get(&node_id) else {
|
let Some(node_metadata) = network_interface.document_network_metadata().persistent_metadata.node_metadata.get(&node_id) else {
|
||||||
log::error!("Cannot get node {:?} in NodeGraphMessage::ToggleLocked", node_id);
|
log::error!("Cannot get node {node_id:?} in NodeGraphMessage::ToggleLocked");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2486,7 +2486,7 @@ impl NodeGraphMessageHandler {
|
||||||
data_type: frontend_data_type,
|
data_type: frontend_data_type,
|
||||||
name: "Output 1".to_string(),
|
name: "Output 1".to_string(),
|
||||||
description: String::new(),
|
description: String::new(),
|
||||||
resolved_type: format!("{:?}", output_type),
|
resolved_type: format!("{output_type:?}"),
|
||||||
connected_to,
|
connected_to,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2518,7 +2518,7 @@ impl NodeGraphMessageHandler {
|
||||||
data_type,
|
data_type,
|
||||||
name: output_name,
|
name: output_name,
|
||||||
description: String::new(),
|
description: String::new(),
|
||||||
resolved_type: format!("{:?}", output_type),
|
resolved_type: format!("{output_type:?}"),
|
||||||
connected_to,
|
connected_to,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1156,7 +1156,7 @@ impl OverlayContextInternal {
|
||||||
let move_to = last_point != Some(start_id);
|
let move_to = last_point != Some(start_id);
|
||||||
last_point = Some(end_id);
|
last_point = Some(end_id);
|
||||||
|
|
||||||
self.bezier_to_path(bezier, row.transform.clone(), move_to, &mut path);
|
self.bezier_to_path(bezier, *row.transform, move_to, &mut path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the path
|
// Render the path
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,7 @@ impl NodeNetworkInterface {
|
||||||
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") {
|
if protonode.name.contains("PathModifyNode") && node.inputs.len() < 3 {
|
||||||
if node.inputs.len() < 3 {
|
|
||||||
node.inputs.push(NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath));
|
node.inputs.push(NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +81,6 @@ impl NodeNetworkInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Public immutable getters for the network interface
|
// Public immutable getters for the network interface
|
||||||
impl NodeNetworkInterface {
|
impl NodeNetworkInterface {
|
||||||
|
|
@ -821,7 +819,7 @@ impl NodeNetworkInterface {
|
||||||
data_type,
|
data_type,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
resolved_type: format!("{:?}", input_type),
|
resolved_type: format!("{input_type:?}"),
|
||||||
connected_to,
|
connected_to,
|
||||||
},
|
},
|
||||||
click_target,
|
click_target,
|
||||||
|
|
@ -1069,7 +1067,7 @@ impl NodeNetworkInterface {
|
||||||
|
|
||||||
pub fn reference(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&Option<String>> {
|
pub fn reference(&self, node_id: &NodeId, network_path: &[NodeId]) -> Option<&Option<String>> {
|
||||||
let Some(node_metadata) = self.node_metadata(node_id, network_path) else {
|
let Some(node_metadata) = self.node_metadata(node_id, network_path) else {
|
||||||
log::error!("Could not get reference for node: {:?}", node_id);
|
log::error!("Could not get reference for node: {node_id:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
Some(&node_metadata.persistent_metadata.reference)
|
Some(&node_metadata.persistent_metadata.reference)
|
||||||
|
|
@ -2522,7 +2520,7 @@ impl NodeNetworkInterface {
|
||||||
InputConnector::Node { node_id, input_index } => {
|
InputConnector::Node { node_id, input_index } => {
|
||||||
let input_metadata = self.transient_input_metadata(node_id, *input_index, network_path)?;
|
let input_metadata = self.transient_input_metadata(node_id, *input_index, network_path)?;
|
||||||
let TransientMetadata::Loaded(wire) = &input_metadata.wire else {
|
let TransientMetadata::Loaded(wire) = &input_metadata.wire else {
|
||||||
log::error!("Could not load wire for input: {:?}", input);
|
log::error!("Could not load wire for input: {input:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
wire.clone()
|
wire.clone()
|
||||||
|
|
@ -2530,7 +2528,7 @@ impl NodeNetworkInterface {
|
||||||
InputConnector::Export(export_index) => {
|
InputConnector::Export(export_index) => {
|
||||||
let network_metadata = self.network_metadata(network_path)?;
|
let network_metadata = self.network_metadata(network_path)?;
|
||||||
let Some(TransientMetadata::Loaded(wire)) = network_metadata.transient_metadata.wires.get(*export_index) else {
|
let Some(TransientMetadata::Loaded(wire)) = network_metadata.transient_metadata.wires.get(*export_index) else {
|
||||||
log::error!("Could not load wire for input: {:?}", input);
|
log::error!("Could not load wire for input: {input:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
wire.clone()
|
wire.clone()
|
||||||
|
|
@ -2701,12 +2699,12 @@ impl NodeNetworkInterface {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let Some(input_position) = self.get_input_center(&input, network_path) else {
|
let Some(input_position) = self.get_input_center(&input, network_path) else {
|
||||||
log::error!("Could not get dom rect for wire end in root node: {:?}", input);
|
log::error!("Could not get dom rect for wire end in root node: {input:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let upstream_output = OutputConnector::node(root_node.node_id, root_node.output_index);
|
let upstream_output = OutputConnector::node(root_node.node_id, root_node.output_index);
|
||||||
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
||||||
log::error!("Could not get dom rect for wire start in root node: {:?}", upstream_output);
|
log::error!("Could not get dom rect for wire start in root node: {upstream_output:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
||||||
|
|
@ -2733,7 +2731,7 @@ impl NodeNetworkInterface {
|
||||||
/// Returns the vector subpath and a boolean of whether the wire should be thick.
|
/// Returns the vector subpath and a boolean of whether the wire should be thick.
|
||||||
pub fn vector_wire_from_input(&mut self, input: &InputConnector, wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<(BezPath, bool)> {
|
pub fn vector_wire_from_input(&mut self, input: &InputConnector, wire_style: GraphWireStyle, network_path: &[NodeId]) -> Option<(BezPath, bool)> {
|
||||||
let Some(input_position) = self.get_input_center(input, network_path) else {
|
let Some(input_position) = self.get_input_center(input, network_path) else {
|
||||||
log::error!("Could not get dom rect for wire end: {:?}", input);
|
log::error!("Could not get dom rect for wire end: {input:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
// An upstream output could not be found, so the wire does not exist, but it should still be loaded as as empty vector
|
// An upstream output could not be found, so the wire does not exist, but it should still be loaded as as empty vector
|
||||||
|
|
@ -2741,7 +2739,7 @@ impl NodeNetworkInterface {
|
||||||
return Some((BezPath::new(), false));
|
return Some((BezPath::new(), false));
|
||||||
};
|
};
|
||||||
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
let Some(output_position) = self.get_output_center(&upstream_output, network_path) else {
|
||||||
log::error!("Could not get dom rect for wire start: {:?}", upstream_output);
|
log::error!("Could not get dom rect for wire start: {upstream_output:?}");
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
let vertical_end = input.node_id().is_some_and(|node_id| self.is_layer(&node_id, network_path) && input.input_index() == 0);
|
||||||
|
|
@ -3357,7 +3355,7 @@ impl NodeNetworkInterface {
|
||||||
self.selected_nodes()
|
self.selected_nodes()
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|node| self.is_layer(&node, &[]))
|
.filter(|node| self.is_layer(node, &[]))
|
||||||
.filter_map(|layer| self.document_metadata.bounding_box_viewport(LayerNodeIdentifier::new(*layer, self)))
|
.filter_map(|layer| self.document_metadata.bounding_box_viewport(LayerNodeIdentifier::new(*layer, self)))
|
||||||
.reduce(Quad::combine_bounds)
|
.reduce(Quad::combine_bounds)
|
||||||
}
|
}
|
||||||
|
|
@ -3366,7 +3364,7 @@ impl NodeNetworkInterface {
|
||||||
self.selected_nodes()
|
self.selected_nodes()
|
||||||
.0
|
.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|node| self.is_layer(&node, &[]) && !self.is_locked(&node, &[]))
|
.filter(|node| self.is_layer(node, &[]) && !self.is_locked(node, &[]))
|
||||||
.filter_map(|layer| self.document_metadata.bounding_box_viewport(LayerNodeIdentifier::new(*layer, self)))
|
.filter_map(|layer| self.document_metadata.bounding_box_viewport(LayerNodeIdentifier::new(*layer, self)))
|
||||||
.reduce(Quad::combine_bounds)
|
.reduce(Quad::combine_bounds)
|
||||||
}
|
}
|
||||||
|
|
@ -4138,7 +4136,7 @@ impl NodeNetworkInterface {
|
||||||
if let DocumentNodeImplementation::Network(network) = &node.implementation {
|
if let DocumentNodeImplementation::Network(network) = &node.implementation {
|
||||||
let number_of_exports = network.exports.len();
|
let number_of_exports = network.exports.len();
|
||||||
let Some(metadata) = self.node_metadata_mut(node_id, network_path) else {
|
let Some(metadata) = self.node_metadata_mut(node_id, network_path) else {
|
||||||
log::error!("Could not get metadata for node: {:?}", node_id);
|
log::error!("Could not get metadata for node: {node_id:?}");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
metadata.persistent_metadata.output_names.resize(number_of_exports, "".to_string());
|
metadata.persistent_metadata.output_names.resize(number_of_exports, "".to_string());
|
||||||
|
|
|
||||||
|
|
@ -1083,8 +1083,8 @@ mod tests {
|
||||||
*hashmap.entry(node.node.clone()).or_default() += 1;
|
*hashmap.entry(node.node.clone()).or_default() += 1;
|
||||||
});
|
});
|
||||||
let duplicates = hashmap.iter().filter(|(_, count)| **count > 1).map(|(node, _)| &node.name).collect::<Vec<_>>();
|
let duplicates = hashmap.iter().filter(|(_, count)| **count > 1).map(|(node, _)| &node.name).collect::<Vec<_>>();
|
||||||
if duplicates.len() > 0 {
|
if !duplicates.is_empty() {
|
||||||
panic!("Duplicate entries in `NODE_REPLACEMENTS`: {:?}", duplicates);
|
panic!("Duplicate entries in `NODE_REPLACEMENTS`: {duplicates:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,14 +101,9 @@ impl Circle {
|
||||||
};
|
};
|
||||||
|
|
||||||
let dimensions = (start - end).abs();
|
let dimensions = (start - end).abs();
|
||||||
let radius: f64;
|
|
||||||
|
|
||||||
// We keep the smaller dimension's scale at 1 and scale the other dimension accordingly
|
// We keep the smaller dimension's scale at 1 and scale the other dimension accordingly
|
||||||
if dimensions.x > dimensions.y {
|
let radius: f64 = if dimensions.x > dimensions.y { dimensions.y / 2. } else { dimensions.x / 2. };
|
||||||
radius = dimensions.y / 2.;
|
|
||||||
} else {
|
|
||||||
radius = dimensions.x / 2.;
|
|
||||||
}
|
|
||||||
|
|
||||||
responses.add(NodeGraphMessage::SetInput {
|
responses.add(NodeGraphMessage::SetInput {
|
||||||
input_connector: InputConnector::node(node_id, 1),
|
input_connector: InputConnector::node(node_id, 1),
|
||||||
|
|
|
||||||
|
|
@ -210,18 +210,18 @@ mod test_line_tool {
|
||||||
async fn get_line_node_inputs(editor: &mut EditorTestUtils) -> Option<(DVec2, DVec2)> {
|
async fn get_line_node_inputs(editor: &mut EditorTestUtils) -> Option<(DVec2, DVec2)> {
|
||||||
let document = editor.active_document();
|
let document = editor.active_document();
|
||||||
let network_interface = &document.network_interface;
|
let network_interface = &document.network_interface;
|
||||||
let node_id = network_interface
|
|
||||||
|
network_interface
|
||||||
.selected_nodes()
|
.selected_nodes()
|
||||||
.selected_visible_and_unlocked_layers(network_interface)
|
.selected_visible_and_unlocked_layers(network_interface)
|
||||||
.filter_map(|layer| {
|
.filter_map(|layer| {
|
||||||
let node_inputs = NodeGraphLayer::new(layer, &network_interface).find_node_inputs("Line")?;
|
let node_inputs = NodeGraphLayer::new(layer, network_interface).find_node_inputs("Line")?;
|
||||||
let (Some(&TaggedValue::DVec2(start)), Some(&TaggedValue::DVec2(end))) = (node_inputs[1].as_value(), node_inputs[2].as_value()) else {
|
let (Some(&TaggedValue::DVec2(start)), Some(&TaggedValue::DVec2(end))) = (node_inputs[1].as_value(), node_inputs[2].as_value()) else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
Some((start, end))
|
Some((start, end))
|
||||||
})
|
})
|
||||||
.next();
|
.next()
|
||||||
node_id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -245,11 +245,7 @@ mod test_line_tool {
|
||||||
editor.new_document().await;
|
editor.new_document().await;
|
||||||
editor.handle_message(NavigationMessage::CanvasZoomSet { zoom_factor: 2. }).await;
|
editor.handle_message(NavigationMessage::CanvasZoomSet { zoom_factor: 2. }).await;
|
||||||
editor.handle_message(NavigationMessage::CanvasPan { delta: DVec2::new(100., 50.) }).await;
|
editor.handle_message(NavigationMessage::CanvasPan { delta: DVec2::new(100., 50.) }).await;
|
||||||
editor
|
editor.handle_message(NavigationMessage::CanvasTiltSet { angle_radians: 30_f64.to_radians() }).await;
|
||||||
.handle_message(NavigationMessage::CanvasTiltSet {
|
|
||||||
angle_radians: (30. as f64).to_radians(),
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
editor.drag_tool(ToolType::Line, 0., 0., 100., 100., ModifierKeys::empty()).await;
|
editor.drag_tool(ToolType::Line, 0., 0., 100., 100., ModifierKeys::empty()).await;
|
||||||
if let Some((start_input, end_input)) = get_line_node_inputs(&mut editor).await {
|
if let Some((start_input, end_input)) = get_line_node_inputs(&mut editor).await {
|
||||||
let document = editor.active_document();
|
let document = editor.active_document();
|
||||||
|
|
@ -261,15 +257,11 @@ mod test_line_tool {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
(start_input - expected_start).length() < 1.,
|
(start_input - expected_start).length() < 1.,
|
||||||
"Start point should match expected document coordinates. Got {:?}, expected {:?}",
|
"Start point should match expected document coordinates. Got {start_input:?}, expected {expected_start:?}"
|
||||||
start_input,
|
|
||||||
expected_start
|
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
(end_input - expected_end).length() < 1.,
|
(end_input - expected_end).length() < 1.,
|
||||||
"End point should match expected document coordinates. Got {:?}, expected {:?}",
|
"End point should match expected document coordinates. Got {end_input:?}, expected {expected_end:?}"
|
||||||
end_input,
|
|
||||||
expected_end
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
panic!("Line was not created successfully with transformed viewport");
|
panic!("Line was not created successfully with transformed viewport");
|
||||||
|
|
@ -292,8 +284,8 @@ mod test_line_tool {
|
||||||
(updated_start, updated_end) => {
|
(updated_start, updated_end) => {
|
||||||
let updated_line_vec = updated_end - updated_start;
|
let updated_line_vec = updated_end - updated_start;
|
||||||
let updated_angle = updated_line_vec.angle_to(DVec2::X);
|
let updated_angle = updated_line_vec.angle_to(DVec2::X);
|
||||||
print!("{:?}", original_angle);
|
print!("{original_angle:?}");
|
||||||
print!("{:?}", updated_angle);
|
print!("{updated_angle:?}");
|
||||||
assert!(
|
assert!(
|
||||||
line_vec.normalize().dot(updated_line_vec.normalize()).abs() - 1. < 1e-6,
|
line_vec.normalize().dot(updated_line_vec.normalize()).abs() - 1. < 1e-6,
|
||||||
"Line angle should be locked when Ctrl is kept pressed"
|
"Line angle should be locked when Ctrl is kept pressed"
|
||||||
|
|
|
||||||
|
|
@ -569,7 +569,7 @@ mod test_artboard {
|
||||||
async fn get_artboards(editor: &mut EditorTestUtils) -> Table<graphene_std::Artboard> {
|
async fn get_artboards(editor: &mut EditorTestUtils) -> Table<graphene_std::Artboard> {
|
||||||
let instrumented = match editor.eval_graph().await {
|
let instrumented = match editor.eval_graph().await {
|
||||||
Ok(instrumented) => instrumented,
|
Ok(instrumented) => instrumented,
|
||||||
Err(e) => panic!("Failed to evaluate graph: {}", e),
|
Err(e) => panic!("Failed to evaluate graph: {e}"),
|
||||||
};
|
};
|
||||||
instrumented
|
instrumented
|
||||||
.grab_all_input::<graphene_std::graphic::extend::NewInput<graphene_std::Artboard>>(&editor.runtime)
|
.grab_all_input::<graphene_std::graphic::extend::NewInput<graphene_std::Artboard>>(&editor.runtime)
|
||||||
|
|
|
||||||
|
|
@ -416,7 +416,10 @@ mod test_freehand {
|
||||||
fn verify_path_points(vector_and_transform_list: &[(Vector, DAffine2)], expected_captured_points: &[DVec2], tolerance: f64) -> Result<(), String> {
|
fn verify_path_points(vector_and_transform_list: &[(Vector, DAffine2)], expected_captured_points: &[DVec2], tolerance: f64) -> Result<(), String> {
|
||||||
assert_eq!(vector_and_transform_list.len(), 1, "There should be one row of Vector geometry");
|
assert_eq!(vector_and_transform_list.len(), 1, "There should be one row of Vector geometry");
|
||||||
|
|
||||||
let (vector, transform) = vector_and_transform_list.iter().find(|(data, _)| data.point_domain.ids().len() > 0).ok_or("Could not find path data")?;
|
let (vector, transform) = vector_and_transform_list
|
||||||
|
.iter()
|
||||||
|
.find(|(data, _)| !data.point_domain.ids().is_empty())
|
||||||
|
.ok_or("Could not find path data")?;
|
||||||
|
|
||||||
let point_count = vector.point_domain.ids().len();
|
let point_count = vector.point_domain.ids().len();
|
||||||
let segment_count = vector.segment_domain.ids().len();
|
let segment_count = vector.segment_domain.ids().len();
|
||||||
|
|
@ -424,7 +427,7 @@ mod test_freehand {
|
||||||
let actual_positions: Vec<DVec2> = vector.point_domain.positions().iter().map(|&position| transform.transform_point2(position)).collect();
|
let actual_positions: Vec<DVec2> = vector.point_domain.positions().iter().map(|&position| transform.transform_point2(position)).collect();
|
||||||
|
|
||||||
if segment_count != point_count - 1 {
|
if segment_count != point_count - 1 {
|
||||||
return Err(format!("Expected segments to be one less than points, got {} segments for {} points", segment_count, point_count));
|
return Err(format!("Expected segments to be one less than points, got {segment_count} segments for {point_count} points"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if point_count != expected_captured_points.len() {
|
if point_count != expected_captured_points.len() {
|
||||||
|
|
@ -434,7 +437,7 @@ mod test_freehand {
|
||||||
for (i, (&expected, &actual)) in expected_captured_points.iter().zip(actual_positions.iter()).enumerate() {
|
for (i, (&expected, &actual)) in expected_captured_points.iter().zip(actual_positions.iter()).enumerate() {
|
||||||
let distance = (expected - actual).length();
|
let distance = (expected - actual).length();
|
||||||
if distance >= tolerance {
|
if distance >= tolerance {
|
||||||
return Err(format!("Point {} position mismatch: expected {:?}, got {:?} (distance: {})", i, expected, actual, distance));
|
return Err(format!("Point {i} position mismatch: expected {expected:?}, got {actual:?} (distance: {distance})"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -508,7 +511,7 @@ mod test_freehand {
|
||||||
let initial_point_count = initial_vector.point_domain.ids().len();
|
let initial_point_count = initial_vector.point_domain.ids().len();
|
||||||
let initial_segment_count = initial_vector.segment_domain.ids().len();
|
let initial_segment_count = initial_vector.segment_domain.ids().len();
|
||||||
|
|
||||||
assert!(initial_point_count >= 2, "Expected at least 2 points in initial path, found {}", initial_point_count);
|
assert!(initial_point_count >= 2, "Expected at least 2 points in initial path, found {initial_point_count}");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
initial_segment_count,
|
initial_segment_count,
|
||||||
initial_point_count - 1,
|
initial_point_count - 1,
|
||||||
|
|
@ -569,17 +572,13 @@ mod test_freehand {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
extended_point_count > initial_point_count,
|
extended_point_count > initial_point_count,
|
||||||
"Expected more points after extension, initial: {}, after extension: {}",
|
"Expected more points after extension, initial: {initial_point_count}, after extension: {extended_point_count}"
|
||||||
initial_point_count,
|
|
||||||
extended_point_count
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
extended_segment_count,
|
extended_segment_count,
|
||||||
extended_point_count - 1,
|
extended_point_count - 1,
|
||||||
"Expected segments to be one less than points, points: {}, segments: {}",
|
"Expected segments to be one less than points, points: {extended_point_count}, segments: {extended_segment_count}"
|
||||||
extended_point_count,
|
|
||||||
extended_segment_count
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let layer_count = {
|
let layer_count = {
|
||||||
|
|
@ -627,8 +626,8 @@ mod test_freehand {
|
||||||
|
|
||||||
let existing_layer_id = {
|
let existing_layer_id = {
|
||||||
let document = editor.active_document();
|
let document = editor.active_document();
|
||||||
let layer = document.metadata().all_layers().next().unwrap();
|
|
||||||
layer
|
document.metadata().all_layers().next().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
editor
|
editor
|
||||||
|
|
@ -685,9 +684,7 @@ mod test_freehand {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
final_point_count > initial_point_count,
|
final_point_count > initial_point_count,
|
||||||
"Expected more points after appending to layer, initial: {}, after append: {}",
|
"Expected more points after appending to layer, initial: {initial_point_count}, after append: {final_point_count}"
|
||||||
initial_point_count,
|
|
||||||
final_point_count
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let expected_new_points = second_path_points.len();
|
let expected_new_points = second_path_points.len();
|
||||||
|
|
|
||||||
|
|
@ -552,7 +552,7 @@ mod test_gradient {
|
||||||
async fn get_fills(editor: &mut EditorTestUtils) -> Vec<(Fill, DAffine2)> {
|
async fn get_fills(editor: &mut EditorTestUtils) -> Vec<(Fill, DAffine2)> {
|
||||||
let instrumented = match editor.eval_graph().await {
|
let instrumented = match editor.eval_graph().await {
|
||||||
Ok(instrumented) => instrumented,
|
Ok(instrumented) => instrumented,
|
||||||
Err(e) => panic!("Failed to evaluate graph: {}", e),
|
Err(e) => panic!("Failed to evaluate graph: {e}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let document = editor.active_document();
|
let document = editor.active_document();
|
||||||
|
|
@ -573,7 +573,7 @@ mod test_gradient {
|
||||||
let (fill, transform) = fills.first().unwrap();
|
let (fill, transform) = fills.first().unwrap();
|
||||||
let gradient = fill.as_gradient().expect("Expected gradient fill type");
|
let gradient = fill.as_gradient().expect("Expected gradient fill type");
|
||||||
|
|
||||||
(gradient.clone(), transform.clone())
|
(gradient.clone(), *transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_stops_at_positions(actual_positions: &[f64], expected_positions: &[f64], tolerance: f64) {
|
fn assert_stops_at_positions(actual_positions: &[f64], expected_positions: &[f64], tolerance: f64) {
|
||||||
|
|
@ -586,7 +586,7 @@ mod test_gradient {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (i, (actual, expected)) in actual_positions.iter().zip(expected_positions.iter()).enumerate() {
|
for (i, (actual, expected)) in actual_positions.iter().zip(expected_positions.iter()).enumerate() {
|
||||||
assert!((actual - expected).abs() < tolerance, "Stop {}: Expected position near {}, got {}", i, expected, actual);
|
assert!((actual - expected).abs() < tolerance, "Stop {i}: Expected position near {expected}, got {actual}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -713,8 +713,7 @@ mod test_gradient {
|
||||||
let positions: Vec<f64> = updated_gradient.stops.iter().map(|(pos, _)| *pos).collect();
|
let positions: Vec<f64> = updated_gradient.stops.iter().map(|(pos, _)| *pos).collect();
|
||||||
assert!(
|
assert!(
|
||||||
positions.iter().any(|pos| (pos - 0.5).abs() < 0.1),
|
positions.iter().any(|pos| (pos - 0.5).abs() < 0.1),
|
||||||
"Expected to find a stop near position 0.5, but found: {:?}",
|
"Expected to find a stop near position 0.5, but found: {positions:?}"
|
||||||
positions
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -782,7 +781,7 @@ mod test_gradient {
|
||||||
|
|
||||||
// Verify the end point has been updated to the new position
|
// Verify the end point has been updated to the new position
|
||||||
let updated_end = transform.transform_point2(updated_gradient.end);
|
let updated_end = transform.transform_point2(updated_gradient.end);
|
||||||
assert!(updated_end.abs_diff_eq(DVec2::new(100., 50.), 1e-10), "Expected end point at (100, 50), got {:?}", updated_end);
|
assert!(updated_end.abs_diff_eq(DVec2::new(100., 50.), 1e-10), "Expected end point at (100, 50), got {updated_end:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
|
||||||
|
|
@ -202,11 +202,11 @@ impl SelectTool {
|
||||||
let list = <BooleanOperation as graphene_std::choice_type::ChoiceTypeStatic>::list();
|
let list = <BooleanOperation as graphene_std::choice_type::ChoiceTypeStatic>::list();
|
||||||
list.iter().flat_map(|i| i.iter()).map(move |(operation, info)| {
|
list.iter().flat_map(|i| i.iter()).map(move |(operation, info)| {
|
||||||
let mut tooltip = info.label.to_string();
|
let mut tooltip = info.label.to_string();
|
||||||
if let Some(doc) = info.docstring.as_deref() {
|
if let Some(doc) = info.docstring {
|
||||||
tooltip.push_str("\n\n");
|
tooltip.push_str("\n\n");
|
||||||
tooltip.push_str(doc);
|
tooltip.push_str(doc);
|
||||||
}
|
}
|
||||||
IconButton::new(info.icon.as_deref().unwrap(), 24)
|
IconButton::new(info.icon.unwrap(), 24)
|
||||||
.tooltip(tooltip)
|
.tooltip(tooltip)
|
||||||
.disabled(selected_count == 0)
|
.disabled(selected_count == 0)
|
||||||
.on_update(move |_| {
|
.on_update(move |_| {
|
||||||
|
|
@ -852,7 +852,13 @@ impl Fsm for SelectToolFsmState {
|
||||||
if let Some(pivot) = pivot {
|
if let Some(pivot) = pivot {
|
||||||
let offset = tool_data
|
let offset = tool_data
|
||||||
.pivot_gizmo_start
|
.pivot_gizmo_start
|
||||||
.map(|offset| tool_data.pivot_gizmo.pivot_disconnected().then_some(tool_data.drag_current - offset).unwrap_or_default())
|
.map(|offset| {
|
||||||
|
if tool_data.pivot_gizmo.pivot_disconnected() {
|
||||||
|
tool_data.drag_current - offset
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let shift = tool_data.pivot_gizmo_shift.unwrap_or_default();
|
let shift = tool_data.pivot_gizmo_shift.unwrap_or_default();
|
||||||
overlay_context.pivot(pivot + offset + shift, angle);
|
overlay_context.pivot(pivot + offset + shift, angle);
|
||||||
|
|
@ -895,7 +901,7 @@ impl Fsm for SelectToolFsmState {
|
||||||
color
|
color
|
||||||
} else {
|
} else {
|
||||||
let color_string = &graphene_std::Color::from_rgb_str(color.strip_prefix('#').unwrap()).unwrap().with_alpha(0.25).to_rgba_hex_srgb();
|
let color_string = &graphene_std::Color::from_rgb_str(color.strip_prefix('#').unwrap()).unwrap().with_alpha(0.25).to_rgba_hex_srgb();
|
||||||
&format!("#{}", color_string)
|
&format!("#{color_string}")
|
||||||
};
|
};
|
||||||
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);
|
||||||
|
|
@ -1455,7 +1461,11 @@ impl Fsm for SelectToolFsmState {
|
||||||
tool_data.select_single_layer = None;
|
tool_data.select_single_layer = None;
|
||||||
|
|
||||||
if let Some(start) = tool_data.pivot_gizmo_start {
|
if let Some(start) = tool_data.pivot_gizmo_start {
|
||||||
let offset = tool_data.pivot_gizmo.pivot_disconnected().then_some(tool_data.drag_current - start).unwrap_or_default();
|
let offset = if tool_data.pivot_gizmo.pivot_disconnected() {
|
||||||
|
tool_data.drag_current - start
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
};
|
||||||
if let Some(v) = tool_data.pivot_gizmo.pivot.pivot.as_mut() {
|
if let Some(v) = tool_data.pivot_gizmo.pivot.pivot.as_mut() {
|
||||||
*v += offset;
|
*v += offset;
|
||||||
}
|
}
|
||||||
|
|
@ -1649,7 +1659,9 @@ impl Fsm for SelectToolFsmState {
|
||||||
}
|
}
|
||||||
(_, SelectToolMessage::PivotShift { offset, flush }) => {
|
(_, SelectToolMessage::PivotShift { offset, flush }) => {
|
||||||
if flush {
|
if flush {
|
||||||
tool_data.pivot_gizmo.pivot.pivot.as_mut().map(|v| *v += tool_data.pivot_gizmo_shift.take().unwrap_or_default());
|
if let Some(v) = tool_data.pivot_gizmo.pivot.pivot.as_mut() {
|
||||||
|
*v += tool_data.pivot_gizmo_shift.take().unwrap_or_default();
|
||||||
|
}
|
||||||
let pivot_gizmo = tool_data.pivot_gizmo();
|
let pivot_gizmo = tool_data.pivot_gizmo();
|
||||||
responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo });
|
responses.add(TransformLayerMessage::SetPivotGizmo { pivot_gizmo });
|
||||||
return self;
|
return self;
|
||||||
|
|
|
||||||
|
|
@ -606,11 +606,7 @@ mod test_spline_tool {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
distance < epsilon,
|
distance < epsilon,
|
||||||
"Point {} position mismatch: expected {:?}, got {:?} (distance: {})",
|
"Point {i} position mismatch: expected {expected_point:?}, got {actual_point:?} (distance: {distance})"
|
||||||
i,
|
|
||||||
expected_point,
|
|
||||||
actual_point,
|
|
||||||
distance
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -644,8 +640,8 @@ mod test_spline_tool {
|
||||||
// Verify initial spline has correct number of points and segments
|
// Verify initial spline has correct number of points and segments
|
||||||
let initial_point_count = first_vector.point_domain.ids().len();
|
let initial_point_count = first_vector.point_domain.ids().len();
|
||||||
let initial_segment_count = first_vector.segment_domain.ids().len();
|
let initial_segment_count = first_vector.segment_domain.ids().len();
|
||||||
assert_eq!(initial_point_count, 3, "Expected 3 points in initial spline, found {}", initial_point_count);
|
assert_eq!(initial_point_count, 3, "Expected 3 points in initial spline, found {initial_point_count}");
|
||||||
assert_eq!(initial_segment_count, 2, "Expected 2 segments in initial spline, found {}", initial_segment_count);
|
assert_eq!(initial_segment_count, 2, "Expected 2 segments in initial spline, found {initial_segment_count}");
|
||||||
|
|
||||||
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
|
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
|
||||||
|
|
||||||
|
|
@ -679,8 +675,8 @@ mod test_spline_tool {
|
||||||
let extended_point_count = extended_vector.point_domain.ids().len();
|
let extended_point_count = extended_vector.point_domain.ids().len();
|
||||||
let extended_segment_count = extended_vector.segment_domain.ids().len();
|
let extended_segment_count = extended_vector.segment_domain.ids().len();
|
||||||
|
|
||||||
assert_eq!(extended_point_count, 5, "Expected 5 points in extended spline, found {}", extended_point_count);
|
assert_eq!(extended_point_count, 5, "Expected 5 points in extended spline, found {extended_point_count}");
|
||||||
assert_eq!(extended_segment_count, 4, "Expected 4 segments in extended spline, found {}", extended_segment_count);
|
assert_eq!(extended_segment_count, 4, "Expected 4 segments in extended spline, found {extended_segment_count}");
|
||||||
|
|
||||||
// Verify the spline node is still the same
|
// Verify the spline node is still the same
|
||||||
let extended_spline_node = find_spline(document, spline_layer).expect("Spline node not found after extension");
|
let extended_spline_node = find_spline(document, spline_layer).expect("Spline node not found after extension");
|
||||||
|
|
@ -715,7 +711,7 @@ mod test_spline_tool {
|
||||||
|
|
||||||
// Evaluate the graph to ensure everything is processed
|
// Evaluate the graph to ensure everything is processed
|
||||||
if let Err(e) = editor.eval_graph().await {
|
if let Err(e) = editor.eval_graph().await {
|
||||||
panic!("Graph evaluation failed: {}", e);
|
panic!("Graph evaluation failed: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the layer and vector data
|
// Get the layer and vector data
|
||||||
|
|
@ -755,7 +751,7 @@ mod test_spline_tool {
|
||||||
|
|
||||||
// Evaluating the graph to ensure everything is processed
|
// Evaluating the graph to ensure everything is processed
|
||||||
if let Err(e) = editor.eval_graph().await {
|
if let Err(e) = editor.eval_graph().await {
|
||||||
panic!("Graph evaluation failed: {}", e);
|
panic!("Graph evaluation failed: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the layer and vector data
|
// Get the layer and vector data
|
||||||
|
|
@ -793,7 +789,7 @@ mod test_spline_tool {
|
||||||
|
|
||||||
// Evaluating the graph to ensure everything is processed
|
// Evaluating the graph to ensure everything is processed
|
||||||
if let Err(e) = editor.eval_graph().await {
|
if let Err(e) = editor.eval_graph().await {
|
||||||
panic!("Graph evaluation failed: {}", e);
|
panic!("Graph evaluation failed: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the layer and vector data
|
// Get the layer and vector data
|
||||||
|
|
@ -832,7 +828,7 @@ mod test_spline_tool {
|
||||||
|
|
||||||
editor.handle_message(SplineToolMessage::Confirm).await;
|
editor.handle_message(SplineToolMessage::Confirm).await;
|
||||||
if let Err(e) = editor.eval_graph().await {
|
if let Err(e) = editor.eval_graph().await {
|
||||||
panic!("Graph evaluation failed: {}", e);
|
panic!("Graph evaluation failed: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the layer and vector data
|
// Get the layer and vector data
|
||||||
|
|
@ -889,8 +885,8 @@ mod test_spline_tool {
|
||||||
let point_count = vector.point_domain.ids().len();
|
let point_count = vector.point_domain.ids().len();
|
||||||
let segment_count = vector.segment_domain.ids().len();
|
let segment_count = vector.segment_domain.ids().len();
|
||||||
|
|
||||||
assert_eq!(point_count, 3, "Expected 3 points in the spline, found {}", point_count);
|
assert_eq!(point_count, 3, "Expected 3 points in the spline, found {point_count}");
|
||||||
assert_eq!(segment_count, 2, "Expected 2 segments in the spline, found {}", segment_count);
|
assert_eq!(segment_count, 2, "Expected 2 segments in the spline, found {segment_count}");
|
||||||
|
|
||||||
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
|
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,7 +189,7 @@ impl MessageHandler<TransformLayerMessage, TransformLayerMessageContext<'_>> for
|
||||||
|
|
||||||
let format_rounded = |value: f64, precision: usize| {
|
let format_rounded = |value: f64, precision: usize| {
|
||||||
if self.typing.digits.is_empty() || !self.transform_operation.can_begin_typing() {
|
if self.typing.digits.is_empty() || !self.transform_operation.can_begin_typing() {
|
||||||
format!("{:.*}", precision, value).trim_end_matches('0').trim_end_matches('.').to_string()
|
format!("{value:.precision$}").trim_end_matches('0').trim_end_matches('.').to_string()
|
||||||
} else {
|
} else {
|
||||||
self.typing.string.clone()
|
self.typing.string.clone()
|
||||||
}
|
}
|
||||||
|
|
@ -892,7 +892,7 @@ mod test_transform_layer {
|
||||||
let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();
|
let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();
|
||||||
|
|
||||||
let translation_diff = (final_transform.translation - original_transform.translation).length();
|
let translation_diff = (final_transform.translation - original_transform.translation).length();
|
||||||
assert!(translation_diff > 10., "Transform should have changed after applying transformation. Diff: {}", translation_diff);
|
assert!(translation_diff > 10., "Transform should have changed after applying transformation. Diff: {translation_diff}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -927,9 +927,7 @@ mod test_transform_layer {
|
||||||
// Verify transform is either restored to original OR reset to identity
|
// Verify transform is either restored to original OR reset to identity
|
||||||
assert!(
|
assert!(
|
||||||
(final_translation - original_translation).length() < 5. || final_translation.length() < 0.001,
|
(final_translation - original_translation).length() < 5. || final_translation.length() < 0.001,
|
||||||
"Transform neither restored to original nor reset to identity. Original: {:?}, Final: {:?}",
|
"Transform neither restored to original nor reset to identity. Original: {original_translation:?}, Final: {final_translation:?}"
|
||||||
original_translation,
|
|
||||||
final_translation
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -958,11 +956,11 @@ mod test_transform_layer {
|
||||||
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
|
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
|
||||||
|
|
||||||
let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();
|
let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();
|
||||||
println!("Final transform: {:?}", final_transform);
|
println!("Final transform: {final_transform:?}");
|
||||||
|
|
||||||
// Check matrix components have changed (rotation affects matrix2)
|
// Check matrix components have changed (rotation affects matrix2)
|
||||||
let matrix_diff = (final_transform.matrix2.x_axis - original_transform.matrix2.x_axis).length();
|
let matrix_diff = (final_transform.matrix2.x_axis - original_transform.matrix2.x_axis).length();
|
||||||
assert!(matrix_diff > 0.1, "Rotation should have changed the transform matrix. Diff: {}", matrix_diff);
|
assert!(matrix_diff > 0.1, "Rotation should have changed the transform matrix. Diff: {matrix_diff}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -984,7 +982,7 @@ mod test_transform_layer {
|
||||||
assert!(!after_cancel.translation.y.is_nan(), "Transform is NaN after cancel");
|
assert!(!after_cancel.translation.y.is_nan(), "Transform is NaN after cancel");
|
||||||
|
|
||||||
let translation_diff = (after_cancel.translation - original_transform.translation).length();
|
let translation_diff = (after_cancel.translation - original_transform.translation).length();
|
||||||
assert!(translation_diff < 1., "Translation component changed too much: {}", translation_diff);
|
assert!(translation_diff < 1., "Translation component changed too much: {translation_diff}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -1019,9 +1017,7 @@ mod test_transform_layer {
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
scale_diff_x > 0.1 || scale_diff_y > 0.1,
|
scale_diff_x > 0.1 || scale_diff_y > 0.1,
|
||||||
"Scaling should have changed the transform matrix. Diffs: x={}, y={}",
|
"Scaling should have changed the transform matrix. Diffs: x={scale_diff_x}, y={scale_diff_y}"
|
||||||
scale_diff_x,
|
|
||||||
scale_diff_y
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1050,7 +1046,7 @@ mod test_transform_layer {
|
||||||
|
|
||||||
// Also check translation component is similar
|
// Also check translation component is similar
|
||||||
let translation_diff = (after_cancel.translation - original_transform.translation).length();
|
let translation_diff = (after_cancel.translation - original_transform.translation).length();
|
||||||
assert!(translation_diff < 1., "Translation component changed too much: {}", translation_diff);
|
assert!(translation_diff < 1., "Translation component changed too much: {translation_diff}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -1077,9 +1073,7 @@ mod test_transform_layer {
|
||||||
let actual_translation = after_grab_transform.translation - original_transform.translation;
|
let actual_translation = after_grab_transform.translation - original_transform.translation;
|
||||||
assert!(
|
assert!(
|
||||||
(actual_translation - expected_translation).length() < 1e-5,
|
(actual_translation - expected_translation).length() < 1e-5,
|
||||||
"Expected translation of {:?}, got {:?}",
|
"Expected translation of {expected_translation:?}, got {actual_translation:?}"
|
||||||
expected_translation,
|
|
||||||
actual_translation
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 2. Chain to rotation - from current position to create ~45 degree rotation
|
// 2. Chain to rotation - from current position to create ~45 degree rotation
|
||||||
|
|
@ -1115,9 +1109,7 @@ mod test_transform_layer {
|
||||||
let after_scale_det = after_scale_transform.matrix2.determinant();
|
let after_scale_det = after_scale_transform.matrix2.determinant();
|
||||||
assert!(
|
assert!(
|
||||||
after_scale_det >= 2. * before_scale_det,
|
after_scale_det >= 2. * before_scale_det,
|
||||||
"Scale should increase the determinant of the matrix (before: {}, after: {})",
|
"Scale should increase the determinant of the matrix (before: {before_scale_det}, after: {after_scale_det})"
|
||||||
before_scale_det,
|
|
||||||
after_scale_det
|
|
||||||
);
|
);
|
||||||
|
|
||||||
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
|
editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
|
||||||
|
|
@ -1149,8 +1141,8 @@ mod test_transform_layer {
|
||||||
let scale_x = final_transform.matrix2.x_axis.length() / original_transform.matrix2.x_axis.length();
|
let scale_x = final_transform.matrix2.x_axis.length() / original_transform.matrix2.x_axis.length();
|
||||||
let scale_y = final_transform.matrix2.y_axis.length() / original_transform.matrix2.y_axis.length();
|
let scale_y = final_transform.matrix2.y_axis.length() / original_transform.matrix2.y_axis.length();
|
||||||
|
|
||||||
assert!((scale_x - 2.).abs() < 0.1, "Expected scale factor X of 2, got: {}", scale_x);
|
assert!((scale_x - 2.).abs() < 0.1, "Expected scale factor X of 2, got: {scale_x}");
|
||||||
assert!((scale_y - 2.).abs() < 0.1, "Expected scale factor Y of 2, got: {}", scale_y);
|
assert!((scale_y - 2.).abs() < 0.1, "Expected scale factor Y of 2, got: {scale_y}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -1175,8 +1167,8 @@ mod test_transform_layer {
|
||||||
let scale_x = final_transform.matrix2.x_axis.length() / original_transform.matrix2.x_axis.length();
|
let scale_x = final_transform.matrix2.x_axis.length() / original_transform.matrix2.x_axis.length();
|
||||||
let scale_y = final_transform.matrix2.y_axis.length() / original_transform.matrix2.y_axis.length();
|
let scale_y = final_transform.matrix2.y_axis.length() / original_transform.matrix2.y_axis.length();
|
||||||
|
|
||||||
assert!((scale_x - 2.).abs() < 0.1, "Expected scale factor X of 2, got: {}", scale_x);
|
assert!((scale_x - 2.).abs() < 0.1, "Expected scale factor X of 2, got: {scale_x}");
|
||||||
assert!((scale_y - 2.).abs() < 0.1, "Expected scale factor Y of 2, got: {}", scale_y);
|
assert!((scale_y - 2.).abs() < 0.1, "Expected scale factor Y of 2, got: {scale_y}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -1191,11 +1183,7 @@ mod test_transform_layer {
|
||||||
|
|
||||||
// Rotate the document view (45 degrees)
|
// Rotate the document view (45 degrees)
|
||||||
editor.handle_message(NavigationMessage::BeginCanvasTilt { was_dispatched_from_menu: false }).await;
|
editor.handle_message(NavigationMessage::BeginCanvasTilt { was_dispatched_from_menu: false }).await;
|
||||||
editor
|
editor.handle_message(NavigationMessage::CanvasTiltSet { angle_radians: 45_f64.to_radians() }).await;
|
||||||
.handle_message(NavigationMessage::CanvasTiltSet {
|
|
||||||
angle_radians: (45. as f64).to_radians(),
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
editor.handle_message(TransformLayerMessage::BeginRotate).await;
|
editor.handle_message(TransformLayerMessage::BeginRotate).await;
|
||||||
|
|
||||||
editor.handle_message(TransformLayerMessage::TypeDigit { digit: 9 }).await;
|
editor.handle_message(TransformLayerMessage::TypeDigit { digit: 9 }).await;
|
||||||
|
|
@ -1210,7 +1198,7 @@ mod test_transform_layer {
|
||||||
|
|
||||||
// Normalize angle between 0 and 360
|
// Normalize angle between 0 and 360
|
||||||
let angle_change = ((angle_change % 360.) + 360.) % 360.;
|
let angle_change = ((angle_change % 360.) + 360.) % 360.;
|
||||||
assert!((angle_change - 90.).abs() < 0.1, "Expected rotation of 90 degrees, got: {}", angle_change);
|
assert!((angle_change - 90.).abs() < 0.1, "Expected rotation of 90 degrees, got: {angle_change}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -1265,8 +1253,8 @@ mod test_transform_layer {
|
||||||
// Verify scale is near zero.
|
// Verify scale is near zero.
|
||||||
let scale_x = near_zero_transform.matrix2.x_axis.length();
|
let scale_x = near_zero_transform.matrix2.x_axis.length();
|
||||||
let scale_y = near_zero_transform.matrix2.y_axis.length();
|
let scale_y = near_zero_transform.matrix2.y_axis.length();
|
||||||
assert!(scale_x < 0.001, "Scale factor X should be near zero, got: {}", scale_x);
|
assert!(scale_x < 0.001, "Scale factor X should be near zero, got: {scale_x}");
|
||||||
assert!(scale_y < 0.001, "Scale factor Y should be near zero, got: {}", scale_y);
|
assert!(scale_y < 0.001, "Scale factor Y should be near zero, got: {scale_y}");
|
||||||
assert!(scale_x > 0., "Scale factor X should not be exactly zero");
|
assert!(scale_x > 0., "Scale factor X should not be exactly zero");
|
||||||
assert!(scale_y > 0., "Scale factor Y should not be exactly zero");
|
assert!(scale_y > 0., "Scale factor Y should not be exactly zero");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,7 @@ pub struct InspectResult {
|
||||||
|
|
||||||
impl InspectResult {
|
impl InspectResult {
|
||||||
pub fn take_data(&mut self) -> Option<Arc<dyn std::any::Any + Send + Sync + 'static>> {
|
pub fn take_data(&mut self) -> Option<Arc<dyn std::any::Any + Send + Sync + 'static>> {
|
||||||
return self.introspected_data.clone();
|
self.introspected_data.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ pub fn system_desc_derive(input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_lifetimes(generics: &syn::Generics, replacement: &str) -> Vec<proc_macro2::TokenStream> {
|
fn replace_lifetimes(generics: &syn::Generics, replacement: &str) -> Vec<proc_macro2::TokenStream> {
|
||||||
let params = generics
|
generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.map(|param| {
|
.map(|param| {
|
||||||
|
|
@ -72,6 +72,5 @@ fn replace_lifetimes(generics: &syn::Generics, replacement: &str) -> Vec<proc_ma
|
||||||
};
|
};
|
||||||
quote! {#param}
|
quote! {#param}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>()
|
||||||
params
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ fn parse_lit(mut pairs: Pairs<Rule>) -> Result<(Literal, Unit), ParseError> {
|
||||||
let unit_pairs = unit_pair.into_inner(); // Get the inner pairs for the unit
|
let unit_pairs = unit_pair.into_inner(); // Get the inner pairs for the unit
|
||||||
let (unit, scale) = parse_unit(unit_pairs)?;
|
let (unit, scale) = parse_unit(unit_pairs)?;
|
||||||
|
|
||||||
println!("found unit: {:?}", unit);
|
println!("found unit: {unit:?}");
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
match literal {
|
match literal {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ pub fn commands_from_path_data(d: &str) -> Result<Vec<PathCommand>, BooleanError
|
||||||
*i += cap[0].len();
|
*i += cap[0].len();
|
||||||
&cap[1] == "1"
|
&cap[1] == "1"
|
||||||
} else {
|
} else {
|
||||||
panic!("Invalid path data. Expected a flag at index {}", i);
|
panic!("Invalid path data. Expected a flag at index {i}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -128,8 +128,8 @@ pub fn path_to_path_data(path: &Path, eps: f64) -> String {
|
||||||
path_to_commands(path.iter(), eps)
|
path_to_commands(path.iter(), eps)
|
||||||
.map(|cmd| match cmd {
|
.map(|cmd| match cmd {
|
||||||
PathCommand::Absolute(abs_cmd) => match abs_cmd {
|
PathCommand::Absolute(abs_cmd) => match abs_cmd {
|
||||||
AbsolutePathCommand::H(dx) => format!("H {:.12}", dx),
|
AbsolutePathCommand::H(dx) => format!("H {dx:.12}"),
|
||||||
AbsolutePathCommand::V(dy) => format!("V {:.12}", dy),
|
AbsolutePathCommand::V(dy) => format!("V {dy:.12}"),
|
||||||
AbsolutePathCommand::M(p) => format!("M {:.12},{:.12}", p.x, p.y),
|
AbsolutePathCommand::M(p) => format!("M {:.12},{:.12}", p.x, p.y),
|
||||||
AbsolutePathCommand::L(p) => format!("L {:.12},{:.12}", p.x, p.y),
|
AbsolutePathCommand::L(p) => format!("L {:.12},{:.12}", p.x, p.y),
|
||||||
AbsolutePathCommand::C(p1, p2, p3) => format!("C {:.12},{:.12} {:.12},{:.12} {:.12},{:.12}", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y),
|
AbsolutePathCommand::C(p1, p2, p3) => format!("C {:.12},{:.12} {:.12},{:.12} {:.12},{:.12}", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y),
|
||||||
|
|
@ -146,18 +146,18 @@ pub fn path_to_path_data(path: &Path, eps: f64) -> String {
|
||||||
AbsolutePathCommand::Z => "Z".to_string(),
|
AbsolutePathCommand::Z => "Z".to_string(),
|
||||||
},
|
},
|
||||||
PathCommand::Relative(rel_cmd) => match rel_cmd {
|
PathCommand::Relative(rel_cmd) => match rel_cmd {
|
||||||
RelativePathCommand::M(dx, dy) => format!("m {:.12},{:.12}", dx, dy),
|
RelativePathCommand::M(dx, dy) => format!("m {dx:.12},{dy:.12}"),
|
||||||
RelativePathCommand::L(dx, dy) => format!("l {:.12},{:.12}", dx, dy),
|
RelativePathCommand::L(dx, dy) => format!("l {dx:.12},{dy:.12}"),
|
||||||
RelativePathCommand::H(dx) => format!("h {:.12}", dx),
|
RelativePathCommand::H(dx) => format!("h {dx:.12}"),
|
||||||
RelativePathCommand::V(dy) => format!("v {:.12}", dy),
|
RelativePathCommand::V(dy) => format!("v {dy:.12}"),
|
||||||
RelativePathCommand::C(dx1, dy1, dx2, dy2, dx, dy) => format!("c{:.12},{:.12} {:.12},{:.12} {:.12},{:.12}", dx1, dy1, dx2, dy2, dx, dy),
|
RelativePathCommand::C(dx1, dy1, dx2, dy2, dx, dy) => format!("c{dx1:.12},{dy1:.12} {dx2:.12},{dy2:.12} {dx:.12},{dy:.12}"),
|
||||||
RelativePathCommand::S(dx2, dy2, dx, dy) => {
|
RelativePathCommand::S(dx2, dy2, dx, dy) => {
|
||||||
format!("s {:.12},{:.12} {:.12},{:.12}", dx2, dy2, dx, dy)
|
format!("s {dx2:.12},{dy2:.12} {dx:.12},{dy:.12}")
|
||||||
}
|
}
|
||||||
RelativePathCommand::Q(dx1, dy1, dx, dy) => {
|
RelativePathCommand::Q(dx1, dy1, dx, dy) => {
|
||||||
format!("q {:.12},{:.12} {:.12},{:.12}", dx1, dy1, dx, dy)
|
format!("q {dx1:.12},{dy1:.12} {dx:.12},{dy:.12}")
|
||||||
}
|
}
|
||||||
RelativePathCommand::T(dx, dy) => format!("t{:.12},{:.12}", dx, dy),
|
RelativePathCommand::T(dx, dy) => format!("t{dx:.12},{dy:.12}"),
|
||||||
RelativePathCommand::A(rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, dx, dy) => {
|
RelativePathCommand::A(rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, dx, dy) => {
|
||||||
format!("a {:.12} {:.12} {:.12} {} {} {:.12},{:.12}", rx, ry, x_axis_rotation, large_arc_flag as u8, sweep_flag as u8, dx, dy)
|
format!("a {:.12} {:.12} {:.12} {} {} {:.12},{:.12}", rx, ry, x_axis_rotation, large_arc_flag as u8, sweep_flag as u8, dx, dy)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -551,13 +551,15 @@ fn round_point(point: DVec2) -> I64Vec2 {
|
||||||
(point * ROUNDING_FACTOR).round().as_i64vec2()
|
(point * ROUNDING_FACTOR).round().as_i64vec2()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Edges = SmallVec<[(PathSegment, u8, MajorEdgeKey, MajorEdgeKey); 2]>;
|
||||||
|
|
||||||
fn find_vertices(edges: &[MajorGraphEdgeStage1]) -> MajorGraph {
|
fn find_vertices(edges: &[MajorGraphEdgeStage1]) -> MajorGraph {
|
||||||
let mut graph = MajorGraph {
|
let mut graph = MajorGraph {
|
||||||
edges: SlotMap::with_capacity_and_key(edges.len() * 2),
|
edges: SlotMap::with_capacity_and_key(edges.len() * 2),
|
||||||
vertices: SlotMap::with_capacity_and_key(edges.len()),
|
vertices: SlotMap::with_capacity_and_key(edges.len()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut vertex_pair_id_to_edges: HashMap<_, SmallVec<[(PathSegment, u8, MajorEdgeKey, MajorEdgeKey); 2]>> = new_hash_map(edges.len());
|
let mut vertex_pair_id_to_edges: HashMap<_, Edges> = new_hash_map(edges.len());
|
||||||
let mut vertex_hashmap: HashMap<I64Vec2, MajorVertexKey> = new_hash_map(edges.len() * 2);
|
let mut vertex_hashmap: HashMap<I64Vec2, MajorVertexKey> = new_hash_map(edges.len() * 2);
|
||||||
|
|
||||||
for (seg, parent) in edges {
|
for (seg, parent) in edges {
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,7 @@ struct Logger;
|
||||||
|
|
||||||
impl NodeGraphUpdateSender for Logger {
|
impl NodeGraphUpdateSender for Logger {
|
||||||
fn send(&self, message: NodeGraphUpdateMessage) {
|
fn send(&self, message: NodeGraphUpdateMessage) {
|
||||||
log::warn!("dispatching message with fallback node graph update sender {:?}", message);
|
log::warn!("dispatching message with fallback node graph update sender {message:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
mod color;
|
|
||||||
mod color_traits;
|
mod color_traits;
|
||||||
|
mod color_types;
|
||||||
mod discrete_srgb;
|
mod discrete_srgb;
|
||||||
|
|
||||||
pub use color::*;
|
|
||||||
pub use color_traits::*;
|
pub use color_traits::*;
|
||||||
|
pub use color_types::*;
|
||||||
pub use discrete_srgb::*;
|
pub use discrete_srgb::*;
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,6 @@ mod test {
|
||||||
fn display() {
|
fn display() {
|
||||||
let p = Polynomial::new([1., 2., 0., 3.]);
|
let p = Polynomial::new([1., 2., 0., 3.]);
|
||||||
|
|
||||||
assert_eq!(format!("{:.2}", p), "3.00x^3 + 2.00x + 1.00");
|
assert_eq!(format!("{p:.2}"), "3.00x^3 + 2.00x + 1.00");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ impl<T, CachedNode> MemoNode<T, CachedNode> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::module_inception)]
|
||||||
pub mod memo {
|
pub mod memo {
|
||||||
pub const IDENTIFIER: crate::ProtoNodeIdentifier = crate::ProtoNodeIdentifier::new("graphene_core::memo::MemoNode");
|
pub const IDENTIFIER: crate::ProtoNodeIdentifier = crate::ProtoNodeIdentifier::new("graphene_core::memo::MemoNode");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
|
||||||
GraphicElement::RasterFrame(RasterFrame::ImageFrame(image)) => Self {
|
GraphicElement::RasterFrame(RasterFrame::ImageFrame(image)) => Self {
|
||||||
image: image.iter().next().unwrap().element.clone(),
|
image: image.iter().next().unwrap().element.clone(),
|
||||||
},
|
},
|
||||||
_ => panic!("Expected Image, found {:?}", element),
|
_ => panic!("Expected Image, found {element:?}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -478,9 +478,9 @@ mod test {
|
||||||
};
|
};
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&image).unwrap();
|
let serialized = serde_json::to_string(&image).unwrap();
|
||||||
println!("{}", serialized);
|
println!("{serialized}");
|
||||||
let deserialized: Image<Color> = serde_json::from_str(&serialized).unwrap();
|
let deserialized: Image<Color> = serde_json::from_str(&serialized).unwrap();
|
||||||
println!("{:?}", deserialized);
|
println!("{deserialized:?}");
|
||||||
|
|
||||||
assert_eq!(image, deserialized);
|
assert_eq!(image, deserialized);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,7 @@ where
|
||||||
};
|
};
|
||||||
match dyn_any::downcast(input) {
|
match dyn_any::downcast(input) {
|
||||||
Ok(input) => Box::pin(output(*input)),
|
Ok(input) => Box::pin(output(*input)),
|
||||||
Err(e) => panic!("DynAnyNode Input, {0} in:\n{1}", e, node_name),
|
Err(e) => panic!("DynAnyNode Input, {e} in:\n{node_name}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -367,7 +367,7 @@ impl std::fmt::Debug for Type {
|
||||||
Self::Future(ty) => format!("{ty:?}"),
|
Self::Future(ty) => format!("{ty:?}"),
|
||||||
};
|
};
|
||||||
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
||||||
write!(f, "{}", result)
|
write!(f, "{result}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,6 +380,6 @@ impl std::fmt::Display for Type {
|
||||||
Type::Future(ty) => ty.to_string(),
|
Type::Future(ty) => ty.to_string(),
|
||||||
};
|
};
|
||||||
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
let result = result.replace("Option<Arc<OwnedContextImpl>>", "Context");
|
||||||
write!(f, "{}", result)
|
write!(f, "{result}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,7 @@ impl<'i, T: 'i> Node<'i, ()> for RefCellMutNode<T> {
|
||||||
type Output = RefMut<'i, T>;
|
type Output = RefMut<'i, T>;
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eval(&'i self, _input: ()) -> Self::Output {
|
fn eval(&'i self, _input: ()) -> Self::Output {
|
||||||
let a = self.0.borrow_mut();
|
self.0.borrow_mut()
|
||||||
a
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ pub fn pathseg_find_tvalues_for_x(segment: PathSeg, x: f64) -> impl Iterator<Ite
|
||||||
let b = 2.0 * (p1.x - p0.x);
|
let b = 2.0 * (p1.x - p0.x);
|
||||||
let c = p0.x - x;
|
let c = p0.x - x;
|
||||||
let r = solve_quadratic(c, b, a);
|
let r = solve_quadratic(c, b, a);
|
||||||
[r.get(0).map(|t| *t), r.get(1).map(|t| *t), None]
|
[r.first().copied(), r.get(1).copied(), None]
|
||||||
}
|
}
|
||||||
PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => {
|
PathSeg::Cubic(CubicBez { p0, p1, p2, p3 }) => {
|
||||||
let a = p3.x - 3.0 * p2.x + 3.0 * p1.x - p0.x;
|
let a = p3.x - 3.0 * p2.x + 3.0 * p1.x - p0.x;
|
||||||
|
|
@ -233,7 +233,7 @@ pub fn pathseg_find_tvalues_for_x(segment: PathSeg, x: f64) -> impl Iterator<Ite
|
||||||
let c = 3.0 * (p1.x - p0.x);
|
let c = 3.0 * (p1.x - p0.x);
|
||||||
let d = p0.x - x;
|
let d = p0.x - x;
|
||||||
let r = solve_cubic(d, c, b, a);
|
let r = solve_cubic(d, c, b, a);
|
||||||
[r.get(0).map(|t| *t), r.get(1).map(|t| *t), r.get(2).map(|t| *t)]
|
[r.first().copied(), r.get(1).copied(), r.get(2).copied()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ mod tests {
|
||||||
assert_eq!(bezier.handles, subpath::BezierHandles::Linear);
|
assert_eq!(bezier.handles, subpath::BezierHandles::Linear);
|
||||||
let vector = bezier.start - bezier.end;
|
let vector = bezier.start - bezier.end;
|
||||||
let angle = (vector.angle_to(DVec2::X).to_degrees() + 180.) % 180.;
|
let angle = (vector.angle_to(DVec2::X).to_degrees() + 180.) % 180.;
|
||||||
assert!([90., 150., 40.].into_iter().any(|target| (target - angle).abs() < 1e-10), "unexpected angle of {}", angle)
|
assert!([90., 150., 40.].into_iter().any(|target| (target - angle).abs() < 1e-10), "unexpected angle of {angle}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -343,8 +343,8 @@ fn to_path_segments(path: &mut Vec<path_bool::PathSegment>, subpath: &Subpath<Po
|
||||||
let PathSegPoints { p0, p1, p2, p3 } = pathseg_points(bezier);
|
let PathSegPoints { p0, p1, p2, p3 } = pathseg_points(bezier);
|
||||||
|
|
||||||
let p0 = transform_point(p0);
|
let p0 = transform_point(p0);
|
||||||
let p1 = p1.map(|p1| transform_point(p1));
|
let p1 = p1.map(transform_point);
|
||||||
let p2 = p2.map(|p2| transform_point(p2));
|
let p2 = p2.map(transform_point);
|
||||||
let p3 = transform_point(p3);
|
let p3 = transform_point(p3);
|
||||||
|
|
||||||
if global_start.is_none() {
|
if global_start.is_none() {
|
||||||
|
|
|
||||||
|
|
@ -949,7 +949,7 @@ impl NodeNetwork {
|
||||||
for (nested_node_id, mut nested_node) in inner_network.nodes.into_iter() {
|
for (nested_node_id, mut nested_node) in inner_network.nodes.into_iter() {
|
||||||
for (nested_input_index, nested_input) in nested_node.clone().inputs.iter().enumerate() {
|
for (nested_input_index, nested_input) in nested_node.clone().inputs.iter().enumerate() {
|
||||||
if let NodeInput::Network { import_index, .. } = nested_input {
|
if let NodeInput::Network { import_index, .. } = nested_input {
|
||||||
let parent_input = node.inputs.get(*import_index).unwrap_or_else(|| panic!("Import index {} should always exist", import_index));
|
let parent_input = node.inputs.get(*import_index).unwrap_or_else(|| panic!("Import index {import_index} should always exist"));
|
||||||
match *parent_input {
|
match *parent_input {
|
||||||
// If the input to self is a node, connect the corresponding output of the inner network to it
|
// If the input to self is a node, connect the corresponding output of the inner network to it
|
||||||
NodeInput::Node { node_id, output_index, lambda } => {
|
NodeInput::Node { node_id, output_index, lambda } => {
|
||||||
|
|
|
||||||
|
|
@ -301,13 +301,13 @@ impl TaggedValue {
|
||||||
"MAGENTA" => Color::MAGENTA,
|
"MAGENTA" => Color::MAGENTA,
|
||||||
"TRANSPARENT" => Color::TRANSPARENT,
|
"TRANSPARENT" => Color::TRANSPARENT,
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("Invalid default value color constant: {}", input);
|
log::error!("Invalid default value color constant: {input}");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
log::error!("Invalid default value color: {}", input);
|
log::error!("Invalid default value color: {input}");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -327,13 +327,13 @@ impl TaggedValue {
|
||||||
"BottomCenter" => ReferencePoint::BottomCenter,
|
"BottomCenter" => ReferencePoint::BottomCenter,
|
||||||
"BottomRight" => ReferencePoint::BottomRight,
|
"BottomRight" => ReferencePoint::BottomRight,
|
||||||
_ => {
|
_ => {
|
||||||
log::error!("Invalid ReferencePoint default type variant: {}", input);
|
log::error!("Invalid ReferencePoint default type variant: {input}");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
log::error!("Invalid ReferencePoint default type: {}", input);
|
log::error!("Invalid ReferencePoint default type: {input}");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
let device = application_io.gpu_executor().unwrap().context.device.clone();
|
let device = application_io.gpu_executor().unwrap().context.device.clone();
|
||||||
|
|
||||||
let preferences = EditorPreferences {
|
let preferences = EditorPreferences { use_vello: true };
|
||||||
use_vello: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
let editor_api = Arc::new(WasmEditorApi {
|
let editor_api = Arc::new(WasmEditorApi {
|
||||||
font_cache: FontCache::default(),
|
font_cache: FontCache::default(),
|
||||||
application_io: Some(application_io.into()),
|
application_io: Some(application_io.into()),
|
||||||
|
|
@ -104,7 +101,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
match app.command {
|
match app.command {
|
||||||
Command::Compile { print_proto, .. } => {
|
Command::Compile { print_proto, .. } => {
|
||||||
if print_proto {
|
if print_proto {
|
||||||
println!("{}", proto_graph);
|
println!("{proto_graph}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Run { run_loop, .. } => {
|
Command::Run { run_loop, .. } => {
|
||||||
|
|
@ -120,7 +117,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
loop {
|
loop {
|
||||||
let result = (&executor).execute(render_config).await?;
|
let result = (&executor).execute(render_config).await?;
|
||||||
if !run_loop {
|
if !run_loop {
|
||||||
println!("{:?}", result);
|
println!("{result:?}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(16)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(16)).await;
|
||||||
|
|
|
||||||
|
|
@ -1209,7 +1209,7 @@ impl Render for Table<Raster<CPU>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LAZY_ARC_VEC_ZERO_U8: LazyLock<Arc<Vec<u8>>> = LazyLock::new(|| Arc::new(Vec::new()));
|
static LAZY_ARC_VEC_ZERO_U8: LazyLock<Arc<Vec<u8>>> = LazyLock::new(|| Arc::new(Vec::new()));
|
||||||
|
|
||||||
impl Render for Table<Raster<GPU>> {
|
impl Render for Table<Raster<GPU>> {
|
||||||
fn render_svg(&self, _render: &mut SvgRender, _render_params: &RenderParams) {
|
fn render_svg(&self, _render: &mut SvgRender, _render_params: &RenderParams) {
|
||||||
|
|
|
||||||
|
|
@ -150,8 +150,8 @@ pub enum IntrospectError {
|
||||||
impl std::fmt::Display for IntrospectError {
|
impl std::fmt::Display for IntrospectError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
IntrospectError::PathNotFound(path) => write!(f, "Path not found: {:?}", path),
|
IntrospectError::PathNotFound(path) => write!(f, "Path not found: {path:?}"),
|
||||||
IntrospectError::ProtoNodeNotFound(id) => write!(f, "ProtoNode not found: {:?}", id),
|
IntrospectError::ProtoNodeNotFound(id) => write!(f, "ProtoNode not found: {id:?}"),
|
||||||
IntrospectError::NoData => write!(f, "No data found for this node"),
|
IntrospectError::NoData => write!(f, "No data found for this node"),
|
||||||
IntrospectError::RuntimeNotReady => write!(f, "Node runtime is not ready"),
|
IntrospectError::RuntimeNotReady => write!(f, "Node runtime is not ready"),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
|
||||||
|
|
||||||
let properties = &attributes.properties_string.as_ref().map(|value| quote!(Some(#value))).unwrap_or(quote!(None));
|
let properties = &attributes.properties_string.as_ref().map(|value| quote!(Some(#value))).unwrap_or(quote!(None));
|
||||||
|
|
||||||
let cfg = crate::shader_nodes::modify_cfg(&attributes);
|
let cfg = crate::shader_nodes::modify_cfg(attributes);
|
||||||
let node_input_accessor = generate_node_input_references(parsed, fn_generics, &field_idents, &graphene_core, &identifier, &cfg);
|
let node_input_accessor = generate_node_input_references(parsed, fn_generics, &field_idents, &graphene_core, &identifier, &cfg);
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
/// Underlying implementation for [#struct_name]
|
/// Underlying implementation for [#struct_name]
|
||||||
|
|
@ -323,6 +323,7 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
|
||||||
|
|
||||||
#cfg
|
#cfg
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[allow(clippy::module_inception)]
|
||||||
mod #mod_name {
|
mod #mod_name {
|
||||||
use super::*;
|
use super::*;
|
||||||
use #graphene_core as gcore;
|
use #graphene_core as gcore;
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ fn derive_enum(enum_attributes: &[Attribute], name: Ident, input: syn::DataEnum)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
syn::Error::new(
|
syn::Error::new(
|
||||||
Span::call_site(),
|
Span::call_site(),
|
||||||
format!("Failed to find location of 'graphene_core' or 'graphene-core-shaders'. Make sure it is imported as a dependency: {}", e),
|
format!("Failed to find location of 'graphene_core' or 'graphene-core-shaders'. Make sure it is imported as a dependency: {e}"),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
match crate_name {
|
match crate_name {
|
||||||
|
|
|
||||||
|
|
@ -295,8 +295,8 @@ impl Parse for NodeFnAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_node_fn(attr: TokenStream2, item: TokenStream2) -> syn::Result<ParsedNodeFn> {
|
fn parse_node_fn(attr: TokenStream2, item: TokenStream2) -> syn::Result<ParsedNodeFn> {
|
||||||
let attributes = syn::parse2::<NodeFnAttributes>(attr.clone()).map_err(|e| Error::new(e.span(), format!("Failed to parse node_fn attributes: {}", e)))?;
|
let attributes = syn::parse2::<NodeFnAttributes>(attr.clone()).map_err(|e| Error::new(e.span(), format!("Failed to parse node_fn attributes: {e}")))?;
|
||||||
let input_fn = syn::parse2::<ItemFn>(item.clone()).map_err(|e| Error::new(e.span(), format!("Failed to parse function: {}. Make sure it's a valid Rust function.", e)))?;
|
let input_fn = syn::parse2::<ItemFn>(item.clone()).map_err(|e| Error::new(e.span(), format!("Failed to parse function: {e}. Make sure it's a valid Rust function.")))?;
|
||||||
|
|
||||||
let vis = input_fn.vis;
|
let vis = input_fn.vis;
|
||||||
let fn_name = input_fn.sig.ident.clone();
|
let fn_name = input_fn.sig.ident.clone();
|
||||||
|
|
@ -312,7 +312,7 @@ fn parse_node_fn(attr: TokenStream2, item: TokenStream2) -> syn::Result<ParsedNo
|
||||||
let crate_name = proc_macro_crate::crate_name("graphene-core").map_err(|e| {
|
let crate_name = proc_macro_crate::crate_name("graphene-core").map_err(|e| {
|
||||||
Error::new(
|
Error::new(
|
||||||
proc_macro2::Span::call_site(),
|
proc_macro2::Span::call_site(),
|
||||||
format!("Failed to find location of graphene_core. Make sure it is imported as a dependency: {}", e),
|
format!("Failed to find location of graphene_core. Make sure it is imported as a dependency: {e}"),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let description = input_fn
|
let description = input_fn
|
||||||
|
|
@ -405,7 +405,7 @@ fn parse_implementations(attr: &Attribute, name: &Ident) -> syn::Result<Punctuat
|
||||||
let parser = Punctuated::<Type, Comma>::parse_terminated;
|
let parser = Punctuated::<Type, Comma>::parse_terminated;
|
||||||
parser.parse2(content.clone()).map_err(|e| {
|
parser.parse2(content.clone()).map_err(|e| {
|
||||||
let span = e.span(); // Get the span of the error
|
let span = e.span(); // Get the span of the error
|
||||||
Error::new(span, format!("Failed to parse implementations for argument '{}': {}", name, e))
|
Error::new(span, format!("Failed to parse implementations for argument '{name}': {e}"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,27 +431,21 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
||||||
let ident = &pat_ident.ident;
|
let ident = &pat_ident.ident;
|
||||||
|
|
||||||
let default_value = extract_attribute(attrs, "default")
|
let default_value = extract_attribute(attrs, "default")
|
||||||
.map(|attr| {
|
.map(|attr| attr.parse_args().map_err(|e| Error::new_spanned(attr, format!("Invalid `default` value for argument '{ident}': {e}"))))
|
||||||
attr.parse_args()
|
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid `default` value for argument '{}': {}", ident, e)))
|
|
||||||
})
|
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let scope = extract_attribute(attrs, "scope")
|
let scope = extract_attribute(attrs, "scope")
|
||||||
.map(|attr| {
|
.map(|attr| attr.parse_args().map_err(|e| Error::new_spanned(attr, format!("Invalid `scope` value for argument '{ident}': {e}"))))
|
||||||
attr.parse_args()
|
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid `scope` value for argument '{}': {}", ident, e)))
|
|
||||||
})
|
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let name = extract_attribute(attrs, "name")
|
let name = extract_attribute(attrs, "name")
|
||||||
.map(|attr| attr.parse_args().map_err(|e| Error::new_spanned(attr, format!("Invalid `name` value for argument '{}': {}", ident, e))))
|
.map(|attr| attr.parse_args().map_err(|e| Error::new_spanned(attr, format!("Invalid `name` value for argument '{ident}': {e}"))))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let widget_override = extract_attribute(attrs, "widget")
|
let widget_override = extract_attribute(attrs, "widget")
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
attr.parse_args()
|
attr.parse_args()
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid `widget override` value for argument '{}': {}", ident, e)))
|
.map_err(|e| Error::new_spanned(attr, format!("Invalid `widget override` value for argument '{ident}': {e}")))
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
@ -468,26 +462,26 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
||||||
let number_soft_min = extract_attribute(attrs, "soft_min")
|
let number_soft_min = extract_attribute(attrs, "soft_min")
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
attr.parse_args()
|
attr.parse_args()
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `soft_min` value for argument '{}': {}", ident, e)))
|
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `soft_min` value for argument '{ident}': {e}")))
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let number_soft_max = extract_attribute(attrs, "soft_max")
|
let number_soft_max = extract_attribute(attrs, "soft_max")
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
attr.parse_args()
|
attr.parse_args()
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `soft_max` value for argument '{}': {}", ident, e)))
|
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `soft_max` value for argument '{ident}': {e}")))
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let number_hard_min = extract_attribute(attrs, "hard_min")
|
let number_hard_min = extract_attribute(attrs, "hard_min")
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
attr.parse_args()
|
attr.parse_args()
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `hard_min` value for argument '{}': {}", ident, e)))
|
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `hard_min` value for argument '{ident}': {e}")))
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
let number_hard_max = extract_attribute(attrs, "hard_max")
|
let number_hard_max = extract_attribute(attrs, "hard_max")
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
attr.parse_args()
|
attr.parse_args()
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `hard_max` value for argument '{}': {}", ident, e)))
|
.map_err(|e| Error::new_spanned(attr, format!("Invalid numerical `hard_max` value for argument '{ident}': {e}")))
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
|
|
@ -496,10 +490,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
||||||
attr.parse_args::<ExprTuple>().map_err(|e| {
|
attr.parse_args::<ExprTuple>().map_err(|e| {
|
||||||
Error::new_spanned(
|
Error::new_spanned(
|
||||||
attr,
|
attr,
|
||||||
format!(
|
format!("Invalid `range` tuple of min and max range slider values for argument '{ident}': {e}\nUSAGE EXAMPLE: #[range((0., 100.))]"),
|
||||||
"Invalid `range` tuple of min and max range slider values for argument '{}': {}\nUSAGE EXAMPLE: #[range((0., 100.))]",
|
|
||||||
ident, e
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -511,7 +502,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
||||||
}
|
}
|
||||||
|
|
||||||
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, format!("Expected a unit type as string"))))
|
.map(|attr| attr.parse_args::<LitStr>().map_err(|_e| Error::new_spanned(attr, "Expected a unit type as string".to_string())))
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
let number_display_decimal_places = extract_attribute(attrs, "display_decimal_places")
|
let number_display_decimal_places = extract_attribute(attrs, "display_decimal_places")
|
||||||
|
|
@ -519,14 +510,14 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
||||||
attr.parse_args::<LitInt>().map_err(|e| {
|
attr.parse_args::<LitInt>().map_err(|e| {
|
||||||
Error::new_spanned(
|
Error::new_spanned(
|
||||||
attr,
|
attr,
|
||||||
format!("Invalid `integer` for number of decimals for argument '{}': {}\nUSAGE EXAMPLE: #[display_decimal_places(2)]", ident, e),
|
format!("Invalid `integer` for number of decimals for argument '{ident}': {e}\nUSAGE EXAMPLE: #[display_decimal_places(2)]"),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.map(|f| {
|
.map(|f| {
|
||||||
if let Err(e) = f.base10_parse::<u32>() {
|
if let Err(e) = f.base10_parse::<u32>() {
|
||||||
Err(Error::new_spanned(f, format!("Expected a `u32` for `display_decimal_places` for '{}': {}", ident, e)))
|
Err(Error::new_spanned(f, format!("Expected a `u32` for `display_decimal_places` for '{ident}': {e}")))
|
||||||
} else {
|
} else {
|
||||||
Ok(f)
|
Ok(f)
|
||||||
}
|
}
|
||||||
|
|
@ -535,7 +526,7 @@ fn parse_field(pat_ident: PatIdent, ty: Type, attrs: &[Attribute]) -> syn::Resul
|
||||||
let number_step = extract_attribute(attrs, "step")
|
let number_step = extract_attribute(attrs, "step")
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
attr.parse_args::<LitFloat>()
|
attr.parse_args::<LitFloat>()
|
||||||
.map_err(|e| Error::new_spanned(attr, format!("Invalid `step` for argument '{}': {}\nUSAGE EXAMPLE: #[step(2.)]", ident, e)))
|
.map_err(|e| Error::new_spanned(attr, format!("Invalid `step` for argument '{ident}': {e}\nUSAGE EXAMPLE: #[step(2.)]")))
|
||||||
})
|
})
|
||||||
.transpose()?;
|
.transpose()?;
|
||||||
|
|
||||||
|
|
@ -660,7 +651,7 @@ pub fn new_node_fn(attr: TokenStream2, item: TokenStream2) -> TokenStream2 {
|
||||||
Ok(parsed) => parsed,
|
Ok(parsed) => parsed,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Return the error as a compile error
|
// Return the error as a compile error
|
||||||
Error::new(e.span(), format!("Failed to parse node function: {}", e)).to_compile_error()
|
Error::new(e.span(), format!("Failed to parse node function: {e}")).to_compile_error()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -757,7 +748,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
_ => panic!("Mismatched default values"),
|
_ => panic!("Mismatched default values"),
|
||||||
}
|
}
|
||||||
assert_eq!(format!("{:?}", p_ty), format!("{:?}", e_ty));
|
assert_eq!(format!("{p_ty:?}"), format!("{:?}", e_ty));
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
ParsedField {
|
ParsedField {
|
||||||
|
|
@ -780,8 +771,8 @@ mod tests {
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
assert_eq!(p_name, e_name);
|
assert_eq!(p_name, e_name);
|
||||||
assert_eq!(format!("{:?}", p_input), format!("{:?}", e_input));
|
assert_eq!(format!("{p_input:?}"), format!("{:?}", e_input));
|
||||||
assert_eq!(format!("{:?}", p_output), format!("{:?}", e_output));
|
assert_eq!(format!("{p_output:?}"), format!("{:?}", e_output));
|
||||||
}
|
}
|
||||||
_ => panic!("Mismatched field types"),
|
_ => panic!("Mismatched field types"),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ pub fn generate_node_substitutions() -> HashMap<ProtoNodeIdentifier, DocumentNod
|
||||||
let document_node = DocumentNode {
|
let document_node = DocumentNode {
|
||||||
inputs: network_inputs,
|
inputs: network_inputs,
|
||||||
manual_composition: Some(input_type.clone()),
|
manual_composition: Some(input_type.clone()),
|
||||||
implementation: DocumentNodeImplementation::ProtoNode(id.clone().into()),
|
implementation: DocumentNodeImplementation::ProtoNode(id.clone()),
|
||||||
visible: true,
|
visible: true,
|
||||||
skip_deduplication: false,
|
skip_deduplication: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -101,14 +101,11 @@ pub fn derive_discriminant_impl(input_item: TokenStream) -> syn::Result<TokenStr
|
||||||
let (pattern, value) = is_sub_discriminant
|
let (pattern, value) = is_sub_discriminant
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|b| {
|
.map(|b| {
|
||||||
(
|
|
||||||
if b {
|
if b {
|
||||||
quote::quote! { (x) }
|
(quote::quote! {(x)}, quote::quote! {(x.to_discriminant())})
|
||||||
} else {
|
} else {
|
||||||
quote::quote! { { .. } }
|
(quote::quote! {{..}}, Default::default())
|
||||||
},
|
}
|
||||||
b.then(|| quote::quote! { (x.to_discriminant()) }).unwrap_or_default(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unzip::<_, _, Vec<_>, Vec<_>>();
|
.unzip::<_, _, Vec<_>, Vec<_>>();
|
||||||
#[cfg(feature = "serde-discriminant")]
|
#[cfg(feature = "serde-discriminant")]
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ pub fn clean_rust_type_syntax(input: String) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'<' => {
|
'<' => {
|
||||||
while let Some(' ') = result.chars().rev().next() {
|
while let Some(' ') = result.chars().next_back() {
|
||||||
result.pop();
|
result.pop();
|
||||||
}
|
}
|
||||||
result.push('<');
|
result.push('<');
|
||||||
|
|
@ -64,7 +64,7 @@ pub fn clean_rust_type_syntax(input: String) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'>' => {
|
'>' => {
|
||||||
while let Some(' ') = result.chars().rev().next() {
|
while let Some(' ') = result.chars().next_back() {
|
||||||
result.pop();
|
result.pop();
|
||||||
}
|
}
|
||||||
result.push('>');
|
result.push('>');
|
||||||
|
|
@ -74,7 +74,7 @@ pub fn clean_rust_type_syntax(input: String) -> String {
|
||||||
}
|
}
|
||||||
'-' => {
|
'-' => {
|
||||||
if let Some('>') = chars.peek() {
|
if let Some('>') = chars.peek() {
|
||||||
while let Some(' ') = result.chars().rev().next() {
|
while let Some(' ') = result.chars().next_back() {
|
||||||
result.pop();
|
result.pop();
|
||||||
}
|
}
|
||||||
result.push_str(" -> ");
|
result.push_str(" -> ");
|
||||||
|
|
@ -88,7 +88,7 @@ pub fn clean_rust_type_syntax(input: String) -> String {
|
||||||
}
|
}
|
||||||
':' => {
|
':' => {
|
||||||
if let Some(':') = chars.peek() {
|
if let Some(':') = chars.peek() {
|
||||||
while let Some(' ') = result.chars().rev().next() {
|
while let Some(' ') = result.chars().next_back() {
|
||||||
result.pop();
|
result.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,22 +47,20 @@ pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result<TokenStream
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let error_msg = match fields.unnamed.len() {
|
let error_msg = match fields.unnamed.len() {
|
||||||
0 => format!("Remove the unnecessary `()` from the `{}` message enum variant.", variant_type),
|
0 => format!("Remove the unnecessary `()` from the `{variant_type}` message enum variant."),
|
||||||
1 => {
|
1 => {
|
||||||
let field_type = &fields.unnamed.first().unwrap().ty;
|
let field_type = &fields.unnamed.first().unwrap().ty;
|
||||||
format!(
|
format!(
|
||||||
"The `{}` message should be defined as a struct-style (not tuple-style) enum variant to maintain consistent formatting across all editor messages.\n\
|
"The `{variant_type}` message should be defined as a struct-style (not tuple-style) enum variant to maintain consistent formatting across all editor messages.\n\
|
||||||
Replace `{}` with a named field using {{curly braces}} instead of a positional field using (parentheses).",
|
Replace `{}` with a named field using {{curly braces}} instead of a positional field using (parentheses).",
|
||||||
variant_type,
|
|
||||||
field_type.to_token_stream()
|
field_type.to_token_stream()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let field_types = fields.unnamed.iter().map(|f| f.ty.to_token_stream().to_string()).collect::<Vec<_>>().join(", ");
|
let field_types = fields.unnamed.iter().map(|f| f.ty.to_token_stream().to_string()).collect::<Vec<_>>().join(", ");
|
||||||
format!(
|
format!(
|
||||||
"The `{}` message should be defined as a struct-style (not tuple-style) enum variant to maintain consistent formatting across all editor messages.\n\
|
"The `{variant_type}` message should be defined as a struct-style (not tuple-style) enum variant to maintain consistent formatting across all editor messages.\n\
|
||||||
Replace `{}` with named fields using {{curly braces}} instead of positional fields using (parentheses).",
|
Replace `{field_types}` with named fields using {{curly braces}} instead of positional fields using (parentheses)."
|
||||||
variant_type, field_types
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue