本文整理汇总了C++中TSet::Add方法的典型用法代码示例。如果您正苦于以下问题:C++ TSet::Add方法的具体用法?C++ TSet::Add怎么用?C++ TSet::Add使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类TSet
的用法示例。
在下文中一共展示了TSet::Add方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: CompactInstanceBaseCache
void FFoliageInstanceBaseCache::CompactInstanceBaseCache(AInstancedFoliageActor* IFA)
{
UWorld* World = IFA->GetWorld();
if (!World || World->IsGameWorld())
{
return;
}
FFoliageInstanceBaseCache& Cache = IFA->InstanceBaseCache;
TSet<FFoliageInstanceBaseId> BasesInUse;
for (auto& Pair : IFA->FoliageMeshes)
{
for (const auto& Pair : Pair.Value->ComponentHash)
{
if (Pair.Key != FFoliageInstanceBaseCache::InvalidBaseId)
{
BasesInUse.Add(Pair.Key);
}
}
}
// Look for any removed maps
TSet<FFoliageInstanceBasePtr> InvalidBasePtrs;
for (auto& Pair : Cache.InstanceBaseLevelMap)
{
const auto& WorldAsset = Pair.Key;
bool bExists = (WorldAsset == World);
// Check sub-levels
if (!bExists)
{
const FName PackageName = FName(*FPackageName::ObjectPathToPackageName(WorldAsset.ToStringReference().ToString()));
if (World->WorldComposition)
{
bExists = World->WorldComposition->DoesTileExists(PackageName);
}
else
{
bExists = (World->GetLevelStreamingForPackageName(PackageName) != nullptr);
}
}
if (!bExists)
{
InvalidBasePtrs.Append(Pair.Value);
Cache.InstanceBaseLevelMap.Remove(Pair.Key);
}
else
{
// Remove dead links
for (int32 i = Pair.Value.Num()-1; i >= 0; --i)
{
// Base needs to be removed if it's not in use by existing instances or component was removed
if (Pair.Value[i].IsNull() || !BasesInUse.Contains(Cache.GetInstanceBaseId(Pair.Value[i])))
{
InvalidBasePtrs.Add(Pair.Value[i]);
Pair.Value.RemoveAt(i);
}
}
if (Pair.Value.Num() == 0)
{
Cache.InstanceBaseLevelMap.Remove(Pair.Key);
}
}
}
TSet<FFoliageInstanceBaseId> InvalidBaseIds;
Cache.InstanceBaseInvMap.Empty();
// Look for any removed base components
for (const auto& Pair : Cache.InstanceBaseMap)
{
const FFoliageInstanceBaseInfo& BaseInfo = Pair.Value;
if (InvalidBasePtrs.Contains(BaseInfo.BasePtr))
{
InvalidBaseIds.Add(Pair.Key);
Cache.InstanceBaseMap.Remove(Pair.Key);
}
else
{
// Regenerate inverse map
check(!Cache.InstanceBaseInvMap.Contains(BaseInfo.BasePtr));
Cache.InstanceBaseInvMap.Add(BaseInfo.BasePtr, Pair.Key);
}
}
if (InvalidBaseIds.Num())
{
for (auto& Pair : IFA->FoliageMeshes)
{
auto& MeshInfo = Pair.Value;
MeshInfo->ComponentHash.Empty();
int32 InstanceIdx = 0;
for (FFoliageInstance& Instance : MeshInfo->Instances)
{
if (InvalidBaseIds.Contains(Instance.BaseId))
{
Instance.BaseId = FFoliageInstanceBaseCache::InvalidBaseId;
//.........这里部分代码省略.........
示例2: GetParentTree
TOptional<EItemDropZone> FSequencerFolderNode::CanDrop( FSequencerDisplayNodeDragDropOp& DragDropOp, EItemDropZone ItemDropZone ) const
{
DragDropOp.ResetToDefaultToolTip();
if ( ItemDropZone == EItemDropZone::AboveItem )
{
if ( GetParent().IsValid() )
{
// When dropping above, only allow it for root level nodes.
return TOptional<EItemDropZone>();
}
else
{
// Make sure there are no folder name collisions with the root folders
UMovieScene* FocusedMovieScene = GetParentTree().GetSequencer().GetFocusedMovieSceneSequence()->GetMovieScene();
TSet<FName> RootFolderNames;
for ( UMovieSceneFolder* RootFolder : FocusedMovieScene->GetRootFolders() )
{
RootFolderNames.Add( RootFolder->GetFolderName() );
}
for ( TSharedRef<FSequencerDisplayNode> DraggedNode : DragDropOp.GetDraggedNodes() )
{
if ( DraggedNode->GetType() == ESequencerNode::Folder )
{
TSharedRef<FSequencerFolderNode> DraggedFolder = StaticCastSharedRef<FSequencerFolderNode>( DraggedNode );
if ( RootFolderNames.Contains( DraggedFolder->GetFolder().GetFolderName() ) )
{
DragDropOp.CurrentHoverText = FText::Format(
NSLOCTEXT( "SeqeuencerFolderNode", "DuplicateRootFolderDragErrorFormat", "Root folder with name '{0}' already exists." ),
FText::FromName( DraggedFolder->GetFolder().GetFolderName() ) );
return TOptional<EItemDropZone>();
}
}
}
}
return TOptional<EItemDropZone>( EItemDropZone::AboveItem );
}
else
{
// When dropping onto, don't allow dropping into the same folder, don't allow dropping
// parents into children, and don't allow duplicate folder names.
TSet<FName> ChildFolderNames;
for ( UMovieSceneFolder* ChildFolder : GetFolder().GetChildFolders() )
{
ChildFolderNames.Add( ChildFolder->GetFolderName() );
}
for ( TSharedRef<FSequencerDisplayNode> DraggedNode : DragDropOp.GetDraggedNodes() )
{
TSharedPtr<FSequencerDisplayNode> ParentSeqNode = DraggedNode->GetParent();
if ( ParentSeqNode.IsValid() && ParentSeqNode.Get() == this )
{
DragDropOp.CurrentHoverText = NSLOCTEXT( "SeqeuencerFolderNode", "SameParentDragError", "Can't drag a node onto the same parent." );
return TOptional<EItemDropZone>();
}
if ( DraggedNode->GetType() == ESequencerNode::Folder )
{
TSharedRef<FSequencerFolderNode> DraggedFolder = StaticCastSharedRef<FSequencerFolderNode>( DraggedNode );
if ( ChildFolderNames.Contains( DraggedFolder->GetFolder().GetFolderName() ) )
{
DragDropOp.CurrentHoverText = FText::Format(
NSLOCTEXT( "SeqeuencerFolderNode", "DuplicateChildFolderDragErrorFormat", "Folder with name '{0}' already exists." ),
FText::FromName( DraggedFolder->GetFolder().GetFolderName() ) );
return TOptional<EItemDropZone>();
}
}
}
TSharedPtr<FSequencerDisplayNode> CurrentNode = SharedThis( ( FSequencerDisplayNode* )this );
while ( CurrentNode.IsValid() )
{
if ( DragDropOp.GetDraggedNodes().Contains( CurrentNode ) )
{
DragDropOp.CurrentHoverText = NSLOCTEXT( "SeqeuencerFolderNode", "ParentIntoChildDragError", "Can't drag a parent node into one of it's children." );
return TOptional<EItemDropZone>();
}
CurrentNode = CurrentNode->GetParent();
}
return TOptional<EItemDropZone>( EItemDropZone::OntoItem );
}
}
示例3: if
void UK2Node::AutowireNewNode(UEdGraphPin* FromPin)
{
const UEdGraphSchema_K2* K2Schema = CastChecked<UEdGraphSchema_K2>(GetSchema());
// Do some auto-connection
if (FromPin != NULL)
{
TSet<UEdGraphNode*> NodeList;
// sometimes we don't always find an ideal connection, but we want to exhaust
// all our options first... this stores a secondary less-ideal pin to connect to, if nothing better was found
UEdGraphPin* BackupConnection = NULL;
// If not dragging an exec pin, auto-connect from dragged pin to first compatible pin on the new node
for (int32 i=0; i<Pins.Num(); i++)
{
UEdGraphPin* Pin = Pins[i];
check(Pin);
ECanCreateConnectionResponse ConnectResponse = K2Schema->CanCreateConnection(FromPin, Pin).Response;
if (ConnectResponse == ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE)
{
if (K2Schema->TryCreateConnection(FromPin, Pin))
{
NodeList.Add(FromPin->GetOwningNode());
NodeList.Add(this);
}
// null out the backup connection (so we don't attempt to make it
// once we exit the loop... we successfully made this connection!)
BackupConnection = NULL;
break;
}
else if((FromPin->PinType.PinCategory == K2Schema->PC_Exec) && (ConnectResponse == ECanCreateConnectionResponse::CONNECT_RESPONSE_BREAK_OTHERS_A))
{
InsertNewNode(FromPin, Pin, NodeList);
// null out the backup connection (so we don't attempt to make it
// once we exit the loop... we successfully made this connection!)
BackupConnection = NULL;
break;
}
else if ((BackupConnection == NULL) && (ConnectResponse == ECanCreateConnectionResponse::CONNECT_RESPONSE_MAKE_WITH_CONVERSION_NODE))
{
// save this off, in-case we don't make any connection at all
BackupConnection = Pin;
}
}
// if we didn't find an ideal connection, then lets connect this pin to
// the BackupConnection (something, like a connection that requires a conversion node, etc.)
if ((BackupConnection != NULL) && K2Schema->TryCreateConnection(FromPin, BackupConnection))
{
NodeList.Add(FromPin->GetOwningNode());
NodeList.Add(this);
}
// If we were not dragging an exec pin, but it was an output pin, try and connect the Then and Execute pins
if ((FromPin->PinType.PinCategory != K2Schema->PC_Exec && FromPin->Direction == EGPD_Output))
{
UEdGraphNode* FromPinNode = FromPin->GetOwningNode();
UEdGraphPin* FromThenPin = FromPinNode->FindPin(K2Schema->PN_Then);
UEdGraphPin* ToExecutePin = FindPin(K2Schema->PN_Execute);
if ((FromThenPin != NULL) && (FromThenPin->LinkedTo.Num() == 0) && (ToExecutePin != NULL) && K2Schema->ArePinsCompatible(FromThenPin, ToExecutePin, NULL))
{
if (K2Schema->TryCreateConnection(FromThenPin, ToExecutePin))
{
NodeList.Add(FromPinNode);
NodeList.Add(this);
}
}
}
// Send all nodes that received a new pin connection a notification
for (auto It = NodeList.CreateConstIterator(); It; ++It)
{
UEdGraphNode* Node = (*It);
Node->NodeConnectionListChanged();
}
}
}
示例4: Run
uint32 FAssetDataDiscovery::Run()
{
double DiscoverStartTime = FPlatformTime::Seconds();
int32 NumDiscoveredFiles = 0;
FString LocalFilenamePathToPrioritize;
TSet<FString> LocalDiscoveredPathsSet;
TArray<FString> LocalDiscoveredDirectories;
TArray<FDiscoveredPackageFile> LocalPriorityFilesToSearch;
TArray<FDiscoveredPackageFile> LocalNonPriorityFilesToSearch;
// This set contains the folders that we should hide by default unless they contain assets
TSet<FString> PathsToHideIfEmpty;
PathsToHideIfEmpty.Add(TEXT("/Game/Collections"));
auto FlushLocalResultsIfRequired = [&]()
{
if (LocalPriorityFilesToSearch.Num() > 0 || LocalNonPriorityFilesToSearch.Num() > 0 || LocalDiscoveredPathsSet.Num() > 0)
{
TArray<FString> LocalDiscoveredPathsArray = LocalDiscoveredPathsSet.Array();
{
FScopeLock CritSectionLock(&WorkerThreadCriticalSection);
// Place all the discovered files into the files to search list
DiscoveredPaths.Append(MoveTemp(LocalDiscoveredPathsArray));
PriorityDiscoveredFiles.Append(MoveTemp(LocalPriorityFilesToSearch));
NonPriorityDiscoveredFiles.Append(MoveTemp(LocalNonPriorityFilesToSearch));
}
}
LocalDiscoveredPathsSet.Reset();
LocalPriorityFilesToSearch.Reset();
LocalNonPriorityFilesToSearch.Reset();
};
auto IsPriorityFile = [&](const FString& InPackageFilename) -> bool
{
return !bIsSynchronous && !LocalFilenamePathToPrioritize.IsEmpty() && InPackageFilename.StartsWith(LocalFilenamePathToPrioritize);
};
auto OnIterateDirectoryItem = [&](const TCHAR* InPackageFilename, const FFileStatData& InPackageStatData) -> bool
{
if (StopTaskCounter.GetValue() != 0)
{
// Requested to stop - break out of the directory iteration
return false;
}
const FString PackageFilenameStr = InPackageFilename;
if (InPackageStatData.bIsDirectory)
{
LocalDiscoveredDirectories.Add(PackageFilenameStr / TEXT(""));
FString PackagePath;
if (FPackageName::TryConvertFilenameToLongPackageName(PackageFilenameStr, PackagePath) && !PathsToHideIfEmpty.Contains(PackagePath))
{
LocalDiscoveredPathsSet.Add(PackagePath);
}
}
else if (FPackageName::IsPackageFilename(PackageFilenameStr))
{
if (IsValidPackageFileToRead(PackageFilenameStr))
{
const FString LongPackageNameStr = FPackageName::FilenameToLongPackageName(PackageFilenameStr);
if (IsPriorityFile(PackageFilenameStr))
{
LocalPriorityFilesToSearch.Add(FDiscoveredPackageFile(PackageFilenameStr, InPackageStatData.ModificationTime));
}
else
{
LocalNonPriorityFilesToSearch.Add(FDiscoveredPackageFile(PackageFilenameStr, InPackageStatData.ModificationTime));
}
LocalDiscoveredPathsSet.Add(FPackageName::GetLongPackagePath(LongPackageNameStr));
++NumDiscoveredFiles;
// Flush the data if we've processed enough
if (!bIsSynchronous && (LocalPriorityFilesToSearch.Num() + LocalNonPriorityFilesToSearch.Num()) >= AssetDataGathererConstants::MaxFilesToDiscoverBeforeFlush)
{
FlushLocalResultsIfRequired();
}
}
}
return true;
};
bool bIsIdle = true;
while (StopTaskCounter.GetValue() == 0)
{
FString LocalDirectoryToSearch;
//.........这里部分代码省略.........
示例5: if
void UK2Node_Composite::PostPasteNode()
{
Super::PostPasteNode();
//@TODO: Should verify that each node in the composite can be pasted into this new graph successfully (CanPasteHere)
if (BoundGraph != NULL)
{
UEdGraph* ParentGraph = CastChecked<UEdGraph>(GetOuter());
ensure(BoundGraph != ParentGraph);
// Update the InputSinkNode / OutputSourceNode pointers to point to the new graph
TSet<UEdGraphNode*> BoundaryNodes;
for (int32 NodeIndex = 0; NodeIndex < BoundGraph->Nodes.Num(); ++NodeIndex)
{
UEdGraphNode* Node = BoundGraph->Nodes[NodeIndex];
//Remove this node if it should not exist more then one in blueprint
if(UK2Node_Event* Event = Cast<UK2Node_Event>(Node))
{
UBlueprint* BP = FBlueprintEditorUtils::FindBlueprintForGraphChecked(BoundGraph);
if(FBlueprintEditorUtils::FindOverrideForFunction(BP, Event->EventReference.GetMemberParentClass(Event->GetBlueprintClassFromNode()), Event->EventReference.GetMemberName()))
{
FBlueprintEditorUtils::RemoveNode(BP, Node, true);
NodeIndex--;
continue;
}
}
BoundaryNodes.Add(Node);
if (Node->GetClass() == UK2Node_Tunnel::StaticClass())
{
// Exactly a tunnel node, should be the entrance or exit node
UK2Node_Tunnel* Tunnel = CastChecked<UK2Node_Tunnel>(Node);
if (Tunnel->bCanHaveInputs && !Tunnel->bCanHaveOutputs)
{
OutputSourceNode = Tunnel;
Tunnel->InputSinkNode = this;
}
else if (Tunnel->bCanHaveOutputs && !Tunnel->bCanHaveInputs)
{
InputSinkNode = Tunnel;
Tunnel->OutputSourceNode = this;
}
else
{
ensureMsgf(false, *LOCTEXT("UnexpectedTunnelNode", "Unexpected tunnel node '%s' in cloned graph '%s' (both I/O or neither)").ToString(), *Tunnel->GetName(), *GetName());
}
}
}
RenameBoundGraphCloseToName(BoundGraph->GetName());
ensure(BoundGraph->SubGraphs.Find(ParentGraph) == INDEX_NONE);
//Nested composites will already be in the SubGraph array
if(ParentGraph->SubGraphs.Find(BoundGraph) == INDEX_NONE)
{
ParentGraph->SubGraphs.Add(BoundGraph);
}
FEdGraphUtilities::PostProcessPastedNodes(BoundaryNodes);
}
}
示例6: BuildManifest
//.........这里部分代码省略.........
int64 FileDataLeft = (FileBuilder.FileSpan.StartIdx + FileBuilder.FileSpan.Size) - FileBuilder.CurrentDataPos;
int64 ChunkDataLeft = (ChunkPart.DataOffset + ChunkPart.PartSize) - FileBuilder.CurrentDataPos;
check(FileDataLeft > 0);
check(ChunkDataLeft > 0);
if (ChunkDataLeft >= FileDataLeft)
{
FileBuilder.CurrentDataPos += FileDataLeft;
FileChunkPartData.Size = FileDataLeft;
}
else
{
FileBuilder.CurrentDataPos += ChunkDataLeft;
FileChunkPartData.Size = ChunkDataLeft;
}
FileDataLeft = (FileBuilder.FileSpan.StartIdx + FileBuilder.FileSpan.Size) - FileBuilder.CurrentDataPos;
ChunkDataLeft = (ChunkPart.DataOffset + ChunkPart.PartSize) - FileBuilder.CurrentDataPos;
check(FileDataLeft == 0 || ChunkDataLeft == 0);
// End of file?
if (FileDataLeft == 0)
{
// Fill out rest of data??
FFileSpan FileSpan;
bool FoundFile = BuildStreamer->GetFileSpan(FileBuilder.FileSpan.StartIdx, FileSpan);
check(FoundFile); // Incorrect positional tracking
check(FileSpan.Filename == FileBuilder.FileManifest->Filename);
FMemory::Memcpy(FileBuilder.FileManifest->FileHash.Hash, FileSpan.SHAHash.Hash, FSHA1::DigestSize);
FFileAttributes Attributes = FileAttributesMap.FindRef(FileSpan.Filename);
FileBuilder.FileManifest->bIsUnixExecutable = Attributes.bUnixExecutable || FileSpan.IsUnixExecutable;
FileBuilder.FileManifest->SymlinkTarget = FileSpan.SymlinkTarget;
FileBuilder.FileManifest->bIsReadOnly = Attributes.bReadOnly;
FileBuilder.FileManifest->bIsCompressed = Attributes.bCompressed;
FileBuilder.FileManifest->InstallTags = Attributes.InstallTags.Array();
FileBuilder.FileManifest->Init();
check(FileBuilder.FileManifest->GetFileSize() == FileBuilder.FileSpan.Size);
FileBuilder.FileManifest = nullptr;
}
else if (ChunkDataLeft == 0)
{
FileBuilder.FileManifest->FileChunkParts.Emplace();
}
// Continue with this chunk?
if (ChunkDataLeft > 0)
{
--idx;
}
}
}
else
{
if (EndOfData)
{
Running = false;
}
else
{
CheckForWork->Wait();
CheckForWork->Reset();
}
}
}
// Fill out chunk list from only chunks that remain referenced
TSet<FGuid> ReferencedChunks;
for (const auto& FileManifest : Manifest->Data->FileManifestList)
{
for (const auto& ChunkPart : FileManifest.FileChunkParts)
{
if (ReferencedChunks.Contains(ChunkPart.Guid) == false)
{
auto& ChunkInfo = ChunkInfoLookup[ChunkPart.Guid];
ReferencedChunks.Add(ChunkPart.Guid);
Manifest->Data->ChunkList.Emplace();
auto& ChunkInfoData = Manifest->Data->ChunkList.Last();
ChunkInfoData.Guid = ChunkPart.Guid;
ChunkInfoData.Hash = ChunkInfo.Hash;
FMemory::Memcpy(ChunkInfoData.ShaHash.Hash, ChunkInfo.ShaHash.Hash, FSHA1::DigestSize);
ChunkInfoData.FileSize = ChunkInfo.ChunkFileSize;
ChunkInfoData.GroupNumber = FCrc::MemCrc32(&ChunkPart.Guid, sizeof(FGuid)) % 100;
}
}
}
// Get empty files
FSHA1 EmptyHasher;
EmptyHasher.Final();
const TArray< FString >& EmptyFileList = BuildStreamer->GetEmptyFiles();
for (const auto& EmptyFile : EmptyFileList)
{
Manifest->Data->FileManifestList.Emplace();
FFileManifestData& EmptyFileManifest = Manifest->Data->FileManifestList.Last();
EmptyFileManifest.Filename = EmptyFile;
EmptyHasher.GetHash(EmptyFileManifest.FileHash.Hash);
}
// Fill out lookups
Manifest->InitLookups();
}
示例7: HandleAddTrackSubMenuNew
void FSequencerObjectBindingNode::HandleAddTrackSubMenuNew(FMenuBuilder& AddTrackMenuBuilder, TArray<TArray<UProperty*> > KeyablePropertyPaths)
{
// [PostProcessSettings] [Bloom1Tint] [X]
// [PostProcessSettings] [Bloom1Tint] [Y]
// [PostProcessSettings] [ColorGrading]
// Create property menu data based on keyable property paths
TSet<UProperty*> PropertiesTraversed;
TArray<PropertyMenuData> KeyablePropertyMenuData;
for (auto KeyablePropertyPath : KeyablePropertyPaths)
{
PropertyMenuData KeyableMenuData;
KeyableMenuData.PropertyPath = KeyablePropertyPath;
// If the path is greater than 1, keep track of the actual properties (not channels) and only add these properties once since we can't do single channel keying of a property yet.
if (KeyablePropertyPath.Num() > 1) //@todo
{
if (PropertiesTraversed.Find(KeyablePropertyPath[1]) != nullptr)
{
continue;
}
KeyableMenuData.MenuName = FObjectEditorUtils::GetCategoryFName(KeyablePropertyPath[1]).ToString();
PropertiesTraversed.Add(KeyablePropertyPath[1]);
}
else
{
// No sub menus items, so skip
continue;
}
KeyablePropertyMenuData.Add(KeyableMenuData);
}
// Sort on the menu name
KeyablePropertyMenuData.Sort([](const PropertyMenuData& A, const PropertyMenuData& B)
{
int32 CompareResult = A.MenuName.Compare(B.MenuName);
return CompareResult < 0;
});
// Add menu items
for (int32 MenuDataIndex = 0; MenuDataIndex < KeyablePropertyMenuData.Num(); )
{
TArray<TArray<UProperty*> > KeyableSubMenuPropertyPaths;
KeyableSubMenuPropertyPaths.Add(KeyablePropertyMenuData[MenuDataIndex].PropertyPath);
for (; MenuDataIndex < KeyablePropertyMenuData.Num()-1; )
{
if (KeyablePropertyMenuData[MenuDataIndex].MenuName == KeyablePropertyMenuData[MenuDataIndex+1].MenuName)
{
++MenuDataIndex;
KeyableSubMenuPropertyPaths.Add(KeyablePropertyMenuData[MenuDataIndex].PropertyPath);
}
else
{
break;
}
}
const int32 PropertyNameIndexStart = 1; // Strip off the struct property name
const int32 PropertyNameIndexEnd = 2; // Stop at the property name, don't descend into the channels
AddTrackMenuBuilder.AddSubMenu(
FText::FromString(KeyablePropertyMenuData[MenuDataIndex].MenuName),
FText::GetEmpty(),
FNewMenuDelegate::CreateSP(this, &FSequencerObjectBindingNode::AddPropertyMenuItems, KeyableSubMenuPropertyPaths, PropertyNameIndexStart, PropertyNameIndexEnd));
++MenuDataIndex;
}
}
示例8: SpawnMissingNodes
void UEnvironmentQueryGraph::SpawnMissingNodes()
{
UEnvQuery* QueryOwner = Cast<UEnvQuery>(GetOuter());
if (QueryOwner == nullptr)
{
return;
}
TSet<UEnvQueryTest*> ExistingTests;
TSet<UEnvQueryOption*> ExistingNodes;
TArray<UEnvQueryOption*> OptionsCopy = QueryOwner->GetOptions();
UAIGraphNode* MyRootNode = nullptr;
for (int32 Idx = 0; Idx < Nodes.Num(); Idx++)
{
UEnvironmentQueryGraphNode* MyNode = Cast<UEnvironmentQueryGraphNode>(Nodes[Idx]);
UEnvQueryOption* OptionInstance = MyNode ? Cast<UEnvQueryOption>(MyNode->NodeInstance) : nullptr;
if (OptionInstance && OptionInstance->Generator)
{
ExistingNodes.Add(OptionInstance);
ExistingTests.Empty(ExistingTests.Num());
for (int32 SubIdx = 0; SubIdx < MyNode->SubNodes.Num(); SubIdx++)
{
UEnvironmentQueryGraphNode* MySubNode = Cast<UEnvironmentQueryGraphNode>(MyNode->SubNodes[SubIdx]);
UEnvQueryTest* TestInstance = MySubNode ? Cast<UEnvQueryTest>(MySubNode->NodeInstance) : nullptr;
if (TestInstance)
{
ExistingTests.Add(TestInstance);
}
else
{
MyNode->RemoveSubNode(MySubNode);
SubIdx--;
}
}
SpawnMissingSubNodes(OptionInstance, ExistingTests, MyNode);
}
UEnvironmentQueryGraphNode_Root* RootNode = Cast<UEnvironmentQueryGraphNode_Root>(Nodes[Idx]);
if (RootNode)
{
MyRootNode = RootNode;
}
}
UEdGraphPin* RootOutPin = MyRootNode ? FindGraphNodePin(MyRootNode, EGPD_Output) : nullptr;
ExistingTests.Empty(0);
for (int32 Idx = 0; Idx < OptionsCopy.Num(); Idx++)
{
UEnvQueryOption* OptionInstance = OptionsCopy[Idx];
if (ExistingNodes.Contains(OptionInstance) || OptionInstance == nullptr || OptionInstance->Generator == nullptr)
{
continue;
}
FGraphNodeCreator<UEnvironmentQueryGraphNode_Option> NodeBuilder(*this);
UEnvironmentQueryGraphNode_Option* MyNode = NodeBuilder.CreateNode();
UAIGraphNode::UpdateNodeClassDataFrom(OptionInstance->Generator->GetClass(), MyNode->ClassData);
MyNode->ErrorMessage = MyNode->ClassData.GetDeprecatedMessage();
NodeBuilder.Finalize();
if (MyRootNode)
{
MyNode->NodePosX = MyRootNode->NodePosX + (Idx * 300);
MyNode->NodePosY = MyRootNode->NodePosY + 100;
}
MyNode->NodeInstance = OptionInstance;
SpawnMissingSubNodes(OptionInstance, ExistingTests, MyNode);
UEdGraphPin* SpawnedInPin = FindGraphNodePin(MyNode, EGPD_Input);
if (RootOutPin && SpawnedInPin)
{
RootOutPin->MakeLinkTo(SpawnedInPin);
}
}
}
示例9: SerializeCDOProperties
void FHotReloadClassReinstancer::SerializeCDOProperties(UObject* InObject, FHotReloadClassReinstancer::FCDOPropertyData& OutData)
{
// Creates a mem-comparable CDO data
class FCDOWriter : public FMemoryWriter
{
/** Objects already visited by this archive */
TSet<UObject*>& VisitedObjects;
/** Output property data */
FCDOPropertyData& PropertyData;
/** Current subobject being serialized */
FName SubobjectName;
public:
/** Serializes all script properties of the provided DefaultObject */
FCDOWriter(FCDOPropertyData& InOutData, UObject* DefaultObject, TSet<UObject*>& InVisitedObjects, FName InSubobjectName = NAME_None)
: FMemoryWriter(InOutData.Bytes, /* bIsPersistent = */ false, /* bSetOffset = */ true)
, VisitedObjects(InVisitedObjects)
, PropertyData(InOutData)
, SubobjectName(InSubobjectName)
{
// Disable delta serialization, we want to serialize everything
ArNoDelta = true;
DefaultObject->SerializeScriptProperties(*this);
}
virtual void Serialize(void* Data, int64 Num) override
{
// Collect serialized properties so we can later update their values on instances if they change
auto SerializedProperty = GetSerializedProperty();
if (SerializedProperty != nullptr)
{
FCDOProperty& PropertyInfo = PropertyData.Properties.FindOrAdd(SerializedProperty->GetFName());
if (PropertyInfo.Property == nullptr)
{
PropertyInfo.Property = SerializedProperty;
PropertyInfo.SubobjectName = SubobjectName;
PropertyInfo.SerializedValueOffset = Tell();
PropertyInfo.SerializedValueSize = Num;
PropertyData.Properties.Add(SerializedProperty->GetFName(), PropertyInfo);
}
else
{
PropertyInfo.SerializedValueSize += Num;
}
}
FMemoryWriter::Serialize(Data, Num);
}
/** Serializes an object. Only name and class for normal references, deep serialization for DSOs */
virtual FArchive& operator<<(class UObject*& InObj) override
{
FArchive& Ar = *this;
if (InObj)
{
FName ClassName = InObj->GetClass()->GetFName();
FName ObjectName = InObj->GetFName();
Ar << ClassName;
Ar << ObjectName;
if (!VisitedObjects.Contains(InObj))
{
VisitedObjects.Add(InObj);
if (Ar.GetSerializedProperty() && Ar.GetSerializedProperty()->ContainsInstancedObjectProperty())
{
// Serialize all DSO properties too
FCDOWriter DefaultSubobjectWriter(PropertyData, InObj, VisitedObjects, InObj->GetFName());
Seek(PropertyData.Bytes.Num());
}
}
}
else
{
FName UnusedName = NAME_None;
Ar << UnusedName;
Ar << UnusedName;
}
return *this;
}
/** Serializes an FName as its index and number */
virtual FArchive& operator<<(FName& InName) override
{
FArchive& Ar = *this;
NAME_INDEX ComparisonIndex = InName.GetComparisonIndex();
NAME_INDEX DisplayIndex = InName.GetDisplayIndex();
int32 Number = InName.GetNumber();
Ar << ComparisonIndex;
Ar << DisplayIndex;
Ar << Number;
return Ar;
}
virtual FArchive& operator<<(FLazyObjectPtr& LazyObjectPtr) override
{
FArchive& Ar = *this;
auto UniqueID = LazyObjectPtr.GetUniqueID();
Ar << UniqueID;
return *this;
}
virtual FArchive& operator<<(FAssetPtr& AssetPtr) override
{
FArchive& Ar = *this;
auto UniqueID = AssetPtr.GetUniqueID();
Ar << UniqueID;
//.........这里部分代码省略.........
示例10: Add
/** Add a new statistic to the internal map (or update an existing one) from the supplied component */
UPrimitiveStats* Add(UPrimitiveComponent* InPrimitiveComponent, EPrimitiveObjectSets InObjectSet)
{
// Objects in transient package or transient objects are not part of level.
if( InPrimitiveComponent->GetOutermost() == GetTransientPackage() || InPrimitiveComponent->HasAnyFlags( RF_Transient ) )
{
return NULL;
}
// Owned by a default object? Not part of a level either.
if(InPrimitiveComponent->GetOuter() && InPrimitiveComponent->GetOuter()->IsDefaultSubobject() )
{
return NULL;
}
UStaticMeshComponent* StaticMeshComponent = Cast<UStaticMeshComponent>(InPrimitiveComponent);
UModelComponent* ModelComponent = Cast<UModelComponent>(InPrimitiveComponent);
USkeletalMeshComponent* SkeletalMeshComponent = Cast<USkeletalMeshComponent>(InPrimitiveComponent);
ULandscapeComponent* LandscapeComponent = Cast<ULandscapeComponent>(InPrimitiveComponent);
UObject* Resource = NULL;
AActor* ActorOuter = Cast<AActor>(InPrimitiveComponent->GetOuter());
int32 VertexColorMem = 0;
int32 InstVertexColorMem = 0;
// Calculate number of direct and other lights relevant to this component.
int32 LightsLMCount = 0;
int32 LightsOtherCount = 0;
bool bUsesOnlyUnlitMaterials = InPrimitiveComponent->UsesOnlyUnlitMaterials();
// The static mesh is a static mesh component's resource.
if( StaticMeshComponent )
{
UStaticMesh* Mesh = StaticMeshComponent->StaticMesh;
Resource = Mesh;
// Calculate vertex color memory on the actual mesh.
if( Mesh && Mesh->RenderData )
{
// Accumulate memory for each LOD
for( int32 LODIndex = 0; LODIndex < Mesh->RenderData->LODResources.Num(); ++LODIndex )
{
VertexColorMem += Mesh->RenderData->LODResources[LODIndex].ColorVertexBuffer.GetAllocatedSize();
}
}
// Calculate instanced vertex color memory used on the component.
for( int32 LODIndex = 0; LODIndex < StaticMeshComponent->LODData.Num(); ++LODIndex )
{
// Accumulate memory for each LOD
const FStaticMeshComponentLODInfo& LODInfo = StaticMeshComponent->LODData[ LODIndex ];
if( LODInfo.OverrideVertexColors )
{
InstVertexColorMem += LODInfo.OverrideVertexColors->GetAllocatedSize();
}
}
// Calculate the number of lightmap and shadow map lights
if( !bUsesOnlyUnlitMaterials )
{
if( StaticMeshComponent->LODData.Num() > 0 )
{
FStaticMeshComponentLODInfo& ComponentLODInfo = StaticMeshComponent->LODData[0];
if( ComponentLODInfo.LightMap )
{
LightsLMCount = ComponentLODInfo.LightMap->LightGuids.Num();
}
}
}
}
// A model component is its own resource.
else if( ModelComponent )
{
// Make sure model component is referenced by level.
ULevel* Level = CastChecked<ULevel>(ModelComponent->GetOuter());
if( Level->ModelComponents.Find( ModelComponent ) != INDEX_NONE )
{
Resource = ModelComponent->GetModel();
// Calculate the number of lightmap and shadow map lights
if( !bUsesOnlyUnlitMaterials )
{
const TIndirectArray<FModelElement> Elements = ModelComponent->GetElements();
if( Elements.Num() > 0 )
{
if( Elements[0].LightMap )
{
LightsLMCount = Elements[0].LightMap->LightGuids.Num();
}
}
}
}
}
// The skeletal mesh of a skeletal mesh component is its resource.
else if( SkeletalMeshComponent )
{
USkeletalMesh* Mesh = SkeletalMeshComponent->SkeletalMesh;
Resource = Mesh;
// Calculate vertex color usage for skeletal meshes
if( Mesh )
{
FSkeletalMeshResource* SkelMeshResource = Mesh->GetResourceForRendering();
//.........这里部分代码省略.........
示例11: EShadowMapFlags
FShadowMap2D* FShadowMap2D::AllocateInstancedShadowMap(UInstancedStaticMeshComponent* Component, TArray<TMap<ULightComponent*, TUniquePtr<FShadowMapData2D>>> InstancedShadowMapData,
const FBoxSphereBounds& Bounds, ELightMapPaddingType InPaddingType, EShadowMapFlags InShadowmapFlags)
{
#if WITH_EDITOR
check(InstancedShadowMapData.Num() > 0);
// Verify all instance shadowmaps are the same size, and build complete list of shadow lights
int32 SizeX = -1;
int32 SizeY = -1;
TSet<ULightComponent*> AllLights;
for (auto& ShadowMapData : InstancedShadowMapData)
{
for (const auto& ShadowDataPair : ShadowMapData)
{
if (SizeX == -1)
{
SizeX = ShadowDataPair.Value->GetSizeX();
SizeY = ShadowDataPair.Value->GetSizeY();
}
else
{
check(ShadowDataPair.Value->GetSizeX() == SizeX);
check(ShadowDataPair.Value->GetSizeY() == SizeY);
}
AllLights.Add(ShadowDataPair.Key);
}
}
check(SizeX != -1 && SizeY != -1); // No valid shadowmaps
TArray<FGuid> LightGuids;
LightGuids.Reserve(AllLights.Num());
for (ULightComponent* Light : AllLights)
{
LightGuids.Add(Light->LightGuid);
}
// Unify all the shadow map data to contain the same lights in the same order
for (auto& ShadowMapData : InstancedShadowMapData)
{
for (ULightComponent* Light : AllLights)
{
if (!ShadowMapData.Contains(Light))
{
ShadowMapData.Add(Light, MakeUnique<FQuantizedShadowSignedDistanceFieldData2D>(SizeX, SizeY));
}
}
}
FShadowMapAllocationGroup AllocationGroup;
AllocationGroup.TextureOuter = Component->GetOutermost();
AllocationGroup.ShadowmapFlags = InShadowmapFlags;
AllocationGroup.Bounds = Bounds;
if (!GAllowStreamingLightmaps)
{
AllocationGroup.ShadowmapFlags = EShadowMapFlags(AllocationGroup.ShadowmapFlags & ~SMF_Streamed);
}
FShadowMap2D* BaseShadowmap = nullptr;
for (int32 InstanceIndex = 0; InstanceIndex < InstancedShadowMapData.Num(); ++InstanceIndex)
{
auto& ShadowMapData = InstancedShadowMapData[InstanceIndex];
check(ShadowMapData.Num() > 0);
// Create a new shadow-map.
FShadowMap2D* ShadowMap = new FShadowMap2D(LightGuids);
if (InstanceIndex == 0)
{
BaseShadowmap = ShadowMap;
}
// Add a pending allocation for this shadow-map.
TUniquePtr<FShadowMapAllocation> Allocation = MakeUnique<FShadowMapAllocation>();
Allocation->PaddingType = InPaddingType;
Allocation->ShadowMap = ShadowMap;
Allocation->TotalSizeX = SizeX;
Allocation->TotalSizeY = SizeY;
Allocation->MappedRect = FIntRect(0, 0, SizeX, SizeY);
Allocation->Primitive = Component;
Allocation->InstanceIndex = InstanceIndex;
for (auto& ShadowDataPair : ShadowMapData)
{
auto& RawData = ShadowDataPair.Value;
auto& DistanceFieldShadowData = Allocation->ShadowMapData.Add(ShadowDataPair.Key, TArray<FQuantizedSignedDistanceFieldShadowSample>());
switch (RawData->GetType())
{
case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA:
case FShadowMapData2D::SHADOW_SIGNED_DISTANCE_FIELD_DATA_QUANTIZED:
// If the data is already quantized, this will just copy the data
RawData->Quantize(DistanceFieldShadowData);
break;
default:
check(0);
}
RawData.Reset();
//.........这里部分代码省略.........
示例12: 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);
//.........这里部分代码省略.........
示例13: SaveCookedPackageAssetRegistry
// cooked package asset registry saves information about all the cooked packages and assets contained within for stats purposes
// in json format
bool FChunkManifestGenerator::SaveCookedPackageAssetRegistry( const FString& SandboxCookedRegistryFilename, const bool Append )
{
bool bSuccess = false;
for ( const auto& Platform : Platforms )
{
TSet<FName> CookedPackages;
// save the file
const FString CookedAssetRegistryFilename = SandboxCookedRegistryFilename.Replace(TEXT("[Platform]"), *Platform->PlatformName());
FString JsonOutString;
JsonWriter Json = TJsonWriterFactory<TCHAR, TPrettyJsonPrintPolicy<TCHAR> >::Create(&JsonOutString);
Json->WriteObjectStart();
Json->WriteArrayStart(TEXT("Packages"));
for ( const auto& Package : AllCookedPackages )
{
Json->WriteObjectStart(); // unnamed package start
const FName& PackageName = Package.Key;
const FString& SandboxPath = Package.Value;
CookedPackages.Add( PackageName );
FString PlatformSandboxPath = SandboxPath.Replace(TEXT("[Platform]"), *Platform->PlatformName());
FDateTime TimeStamp = IFileManager::Get().GetTimeStamp( *PlatformSandboxPath );
Json->WriteValue( "SourcePackageName", PackageName.ToString() );
Json->WriteValue( "CookedPackageName", PlatformSandboxPath );
Json->WriteValue( "CookedPackageTimeStamp", TimeStamp.ToString() );
Json->WriteArrayStart("AssetData");
for (const auto& AssetData : AssetRegistryData)
{ // Add only assets that have actually been cooked and belong to any chunk
if (AssetData.ChunkIDs.Num() > 0 && (AssetData.PackageName == PackageName))
{
Json->WriteObjectStart();
// save all their infos
Json->WriteValue(TEXT("ObjectPath"), AssetData.ObjectPath.ToString() );
Json->WriteValue(TEXT("PackageName"), AssetData.PackageName.ToString() );
Json->WriteValue(TEXT("PackagePath"), AssetData.PackagePath.ToString() );
Json->WriteValue(TEXT("GroupNames"), AssetData.GroupNames.ToString() );
Json->WriteValue(TEXT("AssetName"), AssetData.AssetName.ToString() );
Json->WriteValue(TEXT("AssetClass"), AssetData.AssetClass.ToString() );
Json->WriteObjectStart("TagsAndValues");
for ( const auto& Tag : AssetData.TagsAndValues )
{
Json->WriteValue( Tag.Key.ToString(), Tag.Value );
}
Json->WriteObjectEnd(); // end tags and values object
Json->WriteObjectEnd(); // end unnamed array object
}
}
Json->WriteArrayEnd();
Json->WriteObjectEnd(); // unnamed package
}
if ( Append )
{
FString JsonInString;
if ( FFileHelper::LoadFileToString(JsonInString, *CookedAssetRegistryFilename) )
{
// load up previous package asset registry and fill in any packages which weren't recooked on this run
JsonReader Reader = TJsonReaderFactory<TCHAR>::Create(JsonInString);
TSharedPtr<FJsonObject> JsonObject;
bool shouldRead = FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid() && JsonObject->HasTypedField<EJson::Array>(TEXT("Packages"));
if ( shouldRead )
{
TArray<TSharedPtr<FJsonValue>> PackageList = JsonObject->GetArrayField(TEXT("Packages"));
for (auto PackageListIt = PackageList.CreateConstIterator(); PackageListIt && shouldRead; ++PackageListIt)
{
const TSharedPtr<FJsonValue>& JsonValue = *PackageListIt;
shouldRead = JsonValue->Type == EJson::Object;
if ( shouldRead )
{
const TSharedPtr<FJsonObject>& JsonPackage = JsonValue->AsObject();
// get the package name and see if we have already written it out this run
FString CookedPackageName;
verify( JsonPackage->TryGetStringField(TEXT("SourcePackageName"), CookedPackageName) );
const FName CookedPackageFName(*CookedPackageName);
if ( CookedPackages.Contains(CookedPackageFName))
{
// don't need to process this package
continue;
}
// check that the on disk version is still valid
FString SourcePackageName;
check( JsonPackage->TryGetStringField( TEXT("SourcePackageName"), SourcePackageName) );
// if our timestamp is different then don't copy the information over
FDateTime CurrentTimeStamp = IFileManager::Get().GetTimeStamp( *CookedPackageName );
//.........这里部分代码省略.........
示例14: PostEditChangeProperty
void UTexture::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
SetLightingGuid();
// Determine whether any property that requires recompression of the texture, or notification to Materials has changed.
bool RequiresNotifyMaterials = false;
bool DeferCompressionWasEnabled = false;
UProperty* PropertyThatChanged = PropertyChangedEvent.Property;
if( PropertyThatChanged )
{
static const FName CompressionSettingsName("CompressionSettings");
static const FName LODGroupName("LODGroup");
static const FName DeferCompressionName("DeferCompression");
#if WITH_EDITORONLY_DATA
static const FName MaxTextureSizeName("MaxTextureSize");
#endif // #if WITH_EDITORONLY_DATA
const FName PropertyName = PropertyThatChanged->GetFName();
if (PropertyName == CompressionSettingsName || PropertyName == LODGroupName)
{
RequiresNotifyMaterials = true;
}
else if (PropertyName == DeferCompressionName)
{
DeferCompressionWasEnabled = DeferCompression;
}
#if WITH_EDITORONLY_DATA
else if (PropertyName == MaxTextureSizeName)
{
if (MaxTextureSize <= 0)
{
MaxTextureSize = 0;
}
else
{
MaxTextureSize = FMath::Min<int32>(FMath::RoundUpToPowerOfTwo(MaxTextureSize), GetMaximumDimension());
}
}
#endif // #if WITH_EDITORONLY_DATA
bool bPreventSRGB = (CompressionSettings == TC_Alpha || CompressionSettings == TC_Normalmap || CompressionSettings == TC_Masks || CompressionSettings == TC_HDR || CompressionSettings == TC_HDR_Compressed);
if(bPreventSRGB && SRGB == true)
{
SRGB = false;
}
}
else
{
FMaterialUpdateContext UpdateContext;
// Update any material that uses this texture
TSet<UMaterial*> BaseMaterialsThatUseThisTexture;
for (TObjectIterator<UMaterialInterface> It; It; ++It)
{
UMaterialInterface* MaterialInterface = *It;
if (DoesMaterialUseTexture(MaterialInterface, this))
{
UMaterial *Material = MaterialInterface->GetMaterial();
bool MaterialAlreadyCompute = false;
BaseMaterialsThatUseThisTexture.Add(Material, &MaterialAlreadyCompute);
if (!MaterialAlreadyCompute)
{
UpdateContext.AddMaterial(Material);
if (Material->IsTextureForceRecompileCacheRessource(this))
{
Material->UpdateMaterialShaderCacheAndTextureReferences();
}
}
}
}
//If the DDC key was different the material is already recompile here
RequiresNotifyMaterials = false;
}
NumCinematicMipLevels = FMath::Max<int32>( NumCinematicMipLevels, 0 );
// Don't update the texture resource if we've turned "DeferCompression" on, as this
// would cause it to immediately update as an uncompressed texture
if( !DeferCompressionWasEnabled && (PropertyChangedEvent.ChangeType & EPropertyChangeType::Interactive) == 0 )
{
// Update the texture resource. This will recache derived data if necessary
// which may involve recompressing the texture.
UpdateResource();
}
// Notify any loaded material instances if changed our compression format
if (RequiresNotifyMaterials)
{
TArray<UMaterialInterface*> MaterialsThatUseThisTexture;
// Create a material update context to safely update materials.
{
FMaterialUpdateContext UpdateContext;
// Notify any material that uses this texture
TSet<UMaterial*> BaseMaterialsThatUseThisTexture;
for (TObjectIterator<UMaterialInterface> It; It; ++It)
{
//.........这里部分代码省略.........
示例15: DeserializeFromJSON
// @TODO LSwift: Perhaps replace FromBlob and ToBlob usage with hexadecimal notation instead
bool FBuildPatchAppManifest::DeserializeFromJSON( const FString& JSONInput )
{
bool bSuccess = true;
TSharedPtr<FJsonObject> JSONManifestObject;
TSharedRef<TJsonReader<TCHAR>> Reader = TJsonReaderFactory<TCHAR>::Create(JSONInput);
// Clear current data
DestroyData();
// Attempt to deserialize JSON
if (!FJsonSerializer::Deserialize(Reader, JSONManifestObject) || !JSONManifestObject.IsValid())
{
return false;
}
// Store a list of all data GUID for later use
TSet<FGuid> AllDataGuids;
// Get the values map
TMap<FString, TSharedPtr<FJsonValue>>& JsonValueMap = JSONManifestObject->Values;
// Manifest version did not always exist
int32 ManifestFileVersionInt = 0;
TSharedPtr<FJsonValue> JsonManifestFileVersion = JsonValueMap.FindRef(TEXT("ManifestFileVersion"));
if (JsonManifestFileVersion.IsValid() && FromStringBlob(JsonManifestFileVersion->AsString(), ManifestFileVersionInt))
{
Data->ManifestFileVersion = static_cast<EBuildPatchAppManifestVersion::Type>(ManifestFileVersionInt);
}
else
{
// Then we presume version just before we started outputting the version
Data->ManifestFileVersion = static_cast<EBuildPatchAppManifestVersion::Type>(EBuildPatchAppManifestVersion::StartStoringVersion - 1);
}
// Get the app and version strings
TSharedPtr< FJsonValue > JsonAppID = JsonValueMap.FindRef( TEXT("AppID") );
TSharedPtr< FJsonValue > JsonAppNameString = JsonValueMap.FindRef( TEXT("AppNameString") );
TSharedPtr< FJsonValue > JsonBuildVersionString = JsonValueMap.FindRef( TEXT("BuildVersionString") );
TSharedPtr< FJsonValue > JsonLaunchExe = JsonValueMap.FindRef( TEXT("LaunchExeString") );
TSharedPtr< FJsonValue > JsonLaunchCommand = JsonValueMap.FindRef( TEXT("LaunchCommand") );
TSharedPtr< FJsonValue > JsonPrereqName = JsonValueMap.FindRef( TEXT("PrereqName") );
TSharedPtr< FJsonValue > JsonPrereqPath = JsonValueMap.FindRef( TEXT("PrereqPath") );
TSharedPtr< FJsonValue > JsonPrereqArgs = JsonValueMap.FindRef( TEXT("PrereqArgs") );
bSuccess = bSuccess && JsonAppID.IsValid();
if( bSuccess )
{
bSuccess = bSuccess && FromStringBlob( JsonAppID->AsString(), Data->AppID );
}
bSuccess = bSuccess && JsonAppNameString.IsValid();
if( bSuccess )
{
Data->AppName = JsonAppNameString->AsString();
}
bSuccess = bSuccess && JsonBuildVersionString.IsValid();
if( bSuccess )
{
Data->BuildVersion = JsonBuildVersionString->AsString();
}
bSuccess = bSuccess && JsonLaunchExe.IsValid();
if( bSuccess )
{
Data->LaunchExe = JsonLaunchExe->AsString();
}
bSuccess = bSuccess && JsonLaunchCommand.IsValid();
if( bSuccess )
{
Data->LaunchCommand = JsonLaunchCommand->AsString();
}
// Get the prerequisites installer info. These are optional entries.
Data->PrereqName = JsonPrereqName.IsValid() ? JsonPrereqName->AsString() : FString();
Data->PrereqPath = JsonPrereqPath.IsValid() ? JsonPrereqPath->AsString() : FString();
Data->PrereqArgs = JsonPrereqArgs.IsValid() ? JsonPrereqArgs->AsString() : FString();
// Get the FileManifestList
TSharedPtr<FJsonValue> JsonFileManifestList = JsonValueMap.FindRef(TEXT("FileManifestList"));
bSuccess = bSuccess && JsonFileManifestList.IsValid();
if( bSuccess )
{
TArray<TSharedPtr<FJsonValue>> JsonFileManifestArray = JsonFileManifestList->AsArray();
for (auto JsonFileManifestIt = JsonFileManifestArray.CreateConstIterator(); JsonFileManifestIt && bSuccess; ++JsonFileManifestIt)
{
TSharedPtr<FJsonObject> JsonFileManifest = (*JsonFileManifestIt)->AsObject();
const int32 FileIndex = Data->FileManifestList.Add(FFileManifestData());
FFileManifestData& FileManifest = Data->FileManifestList[FileIndex];
FileManifest.Filename = JsonFileManifest->GetStringField(TEXT("Filename"));
bSuccess = bSuccess && FString::ToBlob(JsonFileManifest->GetStringField(TEXT("FileHash")), FileManifest.FileHash.Hash, FSHA1::DigestSize);
TArray<TSharedPtr<FJsonValue>> JsonChunkPartArray = JsonFileManifest->GetArrayField(TEXT("FileChunkParts"));
for (auto JsonChunkPartIt = JsonChunkPartArray.CreateConstIterator(); JsonChunkPartIt && bSuccess; ++JsonChunkPartIt)
{
const int32 ChunkIndex = FileManifest.FileChunkParts.Add(FChunkPartData());
FChunkPartData& FileChunkPart = FileManifest.FileChunkParts[ChunkIndex];
TSharedPtr<FJsonObject> JsonChunkPart = (*JsonChunkPartIt)->AsObject();
bSuccess = bSuccess && FGuid::Parse(JsonChunkPart->GetStringField(TEXT("Guid")), FileChunkPart.Guid);
bSuccess = bSuccess && FromStringBlob(JsonChunkPart->GetStringField(TEXT("Offset")), FileChunkPart.Offset);
bSuccess = bSuccess && FromStringBlob(JsonChunkPart->GetStringField(TEXT("Size")), FileChunkPart.Size);
AllDataGuids.Add(FileChunkPart.Guid);
}
//.........这里部分代码省略.........