-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
140 changed files
with
4,147 additions
and
1,224 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-1.6 KB
Content/Samples/BasicLoader/Blueprints/Default__BP_LoaderDemoUI_C.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified
BIN
-13.4 KB
(67%)
Content/Samples/BasicUI/Blueprints/WBP_RpmCategoryPanel.uasset
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file renamed
BIN
+6.29 KB
...Samples/BasicUI/Icons/T-rpm-bottom.uasset → .../Samples/Icons/T-rpm-Custom-bottom.uasset
Binary file not shown.
Binary file renamed
BIN
+5.92 KB
.../Samples/BasicUI/Icons/T-rpm-shoes.uasset → ...amples/Icons/T-rpm-Custom-footwear.uasset
Binary file not shown.
Binary file renamed
BIN
+5.45 KB
...nt/Samples/BasicUI/Icons/T-rpm-top.uasset → ...ent/Samples/Icons/T-rpm-Custom-top.uasset
Binary file not shown.
Binary file renamed
BIN
+6.28 KB
...ples/BasicUI/Icons/T-rpm-baseModel.uasset → Content/Samples/Icons/T-rpm-baseModel.uasset
Binary file not shown.
Binary file renamed
BIN
+5.66 KB
...Samples/BasicUI/Icons/T-rpm-custom.uasset → Content/Samples/Icons/T-rpm-custom.uasset
Binary file not shown.
Binary file renamed
BIN
+6.3 KB
...es/BasicUI/Icons/T-rpm-facial-hair.uasset → ...nt/Samples/Icons/T-rpm-facial-hair.uasset
Binary file not shown.
Binary file renamed
BIN
+5.84 KB
...amples/BasicUI/Icons/T-rpm-glasses.uasset → Content/Samples/Icons/T-rpm-glasses.uasset
Binary file not shown.
Binary file renamed
BIN
+6.67 KB
...t/Samples/BasicUI/Icons/T-rpm-hair.uasset → Content/Samples/Icons/T-rpm-hair.uasset
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,216 @@ | ||
#include "Api/Assets/AssetApi.h" | ||
#include "Api/Assets/AssetApi.h" | ||
|
||
#include "RpmNextGen.h" | ||
#include "Settings/RpmDeveloperSettings.h" | ||
#include "Api/Assets/Models/AssetListRequest.h" | ||
#include "Api/Assets/Models/AssetListResponse.h" | ||
#include "Api/Assets/Models/AssetTypeListRequest.h" | ||
#include "Api/Auth/ApiKeyAuthStrategy.h" | ||
#include "Cache/AssetCacheManager.h" | ||
#include "Interfaces/IHttpResponse.h" | ||
|
||
struct FCachedAssetData; | ||
struct FAssetTypeListRequest; | ||
const FString FAssetApi::BaseModelType = TEXT("baseModel"); | ||
|
||
FAssetApi::FAssetApi() : ApiRequestStrategy(EApiRequestStrategy::FallbackToCache) | ||
{ | ||
Initialize(); | ||
} | ||
|
||
FAssetApi::FAssetApi() | ||
FAssetApi::FAssetApi(EApiRequestStrategy InApiRequestStrategy) : ApiRequestStrategy(InApiRequestStrategy) | ||
{ | ||
OnApiResponse.BindRaw(this, &FAssetApi::HandleListAssetResponse); | ||
Initialize(); | ||
} | ||
|
||
FAssetApi::~FAssetApi() | ||
{ | ||
} | ||
|
||
void FAssetApi::Initialize() | ||
{ | ||
if (bIsInitialized) return; | ||
|
||
const URpmDeveloperSettings* Settings = GetDefault<URpmDeveloperSettings>(); | ||
OnRequestComplete.BindRaw(this, &FAssetApi::HandleAssetResponse); | ||
if (Settings->ApplicationId.IsEmpty()) | ||
{ | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("Application ID is empty. Please set the Application ID in the Ready Player Me Developer Settings")); | ||
} | ||
|
||
if (!Settings->ApiKey.IsEmpty() || Settings->ApiProxyUrl.IsEmpty()) | ||
{ | ||
SetAuthenticationStrategy(MakeShared<FApiKeyAuthStrategy>()); | ||
} | ||
bIsInitialized = true; | ||
} | ||
|
||
void FAssetApi::ListAssetsAsync(const FAssetListRequest& Request) | ||
{ | ||
if(ApiRequestStrategy == EApiRequestStrategy::CacheOnly) | ||
{ | ||
LoadAssetsFromCache(Request.BuildQueryMap()); | ||
return; | ||
} | ||
const URpmDeveloperSettings* RpmSettings = GetDefault<URpmDeveloperSettings>(); | ||
ApiBaseUrl = RpmSettings->GetApiBaseUrl(); | ||
if(RpmSettings->ApplicationId.IsEmpty()) | ||
{ | ||
UE_LOG(LogTemp, Error, TEXT("Application ID is empty")); | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("Application ID is empty")); | ||
OnListAssetsResponse.ExecuteIfBound(FAssetListResponse(), false); | ||
return; | ||
} | ||
FString QueryString = Request.BuildQueryString(); | ||
const FString Url = FString::Printf(TEXT("%s/v1/phoenix-assets%s"), *ApiBaseUrl, *QueryString); | ||
FApiRequest ApiRequest = FApiRequest(); | ||
ApiRequest.Url = Url; | ||
ApiRequest.Method = GET; | ||
const FString Url = FString::Printf(TEXT("%s/v1/phoenix-assets"), *ApiBaseUrl); | ||
TSharedPtr<FApiRequest> ApiRequest = MakeShared<FApiRequest>(); | ||
ApiRequest->Url = Url; | ||
ApiRequest->Method = GET; | ||
ApiRequest->QueryParams = Request.BuildQueryMap(); | ||
|
||
DispatchRawWithAuth(ApiRequest); | ||
} | ||
|
||
void FAssetApi::HandleListAssetResponse(FString Response, bool bWasSuccessful) | ||
void FAssetApi::ListAssetTypesAsync(const FAssetTypeListRequest& Request) | ||
{ | ||
if(bWasSuccessful) | ||
if(ApiRequestStrategy == EApiRequestStrategy::CacheOnly) | ||
{ | ||
FAssetListResponse AssetListResponse = FAssetListResponse(); | ||
if(FJsonObjectConverter::JsonObjectStringToUStruct(Response, &AssetListResponse, 0, 0)) | ||
LoadAssetTypesFromCache(); | ||
return; | ||
} | ||
URpmDeveloperSettings* Settings = GetMutableDefault<URpmDeveloperSettings>(); | ||
ApiBaseUrl = Settings->GetApiBaseUrl(); | ||
if(Settings->ApplicationId.IsEmpty()) | ||
{ | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("Application ID is empty")); | ||
OnListAssetsResponse.ExecuteIfBound(FAssetListResponse(), false); | ||
return; | ||
} | ||
FString QueryString = Request.BuildQueryString(); | ||
const FString Url = FString::Printf(TEXT("%s/v1/phoenix-assets/types%s"), *ApiBaseUrl, *QueryString); | ||
TSharedPtr<FApiRequest> ApiRequest = MakeShared<FApiRequest>(); | ||
ApiRequest->Url = Url; | ||
ApiRequest->Method = GET; | ||
|
||
DispatchRawWithAuth( ApiRequest); | ||
} | ||
|
||
void FAssetApi::HandleAssetResponse(TSharedPtr<FApiRequest> ApiRequest, FHttpResponsePtr Response, bool bWasSuccessful) | ||
{ | ||
const bool bIsTypeRequest = ApiRequest->Url.Contains(TEXT("/types")); | ||
if (bWasSuccessful && Response.IsValid() && EHttpResponseCodes::IsOk(Response->GetResponseCode())) | ||
{ | ||
FAssetTypeListResponse AssetTypeListResponse; | ||
|
||
if (bIsTypeRequest && FJsonObjectConverter::JsonObjectStringToUStruct(Response->GetContentAsString(), &AssetTypeListResponse, 0, 0)) | ||
{ | ||
OnListAssetTypeResponse.ExecuteIfBound(AssetTypeListResponse, true); | ||
return; | ||
} | ||
FAssetListResponse AssetListResponse; | ||
if (!bIsTypeRequest && FJsonObjectConverter::JsonObjectStringToUStruct(Response->GetContentAsString(), &AssetListResponse, 0, 0)) | ||
{ | ||
OnListAssetsResponse.ExecuteIfBound(AssetListResponse, true); | ||
return; | ||
} | ||
UE_LOG(LogTemp, Error, TEXT("Failed to parse API response")); | ||
} | ||
|
||
if(ApiRequestStrategy == EApiRequestStrategy::ApiOnly) | ||
{ | ||
if(bIsTypeRequest) | ||
{ | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("AssetApi:ListAssetTypesAsync request failed: %s"), *Response->GetContentAsString()); | ||
OnListAssetTypeResponse.ExecuteIfBound(FAssetTypeListResponse(), false); | ||
return; | ||
} | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("AssetApi:ListAssetsAsync request failed: %s"), *Response->GetContentAsString()); | ||
OnListAssetsResponse.ExecuteIfBound(FAssetListResponse(), false); | ||
return; | ||
} | ||
if(bIsTypeRequest) | ||
{ | ||
UE_LOG(LogReadyPlayerMe, Warning, TEXT("FAssetApi::ListAssetTypesAsync request failed, falling back to cache.")); | ||
LoadAssetTypesFromCache(); | ||
return; | ||
} | ||
UE_LOG(LogReadyPlayerMe, Warning, TEXT("FAssetApi::ListAssetsAsync request failed, falling back to cache.")); | ||
LoadAssetsFromCache(ApiRequest->QueryParams); | ||
} | ||
|
||
void FAssetApi::LoadAssetsFromCache(TMap<FString, FString> QueryParams) | ||
{ | ||
if(QueryParams.Num() < 1) | ||
{ | ||
OnListAssetsResponse.ExecuteIfBound(FAssetListResponse(), false); | ||
return; | ||
} | ||
const FString TypeKey = TEXT("type"); | ||
const FString ExcludeTypeKey = TEXT("excludeType"); | ||
FString Type = QueryParams.Contains(TypeKey) ? *QueryParams.Find(TypeKey) : FString(); | ||
FString ExcludeType = QueryParams.Contains(ExcludeTypeKey) ? *QueryParams.Find(ExcludeTypeKey) : FString(); | ||
TArray<FCachedAssetData> CachedAssets; | ||
|
||
if(ExcludeType.IsEmpty()) | ||
{ | ||
CachedAssets = FAssetCacheManager::Get().GetAssetsOfType(Type); | ||
} | ||
else | ||
{ | ||
UE_LOG(LogTemp, Error, TEXT("API Response was unsuccessful")); | ||
auto ExtractQueryString = TEXT("excludeType=") + ExcludeType; | ||
auto ExtractQueryArray = ExtractQueryValues(ExcludeType, ExcludeTypeKey); | ||
CachedAssets = FAssetCacheManager::Get().GetAssetsExcludingTypes(ExtractQueryArray); | ||
} | ||
|
||
if (CachedAssets.Num() > 0) | ||
{ | ||
FAssetListResponse AssetListResponse; | ||
for (const FCachedAssetData& CachedAsset : CachedAssets) | ||
{ | ||
FAsset Asset = CachedAsset.ToAsset(); | ||
AssetListResponse.Data.Add(Asset); | ||
} | ||
OnListAssetsResponse.ExecuteIfBound(AssetListResponse, true); | ||
return; | ||
} | ||
UE_LOG(LogReadyPlayerMe, Warning, TEXT("No assets found in the cache.")); | ||
OnListAssetsResponse.ExecuteIfBound(FAssetListResponse(), false); | ||
} | ||
|
||
void FAssetApi::HandleListAssetTypeResponse(FString Response, bool bWasSuccessful) | ||
void FAssetApi::LoadAssetTypesFromCache() | ||
{ | ||
TArray<FString> AssetTypes = FAssetCacheManager::Get().LoadAssetTypes(); | ||
if (AssetTypes.Num() > 0) | ||
{ | ||
FAssetTypeListResponse AssetListResponse; | ||
AssetListResponse.Data.Append(AssetTypes); | ||
OnListAssetTypeResponse.ExecuteIfBound(AssetListResponse, true); | ||
return; | ||
} | ||
UE_LOG(LogReadyPlayerMe, Warning, TEXT("No assets found in the cache.")); | ||
OnListAssetTypeResponse.ExecuteIfBound(FAssetTypeListResponse(), false); | ||
} | ||
|
||
TArray<FString> FAssetApi::ExtractQueryValues(const FString& QueryString, const FString& Key) | ||
{ | ||
TArray<FString> Values; | ||
TArray<FString> Pairs; | ||
|
||
// Split the query string by '&' to separate each key-value pair | ||
QueryString.ParseIntoArray(Pairs, TEXT("&"), true); | ||
|
||
// Iterate through all pairs and check if they match the key | ||
for (const FString& Pair : Pairs) | ||
{ | ||
FString KeyPart, ValuePart; | ||
|
||
// Split the pair by '=' to get the key and value | ||
if (Pair.Split(TEXT("="), &KeyPart, &ValuePart)) | ||
{ | ||
// If the key matches the one we're looking for, add the value to the array | ||
if (KeyPart.Equals(Key, ESearchCase::IgnoreCase)) | ||
{ | ||
Values.Add(ValuePart); | ||
} | ||
} | ||
} | ||
|
||
return Values; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#include "Api/Assets/AssetGlbLoader.h" | ||
#include "Api/Assets/AssetLoaderContext.h" | ||
#include "HttpModule.h" | ||
#include "Cache/AssetCacheManager.h" | ||
#include "Interfaces/IHttpResponse.h" | ||
|
||
FAssetGlbLoader::FAssetGlbLoader() | ||
{ | ||
Http = &FHttpModule::Get(); | ||
} | ||
|
||
FAssetGlbLoader::~FAssetGlbLoader() | ||
{ | ||
} | ||
|
||
void FAssetGlbLoader::LoadGlb(const FAsset& Asset, const FString& BaseModelId, bool bStoreInCache) | ||
{ | ||
FCachedAssetData StoredAsset; | ||
if (FAssetCacheManager::Get().GetCachedAsset(Asset.Id, StoredAsset)) | ||
{ | ||
TArray<uint8> GlbData; | ||
const FString StoredGlbPath = StoredAsset.GetGlbPathForBaseModelId(BaseModelId); | ||
if(FFileHelper::LoadFileToArray(GlbData, *StoredGlbPath)) | ||
{ | ||
OnGlbLoaded.ExecuteIfBound(Asset, GlbData); | ||
return; | ||
} | ||
} | ||
const TSharedRef<FAssetLoadingContext> Context = MakeShared<FAssetLoadingContext>(Asset, BaseModelId, bStoreInCache); | ||
LoadGlb(Context); | ||
} | ||
|
||
void FAssetGlbLoader::LoadGlb(TSharedRef<FAssetLoadingContext> Context) | ||
{ | ||
TSharedRef<IHttpRequest> Request = Http->CreateRequest(); | ||
Request->SetURL(Context->Asset.GlbUrl); | ||
Request->SetVerb(TEXT("GET")); | ||
|
||
TSharedPtr<FAssetGlbLoader> ThisPtr = SharedThis(this); | ||
Request->OnProcessRequestComplete().BindLambda([ThisPtr, Context](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) | ||
{ | ||
ThisPtr->GlbLoaded(Response, bWasSuccessful, Context); | ||
}); | ||
Request->ProcessRequest(); | ||
} | ||
|
||
void FAssetGlbLoader::GlbLoaded(TSharedPtr<IHttpResponse> Response, const bool bWasSuccessful, const TSharedRef<FAssetLoadingContext>& Context) | ||
{ | ||
if (bWasSuccessful && Response.IsValid()) | ||
{ | ||
Context->Data = Response->GetContent(); | ||
if (Context->bStoreInCache) | ||
{ | ||
FAssetCacheManager::Get().StoreAndTrackGlb(*Context); | ||
} | ||
OnGlbLoaded.ExecuteIfBound(Context->Asset, Context->Data); | ||
return; | ||
} | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("Failed to load GLB from URL: %s"), *Context->Asset.GlbUrl); | ||
OnGlbLoaded.ExecuteIfBound(Context->Asset, TArray<uint8>()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include "Api/Assets/AssetIconLoader.h" | ||
#include "Api/Assets/AssetLoaderContext.h" | ||
#include "HttpModule.h" | ||
#include "Cache/AssetCacheManager.h" | ||
#include "Interfaces/IHttpResponse.h" | ||
|
||
FAssetIconLoader::FAssetIconLoader() | ||
{ | ||
Http = &FHttpModule::Get(); | ||
} | ||
|
||
FAssetIconLoader::~FAssetIconLoader() | ||
{ | ||
} | ||
|
||
void FAssetIconLoader::LoadIcon(const FAsset& Asset, bool bStoreInCache) | ||
{ | ||
FCachedAssetData StoredAsset; | ||
if (FAssetCacheManager::Get().GetCachedAsset(Asset.Id, StoredAsset)) | ||
{ | ||
TArray<uint8> IconData; | ||
if(FFileHelper::LoadFileToArray(IconData, * FFileUtility::GetFullPersistentPath(StoredAsset.RelativeIconFilePath))) | ||
{ | ||
OnIconLoaded.ExecuteIfBound(Asset, IconData); | ||
return; | ||
} | ||
} | ||
const TSharedRef<FAssetLoadingContext> Context = MakeShared<FAssetLoadingContext>(Asset, "", bStoreInCache); | ||
LoadIcon(Context); | ||
} | ||
|
||
void FAssetIconLoader::LoadIcon(TSharedRef<FAssetLoadingContext> Context) | ||
{ | ||
TSharedRef<IHttpRequest> Request = Http->CreateRequest(); | ||
Request->SetURL(Context->Asset.IconUrl); | ||
Request->SetVerb(TEXT("GET")); | ||
|
||
TSharedPtr<FAssetIconLoader> ThisPtr = SharedThis(this); | ||
Request->OnProcessRequestComplete().BindLambda([ThisPtr, Context](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) | ||
{ | ||
ThisPtr->IconLoaded(Response, bWasSuccessful, Context); | ||
}); | ||
Request->ProcessRequest(); | ||
} | ||
|
||
void FAssetIconLoader::IconLoaded(TSharedPtr<IHttpResponse> Response, bool bWasSuccessful, const TSharedRef<FAssetLoadingContext>& Context) | ||
{ | ||
if (bWasSuccessful && Response.IsValid()) | ||
{ | ||
Context->Data = Response->GetContent(); | ||
if (Context->bStoreInCache) | ||
{ | ||
FAssetCacheManager::Get().StoreAndTrackIcon(*Context); | ||
} | ||
OnIconLoaded.ExecuteIfBound(Context->Asset, Context->Data); | ||
return; | ||
} | ||
UE_LOG(LogReadyPlayerMe, Error, TEXT("Failed to load icon from URL: %s"), *Context->Asset.IconUrl); | ||
OnIconLoaded.ExecuteIfBound(Context->Asset, TArray<uint8>()); | ||
} |
Oops, something went wrong.