-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
HermesContentEndpoint.cpp
152 lines (126 loc) · 5.11 KB
/
HermesContentEndpoint.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright (c) Jørgen Tjernø <jorgen@tjer.no>. All rights reserved.
#include "HermesContentEndpoint.h"
#include "HermesContentEndpointEditorExtension.h"
#include <AssetRegistry/AssetRegistryModule.h>
#include <ContentBrowserModule.h>
#include <CoreMinimal.h>
#include <Editor.h>
#include <HermesServer.h>
#include <IContentBrowserSingleton.h>
#include <Interfaces/IMainFrameModule.h>
#include <Subsystems/AssetEditorSubsystem.h>
#define LOCTEXT_NAMESPACE "Editor.HermesContentEndpoint"
DEFINE_LOG_CATEGORY_STATIC(LogHermesContentEndpoint, Log, All);
const FName NAME_EndpointId(TEXT("content"));
struct FPendingRequest
{
FString Path;
FHermesQueryParamsMap Query;
};
struct FHermesContentEndpointModule : IModuleInterface
{
virtual void StartupModule() override final;
virtual void ShutdownModule() override final;
void OnAssetRegistryFilesLoaded();
void OnRequest(const FString& Path, const FHermesQueryParamsMap& QueryParams);
TArray<FPendingRequest> PendingRequests;
FDelegateHandle AssetRegistryLoadedDelegateHandle;
FHermesContentEndpointEditorExtension EditorExtension;
};
IMPLEMENT_MODULE(FHermesContentEndpointModule, HermesContentEndpoint);
void FHermesContentEndpointModule::StartupModule()
{
// Register a "post-loading" callback if the asset registry is currently loading
IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get();
if (AssetRegistry.IsLoadingAssets())
{
UE_LOG(LogHermesContentEndpoint, Verbose,
TEXT("Asset registry is currently loading, setting up callback for when it finishes"));
AssetRegistryLoadedDelegateHandle = AssetRegistry.OnFilesLoaded().AddRaw(
this, &FHermesContentEndpointModule::OnAssetRegistryFilesLoaded);
}
IHermesServerModule& Hermes = FModuleManager::LoadModuleChecked<IHermesServerModule>("HermesServer");
Hermes.Register(NAME_EndpointId, FHermesOnRequest::CreateRaw(this, &FHermesContentEndpointModule::OnRequest));
EditorExtension.InstallContentBrowserExtension();
EditorExtension.InstallAssetEditorExtension();
}
void FHermesContentEndpointModule::ShutdownModule()
{
EditorExtension.UninstallAssetEditorExtension();
EditorExtension.UninstallContentBrowserExtension();
if (auto Hermes = FModuleManager::GetModulePtr<IHermesServerModule>("HermesServer"))
{
Hermes->Unregister(NAME_EndpointId);
}
if (AssetRegistryLoadedDelegateHandle.IsValid())
{
if (IAssetRegistry* AssetRegistry = IAssetRegistry::Get())
{
AssetRegistry->OnFilesLoaded().Remove(AssetRegistryLoadedDelegateHandle);
}
AssetRegistryLoadedDelegateHandle.Reset();
}
}
void FHermesContentEndpointModule::OnAssetRegistryFilesLoaded()
{
UE_LOG(LogHermesContentEndpoint, Verbose, TEXT("Finished loading asset registry, processing %d pending requests"),
PendingRequests.Num());
AssetRegistryLoadedDelegateHandle.Reset();
// Process any requests that came in while we were loading
TArray<FPendingRequest> Requests(MoveTemp(PendingRequests));
for (const FPendingRequest& Request : Requests)
{
OnRequest(Request.Path, Request.Query);
}
}
void FHermesContentEndpointModule::OnRequest(const FString& Path, const FHermesQueryParamsMap& QueryParams)
{
// If the asset registry is still loading assets, put this in the queue for when it's done
IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry").Get();
if (AssetRegistry.IsLoadingAssets())
{
UE_LOG(LogHermesContentEndpoint, Verbose,
TEXT("Received request for %s while loading asset registry, putting in queue"), *Path);
FPendingRequest& Request = PendingRequests.AddDefaulted_GetRef();
Request.Path = Path;
Request.Query = QueryParams;
return;
}
TArray<FAssetData> AssetData;
AssetRegistry.GetAssetsByPackageName(*Path, AssetData);
if (AssetData.Num() > 0)
{
// Since this is a valid asset, either open it or edit it
const bool bShouldEdit = QueryParams.Contains("edit");
if (bShouldEdit)
{
UE_LOG(LogHermesContentEndpoint, Verbose, TEXT("Opening %s for editing"), *Path);
UAssetEditorSubsystem* AssetEditorSubsystem = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>();
AssetEditorSubsystem->OpenEditorForAsset(AssetData[0].GetAsset());
}
else
{
UE_LOG(LogHermesContentEndpoint, Verbose, TEXT("Focusing %s in content browser"), *Path);
IContentBrowserSingleton& ContentBrowser = FModuleManager::LoadModuleChecked<FContentBrowserModule>(
"ContentBrowser").Get();
const bool bAllowLockedBrowsers = false;
const bool bFocusContentBrowser = true;
ContentBrowser.SyncBrowserToAssets(AssetData, bAllowLockedBrowsers, bFocusContentBrowser);
}
}
else
{
UE_LOG(LogHermesContentEndpoint, Error, TEXT("Couldn't find any assets for %s"), *Path);
}
IMainFrameModule& MainFrameModule = IMainFrameModule::Get();
TSharedPtr<SWindow> ParentWindow = MainFrameModule.GetParentWindow();
if (ParentWindow.IsValid())
{
// Bring the main frame Slate window into focus
ParentWindow->ShowWindow();
// Use this hacky API to bring the OS-level window forward
ParentWindow->GetNativeWindow()->HACK_ForceToFront();
// TODO: Make sure that the content browser drawer is in focus
}
}
#undef LOCTEXT_NAMESPACE