void FBuildPatchAppManifest::EnumerateChunkPartInventory(const TArray<FGuid>& ChunksRequired, TMap<FGuid, TArray<FFileChunkPart>>& ChunkPartsAvailable) const { ChunkPartsAvailable.Empty(); // Use a set to optimize TSet<FGuid> ChunksReqSet(ChunksRequired); // For each file in the manifest, check what chunks it is made out of, and grab details for the ones in ChunksRequired for (auto FileManifestIt = Data->FileManifestList.CreateConstIterator(); FileManifestIt && !FBuildPatchInstallError::HasFatalError(); ++FileManifestIt) { const FFileManifestData& FileManifest = *FileManifestIt; uint64 FileOffset = 0; for (auto ChunkPartIt = FileManifest.FileChunkParts.CreateConstIterator(); ChunkPartIt && !FBuildPatchInstallError::HasFatalError(); ++ChunkPartIt) { const FChunkPartData& ChunkPart = *ChunkPartIt; if (ChunksReqSet.Contains(ChunkPart.Guid)) { TArray<FFileChunkPart>& FileChunkParts = ChunkPartsAvailable.FindOrAdd(ChunkPart.Guid); FFileChunkPart FileChunkPart; FileChunkPart.Filename = FileManifest.Filename; FileChunkPart.ChunkPart = ChunkPart; FileChunkPart.FileOffset = FileOffset; FileChunkParts.Add(FileChunkPart); } FileOffset += ChunkPart.Size; } } }
bool FChunkManifestGenerator::LoadAssetRegistry(const FString& SandboxPath, const TSet<FName>* PackagesToKeep) { UE_LOG(LogChunkManifestGenerator, Display, TEXT("Loading asset registry.")); // Load generated registry for each platform check(Platforms.Num() == 1); for (auto Platform : Platforms) { /*FString PlatformSandboxPath = SandboxPath.Replace(TEXT("[Platform]"), *Platform->PlatformName()); FArchive* AssetRegistryReader = IFileManager::Get().CreateFileReader(*PlatformSandboxPath);*/ FString PlatformSandboxPath = SandboxPath.Replace(TEXT("[Platform]"), *Platform->PlatformName()); FArrayReader FileContents; if (FFileHelper::LoadFileToArray(FileContents, *PlatformSandboxPath) == false) { continue; } FArchive* AssetRegistryReader = &FileContents; TMap<FName, FAssetData*> SavedAssetRegistryData; TArray<FDependsNode*> DependencyData; if (AssetRegistryReader) { AssetRegistry.LoadRegistryData(*AssetRegistryReader, SavedAssetRegistryData, DependencyData); } for (auto& LoadedAssetData : AssetRegistryData) { if (PackagesToKeep && PackagesToKeep->Contains(LoadedAssetData.PackageName) == false) { continue; } FAssetData* FoundAssetData = SavedAssetRegistryData.FindRef(LoadedAssetData.ObjectPath); if ( FoundAssetData ) { LoadedAssetData.ChunkIDs.Append(FoundAssetData->ChunkIDs); SavedAssetRegistryData.Remove(LoadedAssetData.ObjectPath); delete FoundAssetData; } } for (const auto& SavedAsset : SavedAssetRegistryData) { if (PackagesToKeep && PackagesToKeep->Contains(SavedAsset.Value->PackageName)) { AssetRegistryData.Add(*SavedAsset.Value); } delete SavedAsset.Value; } SavedAssetRegistryData.Empty(); } return true; }
void ClearDelegateObjects() { for (auto obj : DelegateObjects) { obj->RemoveFromRoot(); } DelegateObjects.Empty(); functions.Empty(); }
void EmptyD3DSamplerStateCache() { for (auto Iter = GSamplerStateCache.CreateIterator(); Iter; ++Iter ) { auto* State = Iter.Value(); // Manually release State->Release(); } GSamplerStateCache.Empty(); }
void EmptyD3DSamplerStateCache() { #if LOCK_GSamplerStateCache FScopeLock Lock(&GSamplerStateCacheLock); #endif for (auto Iter = GSamplerStateCache.CreateIterator(); Iter; ++Iter ) { auto* State = Iter.Value(); // Manually release State->Release(); } GSamplerStateCache.Empty(); }
void FBlueprintCompileReinstancer::GenerateFieldMappings(TMap<UObject*, UObject*>& FieldMapping) { check(ClassToReinstance); FieldMapping.Empty(); for (auto& Prop : PropertyMap) { FieldMapping.Add(Prop.Value, FindField<UProperty>(ClassToReinstance, *Prop.Key.ToString())); } for (auto& Func : FunctionMap) { UFunction* NewFunction = ClassToReinstance->FindFunctionByName(Func.Key, EIncludeSuperFlag::ExcludeSuper); FieldMapping.Add(Func.Value, NewFunction); } UObject* NewCDO = ClassToReinstance->GetDefaultObject(); FieldMapping.Add(OriginalCDO, NewCDO); }
~FProtoMessagePool() { for (TMap<TWeakObjectPtr<UFunction>, PoolMapping>::TIterator It(Pool); It; ++It) { PoolMapping& PM = It.Value(); // Delete all the non-prototype versions of the message in the pool MessagePoolElem* Elem = PM.FreeList; while (Elem) { MessagePoolElem* NextElem = Elem->Next(); delete (*Elem)->Msg; delete Elem; Elem = NextElem; } } Pool.Empty(); // Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary(); }
/** * Process a string command to the logging suppression system * @param CmdString, string to process * @param FromBoot, if true, this is a boot time command, and is handled differently */ void ProcessCmdString(const FString& CmdString, bool FromBoot = false) { // How to use the log command : `log <category> <verbosity> // e.g., Turn off all logging : `log global none // e.g., Set specific filter : `log logshaders verbose // e.g., Combo command : `log global none, log logshaders verbose static FName NAME_BootGlobal(TEXT("BootGlobal")); static FName NAME_Reset(TEXT("Reset")); FString Cmds = CmdString; Cmds = Cmds.Trim().TrimQuotes(); Cmds.Trim(); TArray<FString> SubCmds; Cmds.ParseIntoArray(SubCmds, TEXT(","), true); for (int32 Index = 0; Index < SubCmds.Num(); Index++) { static FString LogString(TEXT("Log ")); FString Command = SubCmds[Index].Trim(); if (Command.StartsWith(*LogString)) { Command = Command.Right(Command.Len() - LogString.Len()); } TArray<FString> CommandParts; Command.ParseIntoArrayWS(CommandParts); if (CommandParts.Num() < 1) { continue; } FName Category(*CommandParts[0]); if (Category == NAME_Global && FromBoot) { Category = NAME_BootGlobal; // the boot time global is a special one, since we want things like "log global none, log logshaders verbose" } TArray<FLogCategoryBase*> CategoryVerbosities; uint8 Value = 0; if (FromBoot) { // now maybe this was already set at boot, in which case we override what it had uint8* Boot = BootAssociations.Find(Category); if (Boot) { Value = *Boot; } else { // see if we had a boot global override Boot = BootAssociations.Find(NAME_BootGlobal); if (Boot) { Value = *Boot; } } } else { for (TMultiMap<FName, FLogCategoryBase*>::TKeyIterator It(ReverseAssociations, Category); It; ++It) { checkSlow(!(It.Value()->Verbosity & ELogVerbosity::BreakOnLog)); // this bit is factored out of this variable, always Value = It.Value()->Verbosity | (It.Value()->DebugBreakOnLog ? ELogVerbosity::BreakOnLog : 0); CategoryVerbosities.Add(It.Value()); } } if (CommandParts.Num() == 1) { // only possibility is the reset and toggle command which is meaningless at boot if (!FromBoot) { if (Category == NAME_Reset) { for (TMap<FLogCategoryBase*, FName>::TIterator It(Associations); It; ++It) { FLogCategoryBase* Verb = It.Key(); Verb->ResetFromDefault(); // store off the last non-zero one for toggle checkSlow(!(Verb->Verbosity & ELogVerbosity::BreakOnLog)); // this bit is factored out of this variable, always if (Verb->Verbosity) { // currently on, store this in the pending and clear it ToggleAssociations.Add(Category, Verb->Verbosity); } } } else { if (Value & ELogVerbosity::VerbosityMask) { // currently on, toggle it Value = Value & ~ELogVerbosity::VerbosityMask; } else { // try to get a non-zero value from the toggle backup uint8* Toggle = ToggleAssociations.Find(Category); if (Toggle && *Toggle) { Value |= *Toggle; } else { Value |= ELogVerbosity::All; } } } } } else { // now we have the current value, lets change it! for (int32 PartIndex = 1; PartIndex < CommandParts.Num(); PartIndex++) { FName CmdToken = FName(*CommandParts[PartIndex]); static FName NAME_Verbose(TEXT("Verbose")); static FName NAME_VeryVerbose(TEXT("VeryVerbose")); static FName NAME_All(TEXT("All")); static FName NAME_Default(TEXT("Default")); static FName NAME_On(TEXT("On")); static FName NAME_Off(TEXT("Off")); static FName NAME_Break(TEXT("Break")); static FName NAME_Fatal(TEXT("Fatal")); static FName NAME_Log(TEXT("Log")); static FName NAME_Display(TEXT("Display")); if (CmdToken == NAME_None) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Fatal; } else if (CmdToken == NAME_Fatal) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Fatal; } else if (CmdToken == NAME_Error) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Error; } else if (CmdToken == NAME_Warning) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Warning; } else if (CmdToken == NAME_Log) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Log; } else if (CmdToken == NAME_Display) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Display; } else if (CmdToken == NAME_Verbose) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Verbose; } else if (CmdToken == NAME_VeryVerbose || CmdToken == NAME_All) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::VeryVerbose; } else if (CmdToken == NAME_Default) { if (CategoryVerbosities.Num() && !FromBoot) { Value = CategoryVerbosities[0]->DefaultVerbosity; } } else if (CmdToken == NAME_Off) { Value &= ~ELogVerbosity::VerbosityMask; Value |= ELogVerbosity::Fatal; } else if (CmdToken == NAME_On) { Value &= ~ELogVerbosity::VerbosityMask; // try to get a non-zero value from the toggle backup uint8* Toggle = ToggleAssociations.Find(Category); if (Toggle && *Toggle) { Value |= *Toggle; } else { Value |= ELogVerbosity::All; } } else if (CmdToken == NAME_Break) { Value ^= ELogVerbosity::BreakOnLog; } } } if (Category != NAME_Reset) { if (FromBoot) { if (Category == NAME_BootGlobal) { // changing the global at boot removes everything set up so far BootAssociations.Empty(); } BootAssociations.Add(Category, Value); } else { for (int32 CategoryIndex = 0; CategoryIndex < CategoryVerbosities.Num(); CategoryIndex++) { FLogCategoryBase* Verb = CategoryVerbosities[CategoryIndex]; Verb->SetVerbosity(ELogVerbosity::Type(Value)); } if (Category == NAME_Global) { // if this was a global change, we need to change them all ApplyGlobalChanges(); } } // store off the last non-zero one for toggle if (Value & ELogVerbosity::VerbosityMask) { // currently on, store this in the pending and clear it ToggleAssociations.Add(Category, Value & ELogVerbosity::VerbosityMask); } } } }
// TODO: Refactor this (and some other stuff) into a preprocessing step for use by any compiler? bool FNiagaraCompiler::MergeInFunctionNodes() { struct FReconnectionInfo { public: UEdGraphPin* From; TArray<UEdGraphPin*> To; //Fallback default value if an input connection is not connected. FString FallbackDefault; FReconnectionInfo() : From(NULL) {} }; TMap<FName, FReconnectionInfo> InputConnections; TMap<FName, FReconnectionInfo> OutputConnections; TArray<class UEdGraphPin*> FuncCallInputPins; TArray<class UEdGraphPin*> FuncCallOutputPins; //Copies the function graph into the main graph. //Removes the Function call in the main graph and the input and output nodes in the function graph, reconnecting their pins appropriately. auto MergeFunctionIntoMainGraph = [&](UNiagaraNodeFunctionCall* InFunc, UNiagaraGraph* FuncGraph) { InputConnections.Empty(); OutputConnections.Empty(); FuncCallInputPins.Empty(); FuncCallOutputPins.Empty(); check(InFunc && FuncGraph); if (InFunc->FunctionScript) { //Get all the pins that are connected to the inputs of the function call node in the main graph. InFunc->GetInputPins(FuncCallInputPins); for (UEdGraphPin* FuncCallInputPin : FuncCallInputPins) { FName InputName(*FuncCallInputPin->PinName); FReconnectionInfo& InputConnection = InputConnections.FindOrAdd(InputName); if (FuncCallInputPin->LinkedTo.Num() > 0) { check(FuncCallInputPin->LinkedTo.Num() == 1); UEdGraphPin* LinkFrom = FuncCallInputPin->LinkedTo[0]; check(LinkFrom->Direction == EGPD_Output); InputConnection.From = LinkFrom; } else { //This input has no link so we need the default value from the pin. InputConnection.FallbackDefault = FuncCallInputPin->GetDefaultAsString(); } } //Get all the pins that are connected to the outputs of the function call node in the main graph. InFunc->GetOutputPins(FuncCallOutputPins); for (UEdGraphPin* FuncCallOutputPin : FuncCallOutputPins) { FName OutputName(*FuncCallOutputPin->PinName); for (UEdGraphPin* LinkTo : FuncCallOutputPin->LinkedTo) { check(LinkTo->Direction == EGPD_Input); FReconnectionInfo& OutputConnection = OutputConnections.FindOrAdd(OutputName); OutputConnection.To.Add(LinkTo); } } //Remove the function call node from the graph now that we have everything we need from it. SourceGraph->RemoveNode(InFunc); //Keep a list of the Input and Output nodes we see in the function graph so that we can remove (most of) them later. TArray<UEdGraphNode*, TInlineAllocator<64>> ToRemove; //Search the nodes in the function graph, finding any connections to input or output nodes. for (UEdGraphNode* FuncGraphNode : FuncGraph->Nodes) { if (UNiagaraNodeInput* InputNode = Cast<UNiagaraNodeInput>(FuncGraphNode)) { check(InputNode->Pins.Num() == 1); //Get an array of "To" pins from one or more input nodes referencing each named input. FReconnectionInfo& InputConnection = InputConnections.FindOrAdd(InputNode->Input.Name); if (InputConnection.From) { //We have a connection from the function call so remove the input node and connect to that. ToRemove.Add(InputNode); } else { //This input has no connection from the function call so what do we do here? //For now we just leave the input node and connect back to it. //This will mean unconnected pins from the function call will look for constants or attributes. //In some cases we may want to just take the default value from the function call pin instead? //Maybe have some properties on the function call defining that. InputConnection.From = InputNode->Pins[0]; } TArray<UEdGraphPin*>& LinkToPins = InputNode->Pins[0]->LinkedTo; for (UEdGraphPin* ToPin : LinkToPins) { check(ToPin->Direction == EGPD_Input); InputConnection.To.Add(ToPin); } } else if (UNiagaraNodeOutput* OutputNode = Cast<UNiagaraNodeOutput>(FuncGraphNode)) { //Unlike the input nodes, we don't have the option of keeping these if there is no "From" pin. The default values from the node pins should be used. ToRemove.Add(OutputNode); //For each output, get the "From" pin to be reconnected later. for (int32 OutputIdx = 0; OutputIdx < OutputNode->Outputs.Num(); ++OutputIdx) { FName OutputName = OutputNode->Outputs[OutputIdx].Name; UEdGraphPin* OutputNodePin = OutputNode->Pins[OutputIdx]; check(OutputNodePin->LinkedTo.Num() <= 1); FReconnectionInfo& OutputConnection = OutputConnections.FindOrAdd(OutputName); UEdGraphPin* LinkFromPin = OutputNodePin->LinkedTo.Num() == 1 ? OutputNodePin->LinkedTo[0] : NULL; if (LinkFromPin) { check(LinkFromPin->Direction == EGPD_Output); OutputConnection.From = LinkFromPin; } else { //This output is not connected so links to it in the main graph must use it's default value. OutputConnection.FallbackDefault = OutputNodePin->GetDefaultAsString(); } } } } //Remove all the In and Out nodes from the function graph. for (UEdGraphNode* Remove : ToRemove) { FuncGraph->RemoveNode(Remove); } //Copy the nodes from the function graph over into the main graph. FuncGraph->MoveNodesToAnotherGraph(SourceGraph, false); //Finally, do all the reconnection. auto MakeConnection = [&](FReconnectionInfo& Info) { for (UEdGraphPin* LinkTo : Info.To) { if (Info.From) { Info.From->MakeLinkTo(LinkTo); } else { LinkTo->DefaultValue = Info.FallbackDefault; } } }; for (TPair<FName, FReconnectionInfo>& ReconnectInfo : InputConnections){ MakeConnection(ReconnectInfo.Value); } for (TPair<FName, FReconnectionInfo>& ReconnectInfo : OutputConnections){ MakeConnection(ReconnectInfo.Value); } } }; //Helper struct for traversing nested function calls. struct FFunctionContext { //True if this context's function has been merged into the main graph. bool bProcessed; //The index of this context into the ContextPool. int32 PoolIdx; //Pointer back to the parent context for traversal. FFunctionContext* Parent; //The function call node for this function in the source/parent graph. UNiagaraNodeFunctionCall* Function; //The graph for this function that we are going to merge into the main graph. UNiagaraGraph* FunctionGraph; //The script from which the graph is copied. Used for re entrance check. UNiagaraScript* Script; //Contexts for function calls in this function graph. TArray<FFunctionContext*, TInlineAllocator<64>> SubFunctionCalls; FFunctionContext() : bProcessed(false) , PoolIdx(INDEX_NONE) , Parent(NULL) , Function(NULL) , FunctionGraph(NULL) , Script(NULL) { } /** We don't allow re-entrant functions as this would cause an infinite loop of merging in graphs. Maybe in the future if we allow branching in the VM we can allow this. */ bool CheckForReentrance()const { UNiagaraNodeFunctionCall* Func = Function; FFunctionContext* Curr = Parent; while (Curr) { if (Curr->Script == Script) return true; Curr = Curr->Parent; } return false; } FString GetCallstack()const { FString Ret; const FFunctionContext* Curr = this; while (Curr) { if (Curr->Script) { Ret.Append(*(Curr->Script->GetPathName())); } else { Ret.Append(TEXT("Unknown")); } Ret.Append(TEXT("\n")); Curr = Curr->Parent; } return Ret; } }; //A pool of contexts on the stack to avoid loads of needless, small heap allocations. TArray<FFunctionContext, TInlineAllocator<512>> ContextPool; ContextPool.Reserve(512); FFunctionContext RootContext; FFunctionContext* CurrentContext = &RootContext; CurrentContext->FunctionGraph = SourceGraph; CurrentContext->Script = Script; //Depth first traversal of all function calls. while (CurrentContext) { //Find any sub functions and process this function call. if (!CurrentContext->bProcessed) { CurrentContext->bProcessed = true; //Find any sub functions and check for re-entrance. if (CurrentContext->FunctionGraph) { for (UEdGraphNode* Node : CurrentContext->FunctionGraph->Nodes) { UNiagaraNodeFunctionCall* FuncNode = Cast<UNiagaraNodeFunctionCall>(Node); if (FuncNode) { int32 NewIdx = ContextPool.AddZeroed(); FFunctionContext* SubFuncContext = &ContextPool[NewIdx]; CurrentContext->SubFunctionCalls.Push(SubFuncContext); SubFuncContext->Parent = CurrentContext; SubFuncContext->Function = FuncNode; SubFuncContext->PoolIdx = NewIdx; SubFuncContext->Script = FuncNode->FunctionScript; if (SubFuncContext->CheckForReentrance()) { FString Callstack = SubFuncContext->GetCallstack(); MessageLog.Error(TEXT("Reentrant function call!\n%s"), *Callstack); return false; } //Copy the function graph as we'll be modifying it as we merge in with the main graph. UNiagaraScriptSource* FuncSource = CastChecked<UNiagaraScriptSource>(FuncNode->FunctionScript->Source); check(FuncSource); SubFuncContext->FunctionGraph = CastChecked<UNiagaraGraph>(FEdGraphUtilities::CloneGraph(FuncSource->NodeGraph, NULL, &MessageLog)); } } } //Merge this function into the main graph now. if (CurrentContext->Function && CurrentContext->FunctionGraph) { MergeFunctionIntoMainGraph(CurrentContext->Function, CurrentContext->FunctionGraph); } } if (CurrentContext->SubFunctionCalls.Num() > 0) { //Move to the next sub function. CurrentContext = CurrentContext->SubFunctionCalls.Pop(); } else { //Done processing this function so remove it and move back to the parent. if (CurrentContext->PoolIdx != INDEX_NONE) { CurrentContext->FunctionGraph->MarkPendingKill(); ContextPool.RemoveAtSwap(CurrentContext->PoolIdx); } CurrentContext = CurrentContext->Parent; } } return true; }
void IGameplayCueInterface::ClearTagToFunctionMap() { PerClassGameplayTagToFunctionMap.Empty(); }
FReply SGraphPin::OnPinMouseDown( const FGeometry& SenderGeometry, const FPointerEvent& MouseEvent ) { bIsMovingLinks = false; if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { if (!GraphPinObj->bNotConnectable && IsEditable.Get()) { if (MouseEvent.IsAltDown()) { // Alt-Left clicking will break all existing connections to a pin const UEdGraphSchema* Schema = GraphPinObj->GetSchema(); Schema->BreakPinLinks(*GraphPinObj, true); return FReply::Handled(); } auto OwnerNodePinned = OwnerNodePtr.Pin(); if (MouseEvent.IsControlDown() && (GraphPinObj->LinkedTo.Num() > 0)) { // Get a reference to the owning panel widget check(OwnerNodePinned.IsValid()); TSharedPtr<SGraphPanel> OwnerPanelPtr = OwnerNodePinned->GetOwnerPanel(); check(OwnerPanelPtr.IsValid()); // Obtain the set of all pins within the panel TSet<TSharedRef<SWidget> > AllPins; OwnerPanelPtr->GetAllPins(AllPins); // Construct a UEdGraphPin->SGraphPin mapping for the full pin set TMap< UEdGraphPin*, TSharedRef<SGraphPin> > PinToPinWidgetMap; for( TSet< TSharedRef<SWidget> >::TIterator ConnectorIt(AllPins); ConnectorIt; ++ConnectorIt ) { const TSharedRef<SWidget>& SomePinWidget = *ConnectorIt; const SGraphPin& PinWidget = static_cast<const SGraphPin&>(SomePinWidget.Get()); PinToPinWidgetMap.Add(PinWidget.GetPinObj(), StaticCastSharedRef<SGraphPin>(SomePinWidget)); } // Define a local struct to temporarily store lookup information for pins that we are currently linked to struct LinkedToPinInfo { // Pin name string FString PinName; // A weak reference to the node object that owns the pin TWeakObjectPtr<UEdGraphNode> OwnerNodePtr; }; // Build a lookup table containing information about the set of pins that we're currently linked to TArray<LinkedToPinInfo> LinkedToPinInfoArray; for( TArray<UEdGraphPin*>::TIterator LinkArrayIter(GetPinObj()->LinkedTo); LinkArrayIter; ++LinkArrayIter ) { if (auto PinWidget = PinToPinWidgetMap.Find(*LinkArrayIter)) { check((*PinWidget)->OwnerNodePtr.IsValid()); LinkedToPinInfo PinInfo; PinInfo.PinName = (*PinWidget)->GetPinObj()->PinName; PinInfo.OwnerNodePtr = (*PinWidget)->OwnerNodePtr.Pin()->GetNodeObj(); LinkedToPinInfoArray.Add(PinInfo); } } // Control-Left clicking will break all existing connections to a pin // Note that for some nodes, this can cause reconstruction. In that case, pins we had previously linked to may now be destroyed. const UEdGraphSchema* Schema = GraphPinObj->GetSchema(); Schema->BreakPinLinks(*GraphPinObj, true); // Check to see if the panel has been invalidated by a graph change notification if (!OwnerPanelPtr->Contains(OwnerNodePinned->GetNodeObj())) { // Force the panel to update. This will cause node & pin widgets to be reinstanced to match any reconstructed node/pin object references. OwnerPanelPtr->Update(); // Obtain the full set of pins again after the update AllPins.Empty(AllPins.Num()); OwnerPanelPtr->GetAllPins(AllPins); // Rebuild the UEdGraphPin->SGraphPin mapping for the full pin set PinToPinWidgetMap.Empty(PinToPinWidgetMap.Num()); for( TSet< TSharedRef<SWidget> >::TIterator ConnectorIt(AllPins); ConnectorIt; ++ConnectorIt ) { const TSharedRef<SWidget>& SomePinWidget = *ConnectorIt; const SGraphPin& PinWidget = static_cast<const SGraphPin&>(SomePinWidget.Get()); PinToPinWidgetMap.Add(PinWidget.GetPinObj(), StaticCastSharedRef<SGraphPin>(SomePinWidget)); } } // Now iterate over our lookup table to find the instances of pin widgets that we had previously linked to TArray<TSharedRef<SGraphPin>> PinArray; for(auto LinkedToPinInfoIter = LinkedToPinInfoArray.CreateConstIterator(); LinkedToPinInfoIter; ++LinkedToPinInfoIter) { LinkedToPinInfo PinInfo = *LinkedToPinInfoIter; UEdGraphNode* OwnerNodeObj = PinInfo.OwnerNodePtr.Get(); if(OwnerNodeObj != NULL) { for(auto PinIter = PinInfo.OwnerNodePtr.Get()->Pins.CreateConstIterator(); PinIter; ++PinIter) { UEdGraphPin* Pin = *PinIter; if(Pin->PinName == PinInfo.PinName) { if (auto pWidget = PinToPinWidgetMap.Find(Pin)) { PinArray.Add(*pWidget); } } } } } if(PinArray.Num() > 0) { bIsMovingLinks = true; return FReply::Handled().BeginDragDrop(SpawnPinDragEvent(OwnerPanelPtr.ToSharedRef(), PinArray, /*bIsShiftOperation=*/ false)); } else { // Shouldn't get here, but just in case we lose our previous links somehow after breaking them, we'll just skip the drag. return FReply::Handled(); } } // Start a drag-drop on the pin if (ensure(OwnerNodePinned.IsValid())) { TArray<TSharedRef<SGraphPin>> PinArray; PinArray.Add(SharedThis(this)); return FReply::Handled().BeginDragDrop(SpawnPinDragEvent(OwnerNodePinned->GetOwnerPanel().ToSharedRef(), PinArray, MouseEvent.IsShiftDown())); } else { return FReply::Unhandled(); } } else { // It's not connectable, but we don't want anything above us to process this left click. return FReply::Handled(); } } else { return FReply::Unhandled(); } }
void FChunkWriter::FQueuedChunkWriter::GetChunkFilesizes(TMap<FGuid, int64>& OutChunkFileSizes) { FScopeLock ScopeLock(&ChunkFileSizesCS); OutChunkFileSizes.Empty(ChunkFileSizes.Num()); OutChunkFileSizes.Append(ChunkFileSizes); }
void FVulkanVertexDeclaration::EmptyCache() { GVertexDeclarationCache.Empty(0); }