const FPinConnectionResponse UMaterialGraphSchema::CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const { bool bPreventInvalidConnections = CVarPreventInvalidMaterialConnections.GetValueOnGameThread() != 0; // Make sure the pins are not on the same node if (A->GetOwningNode() == B->GetOwningNode()) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("ConnectionSameNode", "Both are on the same node")); } // Compare the directions const UEdGraphPin* InputPin = NULL; const UEdGraphPin* OutputPin = NULL; if (!CategorizePinsByDirection(A, B, /*out*/ InputPin, /*out*/ OutputPin)) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("ConnectionIncompatible", "Directions are not compatible")); } // Check for new and existing loops FText ResponseMessage; if (ConnectionCausesLoop(InputPin, OutputPin)) { ResponseMessage = LOCTEXT("ConnectionLoop", "Connection could cause loop"); // TODO: re-enable this if loops are going to be removed completely //return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("ConnectionLoop", "Connection would cause loop").ToString()); } // Check for incompatible pins and get description if they cannot connect if (!ArePinsCompatible(InputPin, OutputPin, ResponseMessage) && bPreventInvalidConnections) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, ResponseMessage); } // Break existing connections on inputs only - multiple output connections are acceptable if (InputPin->LinkedTo.Num() > 0) { ECanCreateConnectionResponse ReplyBreakOutputs; if (InputPin == A) { ReplyBreakOutputs = CONNECT_RESPONSE_BREAK_OTHERS_A; } else { ReplyBreakOutputs = CONNECT_RESPONSE_BREAK_OTHERS_B; } if (ResponseMessage.IsEmpty()) { ResponseMessage = LOCTEXT("ConnectionReplace", "Replace existing connections"); } return FPinConnectionResponse(ReplyBreakOutputs, ResponseMessage); } return FPinConnectionResponse(CONNECT_RESPONSE_MAKE, ResponseMessage); }
const FPinConnectionResponse UEdGraphSchema_Niagara::CanCreateConnection(const UEdGraphPin* PinA, const UEdGraphPin* PinB) const { // Make sure the pins are not on the same node if (PinA->GetOwningNode() == PinB->GetOwningNode()) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Both are on the same node")); } // Check both pins support connections if(PinA->bNotConnectable || PinB->bNotConnectable) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Pin doesn't support connections.")); } // Compare the directions const UEdGraphPin* InputPin = NULL; const UEdGraphPin* OutputPin = NULL; if (!CategorizePinsByDirection(PinA, PinB, /*out*/ InputPin, /*out*/ OutputPin)) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Directions are not compatible")); } // Types must match exactly if(PinA->PinType != PinB->PinType) { return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Types are not compatible")); } // See if we want to break existing connections (if its an input with an existing connection) const bool bBreakExistingDueToDataInput = (InputPin->LinkedTo.Num() > 0); if (bBreakExistingDueToDataInput) { const ECanCreateConnectionResponse ReplyBreakInputs = (PinA == InputPin) ? CONNECT_RESPONSE_BREAK_OTHERS_A : CONNECT_RESPONSE_BREAK_OTHERS_B; return FPinConnectionResponse(ReplyBreakInputs, TEXT("Replace existing input connections")); } else { return FPinConnectionResponse(CONNECT_RESPONSE_MAKE, TEXT("")); } }
bool UAnimationGraphSchema::CreateAutomaticConversionNodeAndConnections(UEdGraphPin* PinA, UEdGraphPin* PinB) const { // Determine which pin is an input and which pin is an output UEdGraphPin* InputPin = NULL; UEdGraphPin* OutputPin = NULL; if (!CategorizePinsByDirection(PinA, PinB, /*out*/ InputPin, /*out*/ OutputPin)) { return false; } // Look for animation specific conversion operations UK2Node* TemplateNode = NULL; if (IsComponentSpacePosePin(OutputPin->PinType) && IsLocalSpacePosePin(InputPin->PinType)) { TemplateNode = NewObject<UAnimGraphNode_ComponentToLocalSpace>(); } else if (IsLocalSpacePosePin(OutputPin->PinType) && IsComponentSpacePosePin(InputPin->PinType)) { TemplateNode = NewObject<UAnimGraphNode_LocalToComponentSpace>(); } // Spawn the conversion node if it's specific to animation if (TemplateNode != NULL) { UEdGraph* Graph = InputPin->GetOwningNode()->GetGraph(); FVector2D AverageLocation = CalculateAveragePositionBetweenNodes(InputPin, OutputPin); UK2Node* ConversionNode = FEdGraphSchemaAction_K2NewNode::SpawnNodeFromTemplate<UK2Node>(Graph, TemplateNode, AverageLocation); AutowireConversionNode(InputPin, OutputPin, ConversionNode); return true; } else { // Give the regular conversions a shot return Super::CreateAutomaticConversionNodeAndConnections(PinA, PinB); } }