You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Copying //UE4/Dev-Framework to Dev-Main (//UE4/Dev-Main) [at] 9318869
#rb
#rnx
#ROBOMERGE-OWNER: juan.canada
#ROBOMERGE-AUTHOR: marc.audy
#ROBOMERGE-SOURCE: CL 9318896 in //UE4/Main/...
#ROBOMERGE-BOT: RENDERING (Main -> Dev-RenderPlat-Staging) (v456-9359915)
[CL 9382348 by marc audy in Dev-RenderPlat-Staging branch]
This commit is contained in:
@@ -508,7 +508,6 @@ bNativizeAnimBPOnlyWhenNonReducibleFuncitons=false
|
||||
+NoExportTypesWithDirectNativeFieldAccess=/Script/Engine.FormatArgumentData
|
||||
|
||||
[/Script/UnrealEd.BlueprintEditorProjectSettings]
|
||||
bUseCompilationManager=true
|
||||
bValidateUnloadedSoftActorReferences=true
|
||||
|
||||
[/Script/UnrealEd.AssetViewerSettings]
|
||||
|
||||
@@ -183,27 +183,31 @@ void SAddNewRestrictedGameplayTagWidget::PopulateTagSources()
|
||||
UGameplayTagsManager& Manager = UGameplayTagsManager::Get();
|
||||
RestrictedTagSources.Empty();
|
||||
|
||||
FName DefaultSource = FGameplayTagSource::GetDefaultName();
|
||||
|
||||
// Always ensure that the default source is first
|
||||
RestrictedTagSources.Add( MakeShareable( new FName( DefaultSource ) ) );
|
||||
|
||||
TArray<const FGameplayTagSource*> Sources;
|
||||
Manager.GetRestrictedTagSources(Sources);
|
||||
|
||||
// Used to make sure we have a non-empty list of restricted tag sources. Not an actual source.
|
||||
FName PlaceholderSource = NAME_None;
|
||||
|
||||
// Add the placeholder source if no other sources exist
|
||||
if (Sources.Num() == 0)
|
||||
{
|
||||
RestrictedTagSources.Add(MakeShareable(new FName(PlaceholderSource)));
|
||||
}
|
||||
|
||||
for (const FGameplayTagSource* Source : Sources)
|
||||
{
|
||||
if (Source != nullptr && Source->SourceName != DefaultSource)
|
||||
if (Source != nullptr && Source->SourceName != PlaceholderSource)
|
||||
{
|
||||
RestrictedTagSources.Add(MakeShareable(new FName(Source->SourceName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SAddNewRestrictedGameplayTagWidget::Reset()
|
||||
void SAddNewRestrictedGameplayTagWidget::Reset(FName TagSource)
|
||||
{
|
||||
SetTagName();
|
||||
SelectTagSource();
|
||||
SelectTagSource(TagSource);
|
||||
SetAllowNonRestrictedChildren();
|
||||
TagCommentTextBox->SetText(FText());
|
||||
}
|
||||
@@ -274,6 +278,18 @@ void SAddNewRestrictedGameplayTagWidget::ValidateNewRestrictedTag()
|
||||
bool bAllowNonRestrictedChildren = AllowNonRestrictedChildrenCheckBox->IsChecked();
|
||||
FName TagSource = *TagSourcesComboBox->GetSelectedItem().Get();
|
||||
|
||||
if (TagSource == NAME_None)
|
||||
{
|
||||
FNotificationInfo Info(LOCTEXT("NoRestrictedSource", "You must specify a source file for restricted gameplay tags."));
|
||||
Info.ExpireDuration = 10.f;
|
||||
Info.bUseSuccessFailIcons = true;
|
||||
Info.Image = FEditorStyle::GetBrush(TEXT("MessageLog.Error"));
|
||||
|
||||
AddRestrictedGameplayTagDialog = FSlateNotificationManager::Get().AddNotification(Info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TArray<FString> TagSourceOwners;
|
||||
Manager.GetOwnersForTagSource(TagSource.ToString(), TagSourceOwners);
|
||||
|
||||
@@ -360,7 +376,7 @@ void SAddNewRestrictedGameplayTagWidget::CreateNewRestrictedGameplayTag()
|
||||
|
||||
OnRestrictedGameplayTagAdded.ExecuteIfBound(TagName, TagComment, TagSource);
|
||||
|
||||
Reset();
|
||||
Reset(TagSource);
|
||||
}
|
||||
|
||||
void SAddNewRestrictedGameplayTagWidget::CancelNewTag()
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
void AddSubtagFromParent(const FString& ParentTagName, const FName& ParentTagSource, bool bAllowNonRestrictedChildren);
|
||||
|
||||
/** Resets all input fields */
|
||||
void Reset();
|
||||
void Reset(FName TagSource = NAME_None);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -121,9 +121,9 @@ bool FLuminARDevice::GetStartSessionRequestFinished()
|
||||
}
|
||||
|
||||
// Note that this function will only be registered when LuminAR is supported.
|
||||
void FLuminARDevice::OnWorldTickStart(ELevelTick TickType, float DeltaTime)
|
||||
void FLuminARDevice::OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime)
|
||||
{
|
||||
WorldToMeterScale = GWorld->GetWorldSettings()->WorldToMeters;
|
||||
WorldToMeterScale = World->GetWorldSettings()->WorldToMeters;
|
||||
TFunction<void()> Func;
|
||||
while (RunOnGameThreadQueue.Dequeue(Func))
|
||||
{
|
||||
|
||||
@@ -98,7 +98,7 @@ private:
|
||||
void OnModuleLoaded();
|
||||
void OnModuleUnloaded();
|
||||
|
||||
void OnWorldTickStart(ELevelTick TickType, float DeltaTime);
|
||||
void OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime);
|
||||
|
||||
void StartSession();
|
||||
|
||||
|
||||
@@ -296,9 +296,9 @@ bool FGoogleARCoreDevice::GetStartSessionRequestFinished()
|
||||
}
|
||||
|
||||
// Note that this function will only be registered when ARCore is supported.
|
||||
void FGoogleARCoreDevice::OnWorldTickStart(ELevelTick TickType, float DeltaTime)
|
||||
void FGoogleARCoreDevice::OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime)
|
||||
{
|
||||
WorldToMeterScale = GWorld->GetWorldSettings()->WorldToMeters;
|
||||
WorldToMeterScale = World->GetWorldSettings()->WorldToMeters;
|
||||
TFunction<void()> Func;
|
||||
while (RunOnGameThreadQueue.Dequeue(Func))
|
||||
{
|
||||
|
||||
@@ -155,7 +155,7 @@ private:
|
||||
void OnModuleLoaded();
|
||||
void OnModuleUnloaded();
|
||||
|
||||
void OnWorldTickStart(ELevelTick TickType, float DeltaTime);
|
||||
void OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime);
|
||||
|
||||
void CheckAndRequrestPermission(const UARSessionConfig& ConfigurationData);
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ void FGoogleARCoreServicesManager::OnARSessionStarted()
|
||||
}
|
||||
|
||||
// We need to make sure this tick happens after the ARSystem tick
|
||||
void FGoogleARCoreServicesManager::OnWorldTickStart(ELevelTick TickType, float DeltaTime)
|
||||
void FGoogleARCoreServicesManager::OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime)
|
||||
{
|
||||
if (!bHasValidARSystem)
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ private:
|
||||
EARPinCloudTaskResult CheckCloudTaskError();
|
||||
|
||||
void OnARSessionStarted();
|
||||
void OnWorldTickStart(ELevelTick TickType, float DeltaTime);
|
||||
void OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime);
|
||||
|
||||
bool bHasValidARSystem;
|
||||
bool bCloudARPinEnabled;
|
||||
|
||||
@@ -115,7 +115,7 @@ void FHoloLensARSystem::Shutdown()
|
||||
SessionConfig = nullptr;
|
||||
}
|
||||
|
||||
void FHoloLensARSystem::OnWorldTickStart(ELevelTick TickType, float DeltaTime)
|
||||
void FHoloLensARSystem::OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime)
|
||||
{
|
||||
UpdateWMRAnchors();
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
void OnWorldTickStart(ELevelTick TickType, float DeltaTime);
|
||||
void OnWorldTickStart(UWorld* World, ELevelTick TickType, float DeltaTime);
|
||||
|
||||
//~ FGCObject
|
||||
virtual void AddReferencedObjects(FReferenceCollector& Collector) override;
|
||||
|
||||
@@ -1157,7 +1157,7 @@ void UGameplayAbility::MontageStop(float OverrideBlendOutTime)
|
||||
// We should only stop the current montage if we are the animating ability
|
||||
if (AbilitySystemComponent->IsAnimatingAbility(this))
|
||||
{
|
||||
AbilitySystemComponent->CurrentMontageStop();
|
||||
AbilitySystemComponent->CurrentMontageStop(OverrideBlendOutTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -963,7 +963,7 @@ void UAbilitySystemComponent::OnRep_ActivateAbilities()
|
||||
|
||||
// Try to run any pending activations that couldn't run before. If they don't work now, kill them
|
||||
|
||||
for (auto PendingAbilityInfo : PendingServerActivatedAbilities)
|
||||
for (const FPendingAbilityInfo& PendingAbilityInfo : PendingServerActivatedAbilities)
|
||||
{
|
||||
if (PendingAbilityInfo.bPartiallyActivated)
|
||||
{
|
||||
@@ -1827,48 +1827,10 @@ bool UAbilitySystemComponent::TriggerAbilityFromGameplayEvent(FGameplayAbilitySp
|
||||
// Run on the non-instanced ability
|
||||
if (Ability->ShouldAbilityRespondToEvent(ActorInfo, &TempEventData))
|
||||
{
|
||||
int32 ExecutingAbilityIndex = -1;
|
||||
|
||||
// if we're the server and this is coming from a predicted event we should check if the client has already predicted it
|
||||
if (ScopedPredictionKey.IsValidKey()
|
||||
&& Ability->GetNetExecutionPolicy() == EGameplayAbilityNetExecutionPolicy::LocalPredicted
|
||||
&& ActorInfo->OwnerActor->GetLocalRole() == ROLE_Authority)
|
||||
{
|
||||
bool bPendingClientAbilityFound = false;
|
||||
for (auto PendingAbilityInfo : Component.PendingClientActivatedAbilities)
|
||||
{
|
||||
if (ScopedPredictionKey.Current == PendingAbilityInfo.PredictionKey.Base && Handle == PendingAbilityInfo.Handle) // found a match
|
||||
{
|
||||
Component.PendingClientActivatedAbilities.RemoveSingleSwap(PendingAbilityInfo);
|
||||
bPendingClientAbilityFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// we haven't received the client's copy of the triggered ability
|
||||
// keep track of this so we can associate the prediction keys when it comes in
|
||||
if (bPendingClientAbilityFound == false)
|
||||
{
|
||||
UAbilitySystemComponent::FExecutingAbilityInfo Info;
|
||||
Info.PredictionKey = ScopedPredictionKey;
|
||||
Info.Handle = Handle;
|
||||
|
||||
ExecutingAbilityIndex = Component.ExecutingServerAbilities.Add(Info);
|
||||
}
|
||||
}
|
||||
|
||||
if (InternalTryActivateAbility(Handle, ScopedPredictionKey, nullptr, nullptr, &TempEventData))
|
||||
{
|
||||
if (ExecutingAbilityIndex >= 0)
|
||||
{
|
||||
Component.ExecutingServerAbilities[ExecutingAbilityIndex].State = UAbilitySystemComponent::EAbilityExecutionState::Succeeded;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (ExecutingAbilityIndex >= 0)
|
||||
{
|
||||
Component.ExecutingServerAbilities[ExecutingAbilityIndex].State = UAbilitySystemComponent::EAbilityExecutionState::Failed;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -732,7 +732,7 @@ TSharedPtr<FStreamableHandle> UGameplayCueManager::InitObjectLibrary(FGameplayCu
|
||||
// Instantiate the UObjectLibraries if they aren't there already
|
||||
if (!Lib.StaticObjectLibrary)
|
||||
{
|
||||
Lib.StaticObjectLibrary = UObjectLibrary::CreateLibrary(AGameplayCueNotify_Actor::StaticClass(), true, GIsEditor && !IsRunningCommandlet());
|
||||
Lib.StaticObjectLibrary = UObjectLibrary::CreateLibrary(UGameplayCueNotify_Static::StaticClass(), true, GIsEditor && !IsRunningCommandlet());
|
||||
if (GIsEditor)
|
||||
{
|
||||
Lib.StaticObjectLibrary->bIncludeOnlyOnDiskAssets = false;
|
||||
@@ -740,7 +740,7 @@ TSharedPtr<FStreamableHandle> UGameplayCueManager::InitObjectLibrary(FGameplayCu
|
||||
}
|
||||
if (!Lib.ActorObjectLibrary)
|
||||
{
|
||||
Lib.ActorObjectLibrary = UObjectLibrary::CreateLibrary(UGameplayCueNotify_Static::StaticClass(), true, GIsEditor && !IsRunningCommandlet());
|
||||
Lib.ActorObjectLibrary = UObjectLibrary::CreateLibrary(AGameplayCueNotify_Actor::StaticClass(), true, GIsEditor && !IsRunningCommandlet());
|
||||
if (GIsEditor)
|
||||
{
|
||||
Lib.ActorObjectLibrary->bIncludeOnlyOnDiskAssets = false;
|
||||
|
||||
@@ -775,7 +775,7 @@ protected:
|
||||
/**
|
||||
* Stops the current animation montage.
|
||||
*
|
||||
* @param OverrideBlendTime If < 0, will override the BlendOutTime parameter on the AnimMontage instance
|
||||
* @param OverrideBlendTime If >= 0, will override the BlendOutTime parameter on the AnimMontage instance
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category="Ability|Animation", Meta = (AdvancedDisplay = "OverrideBlendOutTime"))
|
||||
void MontageStop(float OverrideBlendOutTime = -1.0f);
|
||||
|
||||
@@ -249,40 +249,9 @@ class GAMEPLAYABILITIES_API UAbilitySystemComponent : public UGameplayTasksCompo
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a list of GameplayAbilities that are predicted by the client and were triggered by abilities that were also predicted by the client
|
||||
* When the server version of the predicted ability executes it should trigger copies of these and the copies will be associated with the correct prediction keys
|
||||
*/
|
||||
TArray<FPendingAbilityInfo> PendingClientActivatedAbilities;
|
||||
|
||||
/** This is a list of GameplayAbilities that were activated on the server and can't yet execute on the client. It will try to execute these at a later point */
|
||||
TArray<FPendingAbilityInfo> PendingServerActivatedAbilities;
|
||||
|
||||
/** State of execution for an ability, used to track on the server */
|
||||
enum class EAbilityExecutionState : uint8
|
||||
{
|
||||
Executing,
|
||||
Succeeded,
|
||||
Failed,
|
||||
};
|
||||
|
||||
struct FExecutingAbilityInfo
|
||||
{
|
||||
FExecutingAbilityInfo() : State(EAbilityExecutionState::Executing) {};
|
||||
|
||||
bool operator==(const FExecutingAbilityInfo& Other) const
|
||||
{
|
||||
return PredictionKey == Other.PredictionKey && State == Other.State;
|
||||
}
|
||||
|
||||
FPredictionKey PredictionKey;
|
||||
EAbilityExecutionState State;
|
||||
FGameplayAbilitySpecHandle Handle;
|
||||
};
|
||||
|
||||
/** List of all executing abilities the server knows about */
|
||||
TArray<FExecutingAbilityInfo> ExecutingServerAbilities;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
// GameplayEffects: Primary outward facing API for other systems
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "BlueprintNativeCodeGenUtils.h"
|
||||
#include "BlueprintCompilationManager.h"
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "HAL/FileManager.h"
|
||||
#include "Misc/Paths.h"
|
||||
@@ -453,19 +454,9 @@ void FBlueprintNativeCodeGenUtils::GenerateCppCode(UObject* Obj, TSharedPtr<FStr
|
||||
CodeGenBackend.NativizationSummary() = NativizationSummary;
|
||||
|
||||
{
|
||||
TSharedPtr<FBlueprintCompileReinstancer> Reinstancer = FBlueprintCompileReinstancer::Create(DuplicateBP->GeneratedClass);
|
||||
FBlueprintCompilationManager::CompileSynchronouslyToCpp( DuplicateBP, OutHeaderSource, OutCppSource, NativizationOptions );
|
||||
|
||||
IKismetCompilerInterface& Compiler = FModuleManager::LoadModuleChecked<IKismetCompilerInterface>(KISMET_COMPILER_MODULENAME);
|
||||
TGuardValue<bool> GuardTemplateNameFlag(GCompilingBlueprint, true);
|
||||
FCompilerResultsLog Results;
|
||||
|
||||
FKismetCompilerOptions CompileOptions;
|
||||
CompileOptions.CompileType = EKismetCompileType::Cpp;
|
||||
CompileOptions.OutCppSourceCode = OutCppSource;
|
||||
CompileOptions.OutHeaderSourceCode = OutHeaderSource;
|
||||
CompileOptions.NativizationOptions = NativizationOptions;
|
||||
|
||||
Compiler.CompileBlueprint(DuplicateBP, CompileOptions, Results);
|
||||
|
||||
Compiler.RemoveBlueprintGeneratedClasses(DuplicateBP);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,40 +38,13 @@ UObject const* FMergeToolUtils::LoadRevision(const FString& AssetName, const ISo
|
||||
{
|
||||
FSlateNotificationManager& NotificationManager = FSlateNotificationManager::Get();
|
||||
|
||||
const UObject* AssetRevision = nullptr;
|
||||
|
||||
// Get the head revision of this package from source control
|
||||
FString TempFileName;
|
||||
if (DesiredRevision.Get(TempFileName))
|
||||
{
|
||||
// Try and load that package
|
||||
UPackage* TempPackage = LoadPackage(NULL, *TempFileName, LOAD_ForDiff|LOAD_DisableCompileOnLoad);
|
||||
if (TempPackage != NULL)
|
||||
{
|
||||
// Grab the old asset from that old package
|
||||
UObject* OldObject = FindObject<UObject>(TempPackage, *AssetName);
|
||||
if (OldObject)
|
||||
{
|
||||
return OldObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotificationManager.AddNotification(
|
||||
FText::Format(
|
||||
LOCTEXT("MergedFailedToFindObject", "Aborted Load of {0} because we could not find an object named {1}" )
|
||||
, FText::FromString(TempFileName)
|
||||
, FText::FromString(AssetName)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NotificationManager.AddNotification(
|
||||
FText::Format(
|
||||
LOCTEXT("MergedFailedToLoadPackage", "Aborted Load of {0} because we could not load the package")
|
||||
, FText::FromString(TempFileName)
|
||||
)
|
||||
);
|
||||
}
|
||||
AssetRevision = LoadAssetFromPackage(TempFileName, AssetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -82,7 +55,8 @@ UObject const* FMergeToolUtils::LoadRevision(const FString& AssetName, const ISo
|
||||
)
|
||||
);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return AssetRevision;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -136,4 +110,45 @@ UObject const* FMergeToolUtils::LoadRevision(const UObject* AssetObject, const F
|
||||
return AssetRevision;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
UObject const* FMergeToolUtils::LoadAssetFromPackage(const FString& PackageFileName, const FString& AssetName)
|
||||
{
|
||||
FSlateNotificationManager& NotificationManager = FSlateNotificationManager::Get();
|
||||
|
||||
const UObject* Object = nullptr;
|
||||
|
||||
// Try and load that package
|
||||
UPackage* TempPackage = LoadPackage(NULL, *PackageFileName, LOAD_ForDiff | LOAD_DisableCompileOnLoad);
|
||||
if (TempPackage != NULL)
|
||||
{
|
||||
// Grab the old asset from that old package
|
||||
UObject* FoundObject = FindObject<UObject>(TempPackage, *AssetName);
|
||||
if (FoundObject)
|
||||
{
|
||||
Object = FoundObject;
|
||||
}
|
||||
else
|
||||
{
|
||||
NotificationManager.AddNotification(
|
||||
FText::Format(
|
||||
LOCTEXT("MergedFailedToFindObject", "Aborted Load of {0} because we could not find an object named {1}")
|
||||
, FText::FromString(PackageFileName)
|
||||
, FText::FromString(AssetName)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NotificationManager.AddNotification(
|
||||
FText::Format(
|
||||
LOCTEXT("MergedFailedToLoadPackage", "Aborted Load of {0} because we could not load the package")
|
||||
, FText::FromString(PackageFileName)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return Object;
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
@@ -60,4 +60,13 @@ struct FMergeToolUtils
|
||||
* @return The requested version of the specified asset object, could be null if the supplied revision failed to load.
|
||||
*/
|
||||
static UObject const* LoadRevision(const UObject* AssetObject, const FRevisionInfo& DesiredRevision);
|
||||
|
||||
/**
|
||||
* Attempts to load the specified asset from the provided package.
|
||||
*
|
||||
* @param PackageFileName The file name of the package where to look for the asset.
|
||||
* @param AssetName The name of the asset you want loaded from the package.
|
||||
* @return The asset object you wanted loaded, could be null if the asset wasn't found in the package.
|
||||
*/
|
||||
static UObject const* LoadAssetFromPackage(const FString& PackageFileName, const FString& AssetName);
|
||||
};
|
||||
|
||||
@@ -473,38 +473,18 @@ void SBlueprintMerge::OnAcceptLocal()
|
||||
// we use the emptiness of LocalBackupPath as a sentinel value (to
|
||||
// determine how we should replace the TargetBlueprint)... if
|
||||
// Data.BlueprintLocal is malformed (and not ok to copy), then
|
||||
// LocalBackupPath should be valid (and we need to copy the file on disk
|
||||
// instead)
|
||||
// LocalBackupPath should be valid (and we need to replace with
|
||||
// the backup instead)
|
||||
if (LocalBackupPath.IsEmpty())
|
||||
{
|
||||
NewBlueprint = FKismetEditorUtilities::ReplaceBlueprint(TargetBlueprint, Data.BlueprintLocal);
|
||||
}
|
||||
else
|
||||
{
|
||||
UPackage* TargetPackage = TargetBlueprint->GetOutermost();
|
||||
const FString BlueprintName = TargetBlueprint->GetName();
|
||||
const UBlueprint* LocalBackupBlueprint = Cast<const UBlueprint>(FMergeToolUtils::LoadAssetFromPackage(LocalBackupPath, BlueprintName));
|
||||
|
||||
FString PackageFilename;
|
||||
if (FPackageName::DoesPackageExist(TargetPackage->GetName(), /*Guid =*/nullptr, &PackageFilename))
|
||||
{
|
||||
FString SrcFilename = LocalBackupPath;
|
||||
auto OverwriteBlueprintFile = [TargetBlueprint, &PackageFilename, &SrcFilename](UBlueprint* /*UnloadedBP*/)
|
||||
{
|
||||
if (IFileManager::Get().Copy(*PackageFilename, *SrcFilename) != COPY_OK)
|
||||
{
|
||||
const FText TargetName = FText::FromName(TargetBlueprint->GetFName());
|
||||
const FText ErrorMessage = FText::Format(LOCTEXT("FailedMergeLocalCopy", "Failed to overwrite {0} target file."), TargetName);
|
||||
FSlateNotificationManager::Get().AddNotification(FNotificationInfo(ErrorMessage));
|
||||
}
|
||||
};
|
||||
// we have to wait until the package is unloaded (and the file is
|
||||
// unlocked) before we can overwrite the file; so we defer the
|
||||
// copy until then by adding it to the OnBlueprintUnloaded delegate
|
||||
FKismetEditorUtilities::FOnBlueprintUnloaded::FDelegate OnPackageUnloaded = FKismetEditorUtilities::FOnBlueprintUnloaded::FDelegate::CreateLambda(OverwriteBlueprintFile);
|
||||
|
||||
FDelegateHandle OnPackageUnloadedDelegateHandle = FKismetEditorUtilities::OnBlueprintUnloaded.Add(OnPackageUnloaded);
|
||||
NewBlueprint = FKismetEditorUtilities::ReloadBlueprint(TargetBlueprint);
|
||||
FKismetEditorUtilities::OnBlueprintUnloaded.Remove(OnPackageUnloadedDelegateHandle);
|
||||
}
|
||||
NewBlueprint = FKismetEditorUtilities::ReplaceBlueprint(TargetBlueprint, LocalBackupBlueprint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user