UEdGraphPin* FWeakGraphPinPtr::Get() { UEdGraphNode* Node = NodeObjectPtr.Get(); if(Node != NULL) { // If pin is no longer valid or has a different owner, attempt to fix up the reference UEdGraphPin* Pin = PinObjectPtr.Get(); if(Pin == NULL || Pin->GetOuter() != Node) { for(auto PinIter = Node->Pins.CreateConstIterator(); PinIter; ++PinIter) { UEdGraphPin* TestPin = *PinIter; if(TestPin->PinName.Equals(PinName)) { Pin = TestPin; PinObjectPtr = Pin; break; } } } return Pin; } return NULL; }
void FEnumEditorUtils::BroadcastChanges(const UUserDefinedEnum* Enum, const TArray<TPair<FName, int8>>& OldNames, bool bResolveData) { check(NULL != Enum); if (bResolveData) { FArchiveEnumeratorResolver EnumeratorResolver(Enum, OldNames); TArray<UClass*> ClassesToCheck; for (TObjectIterator<UByteProperty> PropertyIter; PropertyIter; ++PropertyIter) { const UByteProperty* ByteProperty = *PropertyIter; if (ByteProperty && (Enum == ByteProperty->GetIntPropertyEnum())) { UClass* OwnerClass = ByteProperty->GetOwnerClass(); if (OwnerClass) { ClassesToCheck.Add(OwnerClass); } } } for (FObjectIterator ObjIter; ObjIter; ++ObjIter) { for (auto ClassIter = ClassesToCheck.CreateConstIterator(); ClassIter; ++ClassIter) { if (ObjIter->IsA(*ClassIter)) { ObjIter->Serialize(EnumeratorResolver); break; } } } } struct FNodeValidatorHelper { static bool IsValid(UK2Node* Node) { return Node && (NULL != Cast<UEdGraph>(Node->GetOuter())) && !Node->HasAnyFlags(RF_Transient | RF_PendingKill); } }; TSet<UBlueprint*> BlueprintsToRefresh; { //CUSTOM NODES DEPENTENT ON ENUM for (TObjectIterator<UK2Node> It(RF_Transient); It; ++It) { UK2Node* Node = *It; INodeDependingOnEnumInterface* NodeDependingOnEnum = Cast<INodeDependingOnEnumInterface>(Node); if (FNodeValidatorHelper::IsValid(Node) && NodeDependingOnEnum && (Enum == NodeDependingOnEnum->GetEnum())) { if (UBlueprint* Blueprint = Node->GetBlueprint()) { if (NodeDependingOnEnum->ShouldBeReconstructedAfterEnumChanged()) { Node->ReconstructNode(); } BlueprintsToRefresh.Add(Blueprint); } } } } for (TObjectIterator<UEdGraphPin> It(RF_Transient); It; ++It) { UEdGraphPin* Pin = *It; if (Pin && (Enum == Pin->PinType.PinSubCategoryObject.Get()) && (EEdGraphPinDirection::EGPD_Input == Pin->Direction)) { UK2Node* Node = Cast<UK2Node>(Pin->GetOuter()); if (FNodeValidatorHelper::IsValid(Node)) { if (UBlueprint* Blueprint = Node->GetBlueprint()) { if (INDEX_NONE == Enum->FindEnumIndex(*Pin->DefaultValue)) { Pin->Modify(); if (Blueprint->BlueprintType == BPTYPE_Interface) { Pin->DefaultValue = Enum->GetEnumName(0); } else { Pin->DefaultValue = FEnumEditorUtilsHelper::InvalidName(); } Node->PinDefaultValueChanged(Pin); BlueprintsToRefresh.Add(Blueprint); } } } } } for (auto It = BlueprintsToRefresh.CreateIterator(); It; ++It) { FBlueprintEditorUtils::MarkBlueprintAsModified(*It); (*It)->BroadcastChanged(); } FEnumEditorManager::Get().PostChange(Enum, EEnumEditorChangeInfo::Changed); }
// Context used to aid debugging displays for nodes FKismetNodeInfoContext::FKismetNodeInfoContext(UEdGraph* SourceGraph) : ActiveObjectBeingDebugged(NULL) { // Only show pending latent actions in PIE/SIE mode SourceBlueprint = FBlueprintEditorUtils::FindBlueprintForGraph(SourceGraph); if (SourceBlueprint != NULL) { ActiveObjectBeingDebugged = SourceBlueprint->GetObjectBeingDebugged(); // Run thru debugged objects to see if any are objects with pending latent actions if (ActiveObjectBeingDebugged != NULL) { UBlueprintGeneratedClass* Class = CastChecked<UBlueprintGeneratedClass>((UObject*)(ActiveObjectBeingDebugged->GetClass())); FBlueprintDebugData const& ClassDebugData = Class->GetDebugData(); TSet<UObject*> LatentContextObjects; TArray<UK2Node_CallFunction*> FunctionNodes; SourceGraph->GetNodesOfClass<UK2Node_CallFunction>(FunctionNodes); // collect all the world context objects for all of the graph's latent nodes for (UK2Node_CallFunction const* FunctionNode : FunctionNodes) { UFunction* Function = FunctionNode->GetTargetFunction(); if ((Function == NULL) || !Function->HasMetaData(FBlueprintMetadata::MD_Latent)) { continue; } UObject* NodeWorldContext = ActiveObjectBeingDebugged; // if the node has a specific "world context" pin, attempt to get the value set for that first if (Function->HasMetaData(FBlueprintMetadata::MD_WorldContext)) { FString const WorldContextPinName = Function->GetMetaData(FBlueprintMetadata::MD_WorldContext); if (UEdGraphPin* ContextPin = FunctionNode->FindPin(WorldContextPinName)) { if (UObjectPropertyBase* ContextProperty = Cast<UObjectPropertyBase>(ClassDebugData.FindClassPropertyForPin(ContextPin))) { UObject* PropertyValue = ContextProperty->GetObjectPropertyValue_InContainer(ActiveObjectBeingDebugged); if (PropertyValue != NULL) { NodeWorldContext = PropertyValue; } } } } LatentContextObjects.Add(NodeWorldContext); } for (UObject* ContextObject : LatentContextObjects) { if (UWorld* World = GEngine->GetWorldFromContextObject(ContextObject, /*bChecked =*/false)) { FLatentActionManager& Manager = World->GetLatentActionManager(); TSet<int32> UUIDSet; Manager.GetActiveUUIDs(ActiveObjectBeingDebugged, /*out*/ UUIDSet); for (TSet<int32>::TConstIterator IterUUID(UUIDSet); IterUUID; ++IterUUID) { const int32 UUID = *IterUUID; if (UEdGraphNode* ParentNode = ClassDebugData.FindNodeFromUUID(UUID)) { TArray<FObjectUUIDPair>& Pairs = NodesWithActiveLatentActions.FindOrAdd(ParentNode); new (Pairs) FObjectUUIDPair(ContextObject, UUID); } } } } } // Covert the watched pin array into a set for (auto WatchedPinIt = SourceBlueprint->PinWatches.CreateConstIterator(); WatchedPinIt; ++WatchedPinIt) { UEdGraphPin* WatchedPin = *WatchedPinIt; UEdGraphNode* OwningNode = Cast<UEdGraphNode>(WatchedPin->GetOuter()); if (!ensure(OwningNode != NULL)) // shouldn't happen, but just in case a dead pin was added to the PinWatches array { continue; } check(OwningNode == WatchedPin->GetOwningNode()); WatchedPinSet.Add(WatchedPin); WatchedNodeSet.Add(OwningNode); } } }