mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-24 11:28:13 +08:00
Fix several bugs causing warning spam in the console (#4547)
This commit is contained in:
@@ -480,7 +480,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
NodeInput::value(TaggedValue::F64(10.), false),
|
||||
NodeInput::value(TaggedValue::Bool(Default::default()), false),
|
||||
NodeInput::value(TaggedValue::InterpolationDistribution(Default::default()), false),
|
||||
NodeInput::type_default(list!(Vector), false),
|
||||
NodeInput::type_default(item!(Vector), false),
|
||||
],
|
||||
input_metadata: vec![
|
||||
("Content", "TODO").into(),
|
||||
@@ -1533,6 +1533,26 @@ impl InputTypeConstraint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if a type reaches the constraint through an `input_adapter`, the per-connector node which the preprocessor places ahead of
|
||||
/// every ranked connector to convert or embed a convertible element, such as a color literal feeding a `Graphic` paint wire.
|
||||
#[must_use]
|
||||
fn satisfies_through_input_adapter(&self, ty: &Type) -> bool {
|
||||
let provided = Self::type_name(ty);
|
||||
|
||||
interpreted_executor::node_registry::NODE_REGISTRY
|
||||
.iter()
|
||||
.filter(|(identifier, _)| identifier.as_str().starts_with("input_adapter<"))
|
||||
.flat_map(|(_, implementations)| implementations.keys())
|
||||
.any(|node_io| node_io.inputs.first().is_some_and(|from| Self::type_name(from) == provided) && self.satisfies(&node_io.return_value))
|
||||
}
|
||||
|
||||
/// Check if a default value of this type is valid for the constraint.
|
||||
#[must_use]
|
||||
fn accepts_default_value(&self, ty: &Type) -> bool {
|
||||
// Empty types are used when the input must come from the graph so they can be skipped
|
||||
ty.nested_type() == &concrete!(()) || self.satisfies(ty) || self.satisfies_through_input_adapter(ty)
|
||||
}
|
||||
|
||||
/// Compute the type constraint for one input. Note that this cannot use the infrastructure in the node network interface as the node is not placed in a network.
|
||||
#[must_use]
|
||||
fn compute_constraint_for_input(template_document_node: &NodeTemplate, name: &str, input_index: usize) -> Self {
|
||||
@@ -1589,9 +1609,7 @@ impl InputTypeConstraint {
|
||||
for (index, (constraint, input)) in all_input_constraints.iter().zip(&template_document_node.inputs).enumerate() {
|
||||
if let Some(value) = input.as_value() {
|
||||
let input_ty = value.ty();
|
||||
|
||||
// Empty types are used when the input must come from the graph so they can be skipped.
|
||||
if input_ty.nested_type() != &concrete!(()) && !constraint.satisfies(&input_ty) {
|
||||
if !constraint.accepts_default_value(&input_ty) {
|
||||
warn!("The default value for input index {index} node {name} is {input_ty}, but does not satisfy {constraint:?}");
|
||||
}
|
||||
}
|
||||
@@ -1687,6 +1705,27 @@ mod test {
|
||||
|
||||
editor.eval_graph().await.expect("the Origins to Polyline chain should type-resolve and evaluate");
|
||||
}
|
||||
|
||||
// Guards the unconnected Path input, whose default must match the rank of the Morph connector it feeds
|
||||
#[tokio::test]
|
||||
async fn blend_resolves_and_evaluates_with_default_inputs() {
|
||||
let mut editor = EditorTestUtils::create();
|
||||
editor.new_document().await;
|
||||
editor.draw_rect(0., 0., 10., 10.).await;
|
||||
|
||||
let layer = editor.active_document().metadata().all_layers().next().expect("drawing a rectangle should create a layer");
|
||||
let node_id = NodeId::new();
|
||||
let node_template = resolve_network_node_type("Blend").expect("the Blend definition should exist").default_node_template();
|
||||
editor
|
||||
.handle_message(NodeGraphMessage::InsertNode {
|
||||
node_id,
|
||||
node_template: Box::new(node_template),
|
||||
})
|
||||
.await;
|
||||
editor.handle_message(NodeGraphMessage::MoveNodeToChainStart { node_id, parent: layer }).await;
|
||||
|
||||
editor.eval_graph().await.expect("the Blend network should type-resolve and evaluate");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -1707,6 +1746,25 @@ mod test_type_constraints {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_definition_default_value_satisfies_its_constraint() {
|
||||
let mut violations = Vec::new();
|
||||
for definition in super::DOCUMENT_NODE_TYPES.values() {
|
||||
let name = &definition.node_template.display_name;
|
||||
let constraints = InputTypeConstraint::constraints_for_all_inputs(&definition.node_template, name);
|
||||
|
||||
for (index, (constraint, input)) in constraints.iter().zip(&definition.node_template.inputs).enumerate() {
|
||||
if let Some(value) = input.as_value()
|
||||
&& !constraint.accepts_default_value(&value.ty())
|
||||
{
|
||||
violations.push(format!("{name} input {index}: {} does not satisfy {constraint:?}", value.ty()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert!(violations.is_empty(), "Default values rejected by their input constraints:\n{}", violations.join("\n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn passthrough() {
|
||||
let node_type = resolve_proto_node_type(graphene_std::ops::passthrough::IDENTIFIER).expect("passthrough node");
|
||||
|
||||
Reference in New Issue
Block a user