本文整理汇总了C++中TSet::Remove方法的典型用法代码示例。如果您正苦于以下问题:C++ TSet::Remove方法的具体用法?C++ TSet::Remove怎么用?C++ TSet::Remove使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TSet
的用法示例。
在下文中一共展示了TSet::Remove方法的9个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: RemoveOrphanedNodes
void UAIGraph::RemoveOrphanedNodes()
{
TSet<UObject*> NodeInstances;
CollectAllNodeInstances(NodeInstances);
NodeInstances.Remove(nullptr);
// Obtain a list of all nodes actually in the asset and discard unused nodes
TArray<UObject*> AllInners;
const bool bIncludeNestedObjects = false;
GetObjectsWithOuter(GetOuter(), AllInners, bIncludeNestedObjects);
for (auto InnerIt = AllInners.CreateConstIterator(); InnerIt; ++InnerIt)
{
UObject* TestObject = *InnerIt;
if (!NodeInstances.Contains(TestObject) && CanRemoveNestedObject(TestObject))
{
TestObject->SetFlags(RF_Transient);
TestObject->Rename(NULL, GetTransientPackage(), REN_DontCreateRedirectors | REN_NonTransactional | REN_ForceNoResetLoaders);
}
}
}
示例2: SyncTrackedComponents
void UActorRecording::SyncTrackedComponents(bool bIncludeNonCDO/*=true*/)
{
TArray<USceneComponent*> NewComponentArray;
GetSceneComponents(NewComponentArray, bIncludeNonCDO);
// Expire section recorders that are watching components no longer attached to our actor
TSet<USceneComponent*> ExpiredComponents;
for (TWeakObjectPtr<USceneComponent>& WeakComponent : TrackedComponents)
{
if (USceneComponent* Component = WeakComponent.Get())
{
ExpiredComponents.Add(Component);
}
}
for (USceneComponent* Component : NewComponentArray)
{
ExpiredComponents.Remove(Component);
}
for (TSharedPtr<IMovieSceneSectionRecorder>& SectionRecorder : SectionRecorders)
{
if (USceneComponent* Component = Cast<USceneComponent>(SectionRecorder->GetSourceObject()))
{
if (ExpiredComponents.Contains(Component))
{
SectionRecorder->InvalidateObjectToRecord();
}
}
}
TrackedComponents.Reset(NewComponentArray.Num());
for(USceneComponent* SceneComponent : NewComponentArray)
{
TrackedComponents.Add(SceneComponent);
}
}
示例3: CompileStruct
void FUserDefinedStructureCompilerUtils::CompileStruct(class UUserDefinedStruct* Struct, class FCompilerResultsLog& MessageLog, bool bForceRecompile)
{
if (FStructureEditorUtils::UserDefinedStructEnabled() && Struct)
{
TSet<UBlueprint*> BlueprintsThatHaveBeenRecompiled;
TSet<UBlueprint*> BlueprintsToRecompile;
TArray<UUserDefinedStruct*> ChangedStructs;
if (FUserDefinedStructureCompilerInner::ShouldBeCompiled(Struct) || bForceRecompile)
{
ChangedStructs.Add(Struct);
}
for (int32 StructIdx = 0; StructIdx < ChangedStructs.Num(); ++StructIdx)
{
UUserDefinedStruct* ChangedStruct = ChangedStructs[StructIdx];
if (ChangedStruct)
{
FStructureEditorUtils::BroadcastPreChange(ChangedStruct);
FUserDefinedStructureCompilerInner::ReplaceStructWithTempDuplicate(ChangedStruct, BlueprintsToRecompile, ChangedStructs);
ChangedStruct->Status = EUserDefinedStructureStatus::UDSS_Dirty;
}
}
// COMPILE IN PROPER ORDER
FUserDefinedStructureCompilerInner::BuildDependencyMapAndCompile(ChangedStructs, MessageLog);
// UPDATE ALL THINGS DEPENDENT ON COMPILED STRUCTURES
for (TObjectIterator<UK2Node> It(RF_Transient | RF_PendingKill | RF_ClassDefaultObject, true); It && ChangedStructs.Num(); ++It)
{
bool bReconstruct = false;
UK2Node* Node = *It;
if (Node && !Node->HasAnyFlags(RF_Transient | RF_PendingKill))
{
// If this is a struct operation node operation on the changed struct we must reconstruct
if (UK2Node_StructOperation* StructOpNode = Cast<UK2Node_StructOperation>(Node))
{
UUserDefinedStruct* StructInNode = Cast<UUserDefinedStruct>(StructOpNode->StructType);
if (StructInNode && ChangedStructs.Contains(StructInNode))
{
bReconstruct = true;
}
}
if (!bReconstruct)
{
// Look through the nodes pins and if any of them are split and the type of the split pin is a user defined struct we need to reconstruct
for (UEdGraphPin* Pin : Node->Pins)
{
if (Pin->SubPins.Num() > 0)
{
UUserDefinedStruct* StructType = Cast<UUserDefinedStruct>(Pin->PinType.PinSubCategoryObject.Get());
if (StructType && ChangedStructs.Contains(StructType))
{
bReconstruct = true;
break;
}
}
}
}
}
if (bReconstruct)
{
if (UBlueprint* FoundBlueprint = Node->GetBlueprint())
{
// The blueprint skeleton needs to be updated before we reconstruct the node
// or else we may have member references that point to the old skeleton
if (!BlueprintsThatHaveBeenRecompiled.Contains(FoundBlueprint))
{
BlueprintsThatHaveBeenRecompiled.Add(FoundBlueprint);
BlueprintsToRecompile.Remove(FoundBlueprint);
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(FoundBlueprint);
}
Node->ReconstructNode();
}
}
}
for (auto BPIter = BlueprintsToRecompile.CreateIterator(); BPIter; ++BPIter)
{
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(*BPIter);
}
for (auto ChangedStruct : ChangedStructs)
{
if (ChangedStruct)
{
FStructureEditorUtils::BroadcastPostChange(ChangedStruct);
ChangedStruct->MarkPackageDirty();
}
}
}
}
示例4: PostEditChangeProperty
void UMaterialParameterCollection::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
// If the array counts have changed, an element has been added or removed, and we need to update the uniform buffer layout,
// Which also requires recompiling any referencing materials
if (ScalarParameters.Num() != PreviousScalarParameters.Num()
|| VectorParameters.Num() != PreviousVectorParameters.Num())
{
// Limit the count of parameters to fit within uniform buffer limits
const uint32 MaxScalarParameters = 1024;
if (ScalarParameters.Num() > MaxScalarParameters)
{
ScalarParameters.RemoveAt(MaxScalarParameters, ScalarParameters.Num() - MaxScalarParameters);
}
const uint32 MaxVectorParameters = 1024;
if (VectorParameters.Num() > MaxVectorParameters)
{
VectorParameters.RemoveAt(MaxVectorParameters, VectorParameters.Num() - MaxVectorParameters);
}
// Generate a new Id so that unloaded materials that reference this collection will update correctly on load
StateId = FGuid::NewGuid();
// Update the uniform buffer layout
CreateBufferStruct();
// Recreate each instance of this collection
for (TObjectIterator<UWorld> It; It; ++It)
{
UWorld* CurrentWorld = *It;
CurrentWorld->AddParameterCollectionInstance(this, false);
}
// Build set of changed parameter names
TSet<FName> ParameterNames;
for (const FCollectionVectorParameter& Param : PreviousVectorParameters)
{
ParameterNames.Add(Param.ParameterName);
}
for (const FCollectionScalarParameter& Param : PreviousScalarParameters)
{
ParameterNames.Add(Param.ParameterName);
}
for (const FCollectionVectorParameter& Param : VectorParameters)
{
ParameterNames.Remove(Param.ParameterName);
}
for (const FCollectionScalarParameter& Param : ScalarParameters)
{
ParameterNames.Remove(Param.ParameterName);
}
// Create a material update context so we can safely update materials using this parameter collection.
{
FMaterialUpdateContext UpdateContext;
// Go through all materials in memory and recompile them if they use this material parameter collection
for (TObjectIterator<UMaterial> It; It; ++It)
{
UMaterial* CurrentMaterial = *It;
bool bRecompile = false;
// Preview materials often use expressions for rendering that are not in their Expressions array,
// And therefore their MaterialParameterCollectionInfos are not up to date.
if (CurrentMaterial->bIsPreviewMaterial)
{
bRecompile = true;
}
else
{
for (int32 FunctionIndex = 0; FunctionIndex < CurrentMaterial->MaterialParameterCollectionInfos.Num() && !bRecompile; FunctionIndex++)
{
if (CurrentMaterial->MaterialParameterCollectionInfos[FunctionIndex].ParameterCollection == this)
{
TArray<UMaterialExpressionCollectionParameter*> CollectionParameters;
CurrentMaterial->GetAllExpressionsInMaterialAndFunctionsOfType(CollectionParameters);
for (UMaterialExpressionCollectionParameter* CollectionParameter : CollectionParameters)
{
if (ParameterNames.Contains(CollectionParameter->ParameterName))
{
bRecompile = true;
break;
}
}
}
}
}
if (bRecompile)
{
UpdateContext.AddMaterial(CurrentMaterial);
// Propagate the change to this material
CurrentMaterial->PreEditChange(NULL);
//.........这里部分代码省略.........
示例5: ConfigureEnabledPlugins
bool FPluginManager::ConfigureEnabledPlugins()
{
if(!bHaveConfiguredEnabledPlugins)
{
// Don't need to run this again
bHaveConfiguredEnabledPlugins = true;
// If a current project is set, check that we know about any plugin that's explicitly enabled
const FProjectDescriptor *Project = IProjectManager::Get().GetCurrentProject();
const bool bHasProjectFile = Project != nullptr;
// Get all the enabled plugin names
TArray< FString > EnabledPluginNames;
#if IS_PROGRAM
// Programs can also define the list of enabled plugins in ini
GConfig->GetArray(TEXT("Plugins"), TEXT("ProgramEnabledPlugins"), EnabledPluginNames, GEngineIni);
#endif
#if !IS_PROGRAM || HACK_HEADER_GENERATOR
if (!FParse::Param(FCommandLine::Get(), TEXT("NoEnginePlugins")))
{
FProjectManager::Get().GetEnabledPlugins(EnabledPluginNames);
}
#endif
// Build a set from the array
TSet< FString > AllEnabledPlugins;
AllEnabledPlugins.Append(MoveTemp(EnabledPluginNames));
// Enable all the plugins by name
for (const TSharedRef< FPlugin > Plugin : AllPlugins)
{
if (AllEnabledPlugins.Contains(Plugin->Name))
{
Plugin->bEnabled = (!IS_PROGRAM || !bHasProjectFile) || IsPluginSupportedByCurrentTarget(Plugin);
if (!Plugin->bEnabled)
{
AllEnabledPlugins.Remove(Plugin->Name);
}
}
}
if (bHasProjectFile)
{
// Take a copy of the Project's plugins as we may remove some
TArray<FPluginReferenceDescriptor> PluginsCopy = Project->Plugins;
for(const FPluginReferenceDescriptor& Plugin: PluginsCopy)
{
if ((Plugin.bEnabled && !FindPluginInstance(Plugin.Name).IsValid()) &&
(!IS_PROGRAM || AllEnabledPlugins.Contains(Plugin.Name))) // skip if this is a program and the plugin is not enabled
{
FText Caption(LOCTEXT("PluginMissingCaption", "Plugin missing"));
if(Plugin.MarketplaceURL.Len() > 0)
{
if(FMessageDialog::Open(EAppMsgType::YesNo, FText::Format(LOCTEXT("PluginMissingError", "This project requires the {0} plugin.\n\nWould you like to download it from the the Marketplace?"), FText::FromString(Plugin.Name)), &Caption) == EAppReturnType::Yes)
{
FString Error;
FPlatformProcess::LaunchURL(*Plugin.MarketplaceURL, nullptr, &Error);
if(Error.Len() > 0) FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(Error));
return false;
}
}
else
{
FString Description = (Plugin.Description.Len() > 0) ? FString::Printf(TEXT("\n\n%s"), *Plugin.Description) : FString();
FMessageDialog::Open(EAppMsgType::Ok, FText::Format(LOCTEXT("PluginRequiredError", "This project requires the {0} plugin. {1}"), FText::FromString(Plugin.Name), FText::FromString(Description)), &Caption);
if (FMessageDialog::Open(EAppMsgType::YesNo, FText::Format(LOCTEXT("PluginMissingDisable", "Would you like to disable {0}? You will no longer be able to open any assets created using it."), FText::FromString(Plugin.Name)), &Caption) == EAppReturnType::No)
{
return false;
}
FText FailReason;
if (!IProjectManager::Get().SetPluginEnabled(*Plugin.Name, false, FailReason))
{
FMessageDialog::Open(EAppMsgType::Ok, FailReason);
}
}
}
}
}
// If we made it here, we have all the required plugins
bHaveAllRequiredPlugins = true;
for(const TSharedRef<FPlugin>& Plugin: AllPlugins)
{
if (Plugin->bEnabled)
{
// Add the plugin binaries directory
const FString PluginBinariesPath = FPaths::Combine(*FPaths::GetPath(Plugin->FileName), TEXT("Binaries"), FPlatformProcess::GetBinariesSubdirectory());
FModuleManager::Get().AddBinariesDirectory(*PluginBinariesPath, Plugin->LoadedFrom == EPluginLoadedFrom::GameProject);
#if !IS_MONOLITHIC
// Only check this when in a non-monolithic build where modules could be in separate binaries
if (Project != NULL && Project->Modules.Num() == 0)
{
// Content only project - check whether any plugins are incompatible and offer to disable instead of trying to build them later
TArray<FString> IncompatibleFiles;
if (!FModuleDescriptor::CheckModuleCompatibility(Plugin->Descriptor.Modules, Plugin->LoadedFrom == EPluginLoadedFrom::GameProject, IncompatibleFiles))
{
//.........这里部分代码省略.........
示例6: EditorAutomatedBuildAndSubmit
bool FEditorBuildUtils::EditorAutomatedBuildAndSubmit( const FEditorAutomatedBuildSettings& BuildSettings, FText& OutErrorMessages )
{
// Assume the build is successful to start
bool bBuildSuccessful = true;
// Keep a set of packages that should be submitted to source control at the end of a successful build. The build preparation and processing
// will add and remove from the set depending on build settings, errors, etc.
TSet<UPackage*> PackagesToSubmit;
// Perform required preparations for the automated build process
bBuildSuccessful = PrepForAutomatedBuild( BuildSettings, PackagesToSubmit, OutErrorMessages );
// If the preparation went smoothly, attempt the actual map building process
if ( bBuildSuccessful )
{
bBuildSuccessful = EditorBuild( GWorld, EBuildOptions::BuildAllSubmit );
// If the map build failed, log the error
if ( !bBuildSuccessful )
{
LogErrorMessage( NSLOCTEXT("UnrealEd", "AutomatedBuild_Error_BuildFailed", "The map build failed or was canceled."), OutErrorMessages );
}
}
// If any map errors resulted from the build, process them according to the behavior specified in the build settings
if ( bBuildSuccessful && FMessageLog("MapCheck").NumMessages( EMessageSeverity::Warning ) > 0 )
{
bBuildSuccessful = ProcessAutomatedBuildBehavior( BuildSettings.BuildErrorBehavior, NSLOCTEXT("UnrealEd", "AutomatedBuild_Error_MapErrors", "Map errors occurred while building.\n\nAttempt to continue the build?"), OutErrorMessages );
}
// If it's still safe to proceed, attempt to save all of the level packages that have been marked for submission
if ( bBuildSuccessful )
{
UPackage* CurOutermostPkg = GWorld->PersistentLevel->GetOutermost();
FString PackagesThatFailedToSave;
// Try to save the p-level if it should be submitted
if ( PackagesToSubmit.Contains( CurOutermostPkg ) && !FEditorFileUtils::SaveLevel( GWorld->PersistentLevel ) )
{
// If the p-level failed to save, remove it from the set of packages to submit
PackagesThatFailedToSave += FString::Printf( TEXT("%s\n"), *CurOutermostPkg->GetName() );
PackagesToSubmit.Remove( CurOutermostPkg );
}
// Try to save each streaming level (if they should be submitted)
for ( TArray<ULevelStreaming*>::TIterator LevelIter( GWorld->StreamingLevels ); LevelIter; ++LevelIter )
{
ULevelStreaming* CurStreamingLevel = *LevelIter;
if ( CurStreamingLevel != NULL )
{
ULevel* Level = CurStreamingLevel->GetLoadedLevel();
if ( Level != NULL )
{
CurOutermostPkg = Level->GetOutermost();
if ( PackagesToSubmit.Contains( CurOutermostPkg ) && !FEditorFileUtils::SaveLevel( Level ) )
{
// If a save failed, remove the streaming level from the set of packages to submit
PackagesThatFailedToSave += FString::Printf( TEXT("%s\n"), *CurOutermostPkg->GetName() );
PackagesToSubmit.Remove( CurOutermostPkg );
}
}
}
}
// If any packages failed to save, process the behavior specified by the build settings to see how the process should proceed
if ( PackagesThatFailedToSave.Len() > 0 )
{
bBuildSuccessful = ProcessAutomatedBuildBehavior( BuildSettings.FailedToSaveBehavior,
FText::Format( NSLOCTEXT("UnrealEd", "AutomatedBuild_Error_FilesFailedSave", "The following assets failed to save and cannot be submitted:\n\n{0}\n\nAttempt to continue the build?"), FText::FromString(PackagesThatFailedToSave) ),
OutErrorMessages );
}
}
// If still safe to proceed, make sure there are actually packages remaining to submit
if ( bBuildSuccessful )
{
bBuildSuccessful = PackagesToSubmit.Num() > 0;
if ( !bBuildSuccessful )
{
LogErrorMessage( NSLOCTEXT("UnrealEd", "AutomatedBuild_Error_NoValidLevels", "None of the current levels are valid for submission; automated build aborted."), OutErrorMessages );
}
}
// Finally, if everything has gone smoothly, submit the requested packages to source control
if ( bBuildSuccessful )
{
SubmitPackagesForAutomatedBuild( PackagesToSubmit, BuildSettings );
}
// Check if the user requested the editor shutdown at the conclusion of the automated build
if ( BuildSettings.bShutdownEditorOnCompletion )
{
FPlatformMisc::RequestExit( false );
}
return bBuildSuccessful;
}
示例7: PrepForAutomatedBuild
//.........这里部分代码省略.........
bBuildSuccessful = ProcessAutomatedBuildBehavior( BuildSettings.NewMapBehavior,
FText::Format( NSLOCTEXT("UnrealEd", "AutomatedBuild_Error_UnsavedMap", "The following levels have never been saved before and cannot be submitted:\n\n{0}\n\nAttempt to continue the build?"), FText::FromString(UnsavedWorlds) ),
OutErrorMessages );
}
}
// Load the asset tools module
FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools");
if ( bBuildSuccessful )
{
// Update the source control status of any relevant world packages in order to determine which need to be
// checked out, added to the depot, etc.
SourceControlProvider.Execute( ISourceControlOperation::Create<FUpdateStatus>(), SourceControlHelpers::PackageFilenames(PreviouslySavedWorldPackages) );
FString PkgsThatCantBeCheckedOut;
for ( TArray<UPackage*>::TConstIterator PkgIter( PreviouslySavedWorldPackages ); PkgIter; ++PkgIter )
{
UPackage* CurPackage = *PkgIter;
const FString CurPkgName = CurPackage->GetName();
FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(CurPackage, EStateCacheUsage::ForceUpdate);
if( !SourceControlState.IsValid() ||
(!SourceControlState->IsSourceControlled() &&
!SourceControlState->IsUnknown() &&
!SourceControlState->IsIgnored()))
{
FString CurFilename;
if ( FPackageName::DoesPackageExist( CurPkgName, NULL, &CurFilename ) )
{
if ( IFileManager::Get().IsReadOnly( *CurFilename ) )
{
PkgsThatCantBeCheckedOut += FString::Printf( TEXT("%s\n"), *CurPkgName );
OutPkgsToSubmit.Remove( CurPackage );
}
}
}
else if(SourceControlState->CanCheckout())
{
PackagesToCheckout.Add( CurPackage );
}
else
{
PkgsThatCantBeCheckedOut += FString::Printf( TEXT("%s\n"), *CurPkgName );
OutPkgsToSubmit.Remove( CurPackage );
}
}
// If any of the packages can't be checked out or are read-only, process the build setting's behavior to see if the build
// should proceed or not
if ( PkgsThatCantBeCheckedOut.Len() > 0 )
{
bBuildSuccessful = ProcessAutomatedBuildBehavior( BuildSettings.UnableToCheckoutFilesBehavior,
FText::Format( NSLOCTEXT("UnrealEd", "AutomatedBuild_Error_UnsaveableFiles", "The following assets cannot be checked out of source control (or are read-only) and cannot be submitted:\n\n{0}\n\nAttempt to continue the build?"), FText::FromString(PkgsThatCantBeCheckedOut) ),
OutErrorMessages );
}
}
if ( bBuildSuccessful )
{
// Check out all of the packages from source control that need to be checked out
if ( PackagesToCheckout.Num() > 0 )
{
TArray<FString> PackageFilenames = SourceControlHelpers::PackageFilenames(PackagesToCheckout);
SourceControlProvider.Execute( ISourceControlOperation::Create<FCheckOut>(), PackageFilenames );
示例8: CheckTextureStreamingBuild
void CheckTextureStreamingBuild(ULevel* InLevel)
{
#if WITH_EDITORONLY_DATA
if (!InLevel) return;
int32 NumTextureStreamingUnbuiltComponents = 0;
TSet<FGuid> BuildGuilds;
for (const FGuid& Guid : InLevel->TextureStreamingBuildGuids)
{
BuildGuilds.Add(Guid);
}
TArray<UPrimitiveComponent*> Components;
GetTextureStreamingPrimitives(InLevel, Components);
for (UPrimitiveComponent* Primitive : Components)
{
//@todo : Non transactional primitives, like the one created from blueprints, fail to save/load their built data.
const bool bHasMissingData = !!(Primitive->GetFlags() & RF_Transactional) && !Primitive->HasStreamingTextureData();
TArray<UTexture*> Textures;
TArray<UMaterialInterface*> Materials;
Primitive->GetUsedMaterials(Materials);
for (const UMaterialInterface* MaterialInterface : Materials)
{
if (MaterialInterface)
{
TArray<FGuid> MaterialGuids;
MaterialInterface->GetLightingGuidChain(false, MaterialGuids);
for (const FGuid& MaterialGuid : MaterialGuids)
{
BuildGuilds.Remove(MaterialGuid);
}
// If there is no data, then we will have to parse the texture to check whether there are streaming textures there.
if (bHasMissingData)
{
MaterialInterface->GetUsedTextures(Textures, EMaterialQualityLevel::Num, false, GMaxRHIFeatureLevel, false);
}
}
}
// If there is no data, check that the material actually uses streaming textures before marking the Texture Streaming Build invalid.
if (bHasMissingData && Textures.Num() > 0)
{
for (UTexture* Texture : Textures)
{
if (IsStreamingTexture(Cast<UTexture2D>(Texture)))
{
++NumTextureStreamingUnbuiltComponents;
break;
}
}
}
const UStaticMeshComponent* StaticMeshComponent = Cast<UStaticMeshComponent>(Primitive);
if (StaticMeshComponent && StaticMeshComponent->StaticMesh)
{
BuildGuilds.Remove(StaticMeshComponent->StaticMesh->GetLightingGuid());
}
}
// All guids must have been found, otherwise, it means the resource changed.
if (NumTextureStreamingUnbuiltComponents != InLevel->NumTextureStreamingUnbuiltComponents || BuildGuilds.Num() != InLevel->NumTextureStreamingDirtyResources)
{
InLevel->NumTextureStreamingUnbuiltComponents = NumTextureStreamingUnbuiltComponents;
InLevel->NumTextureStreamingDirtyResources = BuildGuilds.Num();
// Don't mark package dirty as we avoid marking package dirty unless user changes something.
// InLevel->MarkPackageDirty();
}
#endif
}
示例9: UpdateHitBoxCandidates
void AHUD::UpdateHitBoxCandidates( TArray<FVector2D> InContactPoints )
{
HitBoxHits.Reset();
for (FHUDHitBox& HitBox : HitBoxMap)
{
bool bAdded = false;
for (int32 ContactPointIndex = InContactPoints.Num() - 1; ContactPointIndex >= 0; --ContactPointIndex)
{
if (HitBox.Contains(InContactPoints[ContactPointIndex]))
{
if (!bAdded)
{
HitBoxHits.Add(&HitBox);
bAdded = true;
}
if (HitBox.ConsumesInput())
{
InContactPoints.RemoveAtSwap(ContactPointIndex);
}
else
{
break;
}
}
}
if (InContactPoints.Num() == 0)
{
break;
}
}
TSet<FName> NotOverHitBoxes = HitBoxesOver;
TArray<FName> NewlyOverHitBoxes;
// Now figure out which boxes we are over and deal with begin/end cursor over messages
for (FHUDHitBox* HitBox : HitBoxHits)
{
const FName HitBoxName = HitBox->GetName();
if (HitBoxesOver.Contains(HitBoxName))
{
NotOverHitBoxes.Remove(HitBoxName);
}
else
{
NewlyOverHitBoxes.AddUnique(HitBoxName);
}
}
// Dispatch the end cursor over messages
for (const FName HitBoxName : NotOverHitBoxes)
{
NotifyHitBoxEndCursorOver(HitBoxName);
HitBoxesOver.Remove(HitBoxName);
}
// Dispatch the newly over hitbox messages
for (const FName HitBoxName : NewlyOverHitBoxes)
{
NotifyHitBoxBeginCursorOver(HitBoxName);
HitBoxesOver.Add(HitBoxName);
}
}