Skip to content

Commit

Permalink
Reload runtime AccessTransformers when config file is changed
Browse files Browse the repository at this point in the history
  • Loading branch information
mircearoata committed Jul 29, 2023
1 parent d669d1c commit 2095a95
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public AccessTransformers(ReadOnlyTargetRules Target) : base(Target)
"Engine",
"Projects",
"EditorSubsystem",
"DirectoryWatcher",
});
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "AccessTransformersSubsystem.h"

#include "AccessTransformers.h"
#include "DirectoryWatcherModule.h"
#include "IDirectoryWatcher.h"

UStruct* FindStructBySourceName(const FString Name) {
if(UStruct* EngineNameNoPackage = FindObject<UStruct>(ANY_PACKAGE, *Name)) {
Expand Down Expand Up @@ -86,27 +88,81 @@ UFunction* FFunctionReference::Resolve(FString& OutError, FString& OutWarning) c
void UAccessTransformersSubsystem::Initialize(FSubsystemCollectionBase& Collection) {
Super::Initialize(Collection);

LoadAccessTransformers();
ApplyTransformers();
}

FString GetPluginAccessTransformersPath(IPlugin& Plugin) {
return Plugin.GetBaseDir() / TEXT("Config") / TEXT("AccessTransformers.ini");
}

void UAccessTransformersSubsystem::LoadAccessTransformers() {
const TArray<TSharedRef<IPlugin>> EnabledPlugins = IPluginManager::Get().GetEnabledPlugins();

OnAccessTransformersChanged = IDirectoryWatcher::FDirectoryChanged::CreateUObject(this, &UAccessTransformersSubsystem::AccessTransformersChanged);

AccessTransformers.Empty();

const TArray<TSharedRef<IPlugin>> EnabledPlugins = IPluginManager::Get().GetEnabledPlugins();

for (TSharedRef<IPlugin> Plugin : EnabledPlugins) {
if (Plugin->GetType() == EPluginType::Engine || Plugin->GetType() == EPluginType::Enterprise) {
continue;
}
FPluginAccessTransformers PluginAccessTransformers;
if (GetAccessTransformersForPlugin(Plugin.Get(), PluginAccessTransformers)) {
AccessTransformers.Add(Plugin->GetName(), PluginAccessTransformers);
}
RegisterFileWatcher(Plugin.Get());
}

IPluginManager::Get().OnNewPluginCreated().AddUObject(this, &UAccessTransformersSubsystem::OnPluginCreated);

ApplyTransformers();
}

void UAccessTransformersSubsystem::RegisterFileWatcher(IPlugin& Plugin) {
FDirectoryWatcherModule& DirectoryWatcherModule = FModuleManager::LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher"));
IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get();
FString AccessTransformersPath = GetPluginAccessTransformersPath(Plugin);

FDelegateHandle Handle;
if (!DirectoryWatcher->RegisterDirectoryChangedCallback_Handle(FPaths::GetPath(AccessTransformersPath), OnAccessTransformersChanged, Handle)) {
UE_LOG(LogAccessTransformers, Error, TEXT("Failed to register directory watcher for %s. You will need to reload AccessTransformers manually when changed."), *AccessTransformersPath);
}
}

void UAccessTransformersSubsystem::AccessTransformersChanged(const TArray<FFileChangeData>& FileChangeData) {
bool HasChanges = false;
for (const FFileChangeData& FileChange : FileChangeData) {
if (FPaths::GetCleanFilename(FileChange.Filename) == AccessTransformersFileName) {
// File should be .../PluginDir/Config/AccessTransformers.ini
FString PluginDir = FPaths::GetPath(FPaths::GetPath(FileChange.Filename));
FString PluginName = FPaths::GetCleanFilename(PluginDir);
TSharedPtr<IPlugin> Plugin = IPluginManager::Get().FindPlugin(PluginName);
if (!Plugin.IsValid()) {
UE_LOG(LogAccessTransformers, Error, TEXT("Failed to find plugin for %s"), *PluginName);
continue;
}
FPluginAccessTransformers PluginAccessTransformers;
if (GetAccessTransformersForPlugin(Plugin.ToSharedRef().Get(), PluginAccessTransformers)) {
AccessTransformers.Add(Plugin->GetName(), PluginAccessTransformers);
HasChanges = true;
}
}
}
if (HasChanges) {
UE_LOG(LogAccessTransformers, Display, TEXT("AccessTransformers changed, reloading"));
ApplyTransformers();
}
}

void UAccessTransformersSubsystem::OnPluginCreated(IPlugin& Plugin) {
if (Plugin.GetType() == EPluginType::Engine || Plugin.GetType() == EPluginType::Enterprise) {
return;
}

FPluginAccessTransformers PluginAccessTransformers;
if (GetAccessTransformersForPlugin(Plugin, PluginAccessTransformers)) {
AccessTransformers.Add(Plugin.GetName(), PluginAccessTransformers);
ApplyTransformers();
}

RegisterFileWatcher(Plugin);
}

FString UAccessTransformersSubsystem::GetPluginAccessTransformersPath(IPlugin& Plugin) {
return Plugin.GetBaseDir() / TEXT("Config") / AccessTransformersFileName;
}

bool UAccessTransformersSubsystem::GetAccessTransformersForPlugin(IPlugin& Plugin, FPluginAccessTransformers& OutPluginAccessTransformers) {
FString AccessTransformersPath = GetPluginAccessTransformersPath(Plugin);
Expand Down Expand Up @@ -201,3 +257,5 @@ void UAccessTransformersSubsystem::Reset() {
}
OriginalFunctionFlags.Empty();
}

const TCHAR* UAccessTransformersSubsystem::AccessTransformersFileName = TEXT("AccessTransformers.ini");
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "CoreMinimal.h"
#include "Interfaces/IPluginManager.h"
#include "EditorSubsystem.h"
#include "IDirectoryWatcher.h"
#include "AccessTransformersSubsystem.generated.h"

USTRUCT()
Expand Down Expand Up @@ -61,16 +62,24 @@ class ACCESSTRANSFORMERS_API UAccessTransformersSubsystem : public UEditorSubsys

public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;

void LoadAccessTransformers();

void ApplyTransformers();
void Reset();

static const TCHAR* AccessTransformersFileName;
private:
static FString GetPluginAccessTransformersPath(IPlugin& Plugin);
bool GetAccessTransformersForPlugin(IPlugin& Plugin, FPluginAccessTransformers& OutPluginAccessTransformers);

void OnPluginCreated(IPlugin& Plugin);
void RegisterFileWatcher(IPlugin& Plugin);
void AccessTransformersChanged(const TArray<FFileChangeData>& FileChangeData);

TMap<FString, FPluginAccessTransformers> AccessTransformers;

TMap<FProperty*, EPropertyFlags> OriginalPropertyFlags;

TMap<UFunction*, EFunctionFlags> OriginalFunctionFlags;
};

IDirectoryWatcher::FDirectoryChanged OnAccessTransformersChanged;
};

0 comments on commit 2095a95

Please sign in to comment.