예제 #1
0
void UUnrealEdEngine::GetPackageList( TArray<UPackage*>* InPackages, UClass* InClass )
{
	InPackages->Empty();

	for( FObjectIterator It ; It ; ++It )
	{
		if( It->GetOuter() && It->GetOuter() != GetTransientPackage() )
		{
			UObject* TopParent = NULL;

			if( InClass == NULL || It->IsA( InClass ) )
				TopParent = It->GetOutermost();

			if( Cast<UPackage>(TopParent) )
				InPackages->AddUnique( (UPackage*)TopParent );
		}
	}
}
예제 #2
0
void FEnumEditorUtils::BroadcastChanges(const UUserDefinedEnum* Enum, const TArray<TPair<FName, int8>>& OldNames, bool bResolveData)
{
	check(NULL != Enum);
	if (bResolveData)
	{
		FArchiveEnumeratorResolver EnumeratorResolver(Enum, OldNames);

		TArray<UClass*> ClassesToCheck;
		for (TObjectIterator<UByteProperty> PropertyIter; PropertyIter; ++PropertyIter)
		{
			const UByteProperty* ByteProperty = *PropertyIter;
			if (ByteProperty && (Enum == ByteProperty->GetIntPropertyEnum()))
			{
				UClass* OwnerClass = ByteProperty->GetOwnerClass();
				if (OwnerClass)
				{
					ClassesToCheck.Add(OwnerClass);
				}
			}
		}

		for (FObjectIterator ObjIter; ObjIter; ++ObjIter)
		{
			for (auto ClassIter = ClassesToCheck.CreateConstIterator(); ClassIter; ++ClassIter)
			{
				if (ObjIter->IsA(*ClassIter))
				{
					ObjIter->Serialize(EnumeratorResolver);
					break;
				}
			}
		}
	}

	struct FNodeValidatorHelper
	{
		static bool IsValid(UK2Node* Node)
		{
			return Node
				&& (NULL != Cast<UEdGraph>(Node->GetOuter()))
				&& !Node->HasAnyFlags(RF_Transient | RF_PendingKill);
		}
	};

	TSet<UBlueprint*> BlueprintsToRefresh;

	{
		//CUSTOM NODES DEPENTENT ON ENUM

		for (TObjectIterator<UK2Node> It(RF_Transient); It; ++It)
		{
			UK2Node* Node = *It;
			INodeDependingOnEnumInterface* NodeDependingOnEnum = Cast<INodeDependingOnEnumInterface>(Node);
			if (FNodeValidatorHelper::IsValid(Node) && NodeDependingOnEnum && (Enum == NodeDependingOnEnum->GetEnum()))
			{
				if (UBlueprint* Blueprint = Node->GetBlueprint())
				{
					if (NodeDependingOnEnum->ShouldBeReconstructedAfterEnumChanged())
					{
						Node->ReconstructNode();
					}
					BlueprintsToRefresh.Add(Blueprint);
				}
			}
		}
	}

	for (TObjectIterator<UEdGraphPin> It(RF_Transient); It; ++It)
	{
		UEdGraphPin* Pin = *It;
		if (Pin && (Enum == Pin->PinType.PinSubCategoryObject.Get()) && (EEdGraphPinDirection::EGPD_Input == Pin->Direction))
		{
			UK2Node* Node = Cast<UK2Node>(Pin->GetOuter());
			if (FNodeValidatorHelper::IsValid(Node))
			{
				if (UBlueprint* Blueprint = Node->GetBlueprint())
				{
					if (INDEX_NONE == Enum->FindEnumIndex(*Pin->DefaultValue))
					{
						Pin->Modify();
						if (Blueprint->BlueprintType == BPTYPE_Interface)
						{
							Pin->DefaultValue = Enum->GetEnumName(0);
						}
						else
						{
							Pin->DefaultValue = FEnumEditorUtilsHelper::InvalidName();
						}
						Node->PinDefaultValueChanged(Pin);
						BlueprintsToRefresh.Add(Blueprint);
					}
				}
			}
		}
	}

	for (auto It = BlueprintsToRefresh.CreateIterator(); It; ++It)
	{
		FBlueprintEditorUtils::MarkBlueprintAsModified(*It);
		(*It)->BroadcastChanged();
	}

	FEnumEditorManager::Get().PostChange(Enum, EEnumEditorChangeInfo::Changed);
}
bool UOnlineHotfixManager::HotfixIniFile(const FString& FileName, const FString& IniData)
{
	FConfigFile* ConfigFile = GetConfigFile(FileName);
	// Merge the string into the config file
	ConfigFile->CombineFromBuffer(IniData);
	TArray<UClass*> Classes;
	TArray<UObject*> PerObjectConfigObjects;
	int32 StartIndex = 0;
	int32 EndIndex = 0;
	// Find the set of object classes that were affected
	while (StartIndex >= 0 && StartIndex < IniData.Len() && EndIndex >= StartIndex)
	{
		// Find the next section header
		StartIndex = IniData.Find(TEXT("["), ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex);
		if (StartIndex > -1)
		{
			// Find the ending section identifier
			EndIndex = IniData.Find(TEXT("]"), ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex);
			if (EndIndex > StartIndex)
			{
				int32 PerObjectNameIndex = IniData.Find(TEXT(" "), ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex);
				// Per object config entries will have a space in the name, but classes won't
				if (PerObjectNameIndex == -1 || PerObjectNameIndex > EndIndex)
				{
					if (IniData.StartsWith(TEXT("[/Script/"), ESearchCase::IgnoreCase))
					{
						const int32 ScriptSectionTag = 9;
						// Snip the text out and try to find the class for that
						const FString PackageClassName = IniData.Mid(StartIndex + ScriptSectionTag, EndIndex - StartIndex - ScriptSectionTag);
						// Find the class for this so we know what to update
						UClass* Class = FindObject<UClass>(nullptr, *PackageClassName, true);
						if (Class)
						{
							// Add this to the list to check against
							Classes.Add(Class);
						}
					}
				}
				// Handle the per object config case by finding the object for reload
				else
				{
					const int32 Count = PerObjectNameIndex - StartIndex - 1;
					const FString PerObjectName = IniData.Mid(StartIndex + 1, Count);
					// Explicitly search the transient package (won't update non-transient objects)
					UObject* PerObject = FindObject<UObject>(ANY_PACKAGE, *PerObjectName, false);
					if (PerObject != nullptr)
					{
						PerObjectConfigObjects.Add(PerObject);
					}
				}
				StartIndex = EndIndex;
			}
		}
	}

	int32 NumObjectsReloaded = 0;
	const double StartTime = FPlatformTime::Seconds();
	if (Classes.Num())
	{
		// Now that we have a list of classes to update, we can iterate objects and reload
		for (FObjectIterator It; It; ++It)
		{
			UClass* Class = It->GetClass();
			if (Class->HasAnyClassFlags(CLASS_Config))
			{
				// Check to see if this class is in our list (yes, potentially n^2, but not in practice)
				for (int32 ClassIndex = 0; ClassIndex < Classes.Num(); ClassIndex++)
				{
					if (It->IsA(Classes[ClassIndex]))
					{
						// Force a reload of the config vars
						It->ReloadConfig();
						NumObjectsReloaded++;
						break;
					}
				}
			}
		}
	}
	// Reload any PerObjectConfig objects that were affected
	for (auto ReloadObject : PerObjectConfigObjects)
	{
		ReloadObject->ReloadConfig();
		NumObjectsReloaded++;
	}
	UE_LOG(LogHotfixManager, Log, TEXT("Updating config from %s took %f seconds and reloaded %d objects"),
		*FileName, FPlatformTime::Seconds() - StartTime, NumObjectsReloaded);
	return true;
}