Skip to content

Commit

Permalink
Merge branch 'release/v3.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
HarrisonHough committed Nov 27, 2024
2 parents 89db740 + e138640 commit e6c6424
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 59 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [3.4.0] 2024-11-27

## Updated

- updated auth endpoints [#73](https://github.com/readyplayerme/rpm-unreal-sdk/pull/73)

## [3.3.0] 2024-07-16

## Added
Expand Down
3 changes: 3 additions & 0 deletions Config/DefaultReadyPlayerMe.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[CoreRedirects]
+FunctionRedirects=(OldName="/Script/RpmAvatarCreator.RpmAvatarCreatorApi.ConfirmActivationCode",NewName="/Script/RpmAvatarCreator.RpmAvatarCreatorApi.ConfirmLoginCode")
+FunctionRedirects=(OldName="/Script/RpmAvatarCreator.RpmAvatarCreatorApi.AuthStart",NewName="/Script/RpmAvatarCreator.RpmAvatarCreatorApi.RequestLoginCode")
2 changes: 1 addition & 1 deletion ReadyPlayerMe.uplugin
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "3.3.0",
"VersionName": "3.4.0",
"FriendlyName": "Ready Player Me",
"Description": "Ready Player Me SDK",
"Category": "Runtime",
Expand Down
12 changes: 6 additions & 6 deletions Source/RpmAvatarCreator/Private/Downloaders/RpmAuthManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ void FRpmAuthManager::Logout()
RequestFactory->SetUserData({});
}

void FRpmAuthManager::AuthStart(const FString& Email, bool bIsTypeCode, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed)
void FRpmAuthManager::RequestLoginCode(const FString& Email, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed)
{
OnAuthenticationCompleted = Completed;
OnAvatarCreatorFailed = Failed;

AuthRequest = RequestFactory->CreateAuthStartRequest(FUserDataExtractor::MakeAuthStartPayload(Email, UserData.Id, bIsTypeCode));
AuthRequest->GetCompleteCallback().BindSP(AsShared(), &FRpmAuthManager::AuthStartCompleted);
AuthRequest = RequestFactory->CreateRequestLoginCodeRequest(FUserDataExtractor::MakeRequestLoginCodePayload(Email, UserData.Id, RequestFactory->GetSubdomain()));
AuthRequest->GetCompleteCallback().BindSP(AsShared(), &FRpmAuthManager::RequestLoginCodeCompleted);
AuthRequest->Download();
}

Expand All @@ -42,7 +42,7 @@ void FRpmAuthManager::ConfirmActivationCode(const FString& Code, const FAuthenti
OnAuthenticationCompleted = Completed;
OnAvatarCreatorFailed = Failed;

AuthRequest = RequestFactory->CreateConfirmCodeRequest(FUserDataExtractor::MakeConfirmCodePayload(Code));
AuthRequest = RequestFactory->CreateConfirmCodeRequest(FUserDataExtractor::MakeConfirmCodePayload(Code, RequestFactory->GetSubdomain()));
AuthRequest->GetCompleteCallback().BindSP(AsShared(), &FRpmAuthManager::ConfirmActivationCodeCompleted);
AuthRequest->Download();
}
Expand All @@ -52,7 +52,7 @@ void FRpmAuthManager::AuthAnonymous(const FAuthenticationCompleted& Completed, c
OnAuthenticationCompleted = Completed;
OnAvatarCreatorFailed = Failed;

AuthRequest = RequestFactory->CreateAuthAnonymousRequest();
AuthRequest = RequestFactory->CreateAuthAnonymousRequest(FUserDataExtractor::MakeAuthAnonymousPayload(RequestFactory->GetSubdomain()));
AuthRequest->GetCompleteCallback().BindSP(AsShared(), &FRpmAuthManager::AuthAnonymousCompleted);
AuthRequest->Download();
}
Expand All @@ -72,7 +72,7 @@ void FRpmAuthManager::ConfirmActivationCodeCompleted(bool bSuccess)
(void)OnAuthenticationCompleted.ExecuteIfBound();
}

void FRpmAuthManager::AuthStartCompleted(bool bSuccess)
void FRpmAuthManager::RequestLoginCodeCompleted(bool bSuccess)
{
if (!bSuccess)
{
Expand Down
4 changes: 2 additions & 2 deletions Source/RpmAvatarCreator/Private/Downloaders/RpmAuthManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class FRpmAuthManager : public TSharedFromThis<FRpmAuthManager>
public:
FRpmAuthManager(TSharedPtr<class FRequestFactory> RequestFactory);
void BindTokenRefreshDelegate();
void AuthStart(const FString& Email, bool bIsTypeCode, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);
void RequestLoginCode(const FString& Email, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);
void ConfirmActivationCode(const FString& Code, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);
void AuthAnonymous(const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);
void Logout();
Expand All @@ -20,7 +20,7 @@ class FRpmAuthManager : public TSharedFromThis<FRpmAuthManager>

private:
void AuthAnonymousCompleted(bool bSuccess);
void AuthStartCompleted(bool bSuccess);
void RequestLoginCodeCompleted(bool bSuccess);
void ConfirmActivationCodeCompleted(bool bSuccess);
void TokenRefreshed(const FString& Token, const FString& RefreshToken);

Expand Down
22 changes: 19 additions & 3 deletions Source/RpmAvatarCreator/Private/Extractors/DataJsonUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright © 2023++ Ready Player Me


#include "DataJsonUtils.h"

#include "Templates/SharedPointer.h"
Expand Down Expand Up @@ -36,13 +35,30 @@ TSharedPtr<FJsonObject> FDataJsonUtils::ExtractDataObject(const FString& JsonStr
return JsonObject->GetObjectField(JSON_FIELD_DATA);
}

FString FDataJsonUtils::MakeDataPayload(const TSharedPtr<FJsonObject> DataObject)
TSharedPtr<FJsonObject> FDataJsonUtils::ExtractBodyObject(const FString& JsonString)
{
FString OutputJsonString;
TSharedPtr<FJsonObject> JsonObject;

if (!FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(JsonString), JsonObject))
{
return {};
}

return JsonObject;
}

FString FDataJsonUtils::MakeDataPayload(const TSharedPtr<FJsonObject> DataObject)
{
const TSharedPtr<FJsonObject> JsonObject = MakeShared<FJsonObject>();
JsonObject->SetObjectField(JSON_FIELD_DATA, DataObject);

return MakePayload(JsonObject);
}

FString FDataJsonUtils::MakePayload(const TSharedPtr<FJsonObject> JsonObject)
{
FString OutputJsonString;

if (!FJsonSerializer::Serialize(JsonObject.ToSharedRef(), TJsonWriterFactory<>::Create(&OutputJsonString)))
{
UE_LOG(LogRpmAvatarCreator, Warning, TEXT("Failed to create a valid url"));
Expand Down
2 changes: 2 additions & 0 deletions Source/RpmAvatarCreator/Private/Extractors/DataJsonUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ class FDataJsonUtils
public:
static TArray<TSharedPtr<FJsonValue>> ExtractDataArray(const FString& JsonString);
static TSharedPtr<FJsonObject> ExtractDataObject(const FString& JsonString);
static TSharedPtr<FJsonObject> ExtractBodyObject(const FString& JsonString);
static FString MakeDataPayload(const TSharedPtr<FJsonObject> DataObject);
static FString MakePayload(const TSharedPtr<FJsonObject> DataObject);
};
36 changes: 22 additions & 14 deletions Source/RpmAvatarCreator/Private/Extractors/UserDataExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ static const FString JSON_FIELD_CODE = "code";
static const FString JSON_FIELD_NAME = "name";
static const FString JSON_FIELD_ID = "id";
static const FString JSON_FIELD__ID = "_id";
static const FString JSON_FIELD_AUTH_TYPE = "authType";
static const FString JSON_FIELD_APP_NAME = "appName";
static const FString JSON_FIELD_REQUEST_TOKEN = "requestToken";

FRpmUserData FUserDataExtractor::ExtractAnonymousUserData(const FString& JsonString)
{
Expand All @@ -33,22 +34,22 @@ FRpmUserData FUserDataExtractor::ExtractAnonymousUserData(const FString& JsonStr

FRpmUserData FUserDataExtractor::ExtractRefreshedUserSession(const FString& JsonString)
{
const TSharedPtr<FJsonObject> DataObject = FDataJsonUtils::ExtractDataObject(JsonString);
if (!DataObject || !DataObject->HasField(JSON_FIELD_REFRESH_TOKEN) || !DataObject->HasField(JSON_FIELD_TOKEN))
const TSharedPtr<FJsonObject> ResponseObject = FDataJsonUtils::ExtractBodyObject(JsonString);
if (!ResponseObject || !ResponseObject->HasField(JSON_FIELD_REFRESH_TOKEN) || !ResponseObject->HasField(JSON_FIELD_TOKEN))
{
return {};
}

FRpmUserData UserData;
UserData.bIsAuthenticated = true;
UserData.RefreshToken = DataObject->GetStringField(JSON_FIELD_REFRESH_TOKEN);
UserData.Token = DataObject->GetStringField(JSON_FIELD_TOKEN);
UserData.RefreshToken = ResponseObject->GetStringField(JSON_FIELD_REFRESH_TOKEN);
UserData.Token = ResponseObject->GetStringField(JSON_FIELD_TOKEN);
return UserData;
}

FRpmUserData FUserDataExtractor::ExtractUserData(const FString& JsonString)
{
const TSharedPtr<FJsonObject> DataObject = FDataJsonUtils::ExtractDataObject(JsonString);
const TSharedPtr<FJsonObject> DataObject = FDataJsonUtils::ExtractBodyObject(JsonString);
if (!DataObject || !DataObject->HasField(JSON_FIELD__ID) || !DataObject->HasField(JSON_FIELD_TOKEN))
{
return {};
Expand All @@ -65,32 +66,39 @@ FRpmUserData FUserDataExtractor::ExtractUserData(const FString& JsonString)
return UserData;
}

FString FUserDataExtractor::MakeAuthStartPayload(const FString& Email, const FString& UserId, bool bIsTypeCode)
FString FUserDataExtractor::MakeRequestLoginCodePayload(const FString& Email, const FString& UserId, const FString& Subdomain)
{
const TSharedPtr<FJsonObject> DataObject = MakeShared<FJsonObject>();
DataObject->SetStringField(JSON_FIELD_EMAIL, Email);
DataObject->SetStringField(JSON_FIELD_APP_NAME, Subdomain);
if (!UserId.IsEmpty())
{
DataObject->SetStringField(JSON_FIELD_ID, UserId);
}
if (bIsTypeCode)
{
DataObject->SetStringField(JSON_FIELD_AUTH_TYPE, JSON_FIELD_CODE);
}
return FDataJsonUtils::MakeDataPayload(DataObject);
return FDataJsonUtils::MakePayload(DataObject);
}

FString FUserDataExtractor::MakeConfirmCodePayload(const FString& Code)
FString FUserDataExtractor::MakeConfirmCodePayload(const FString& Code, const FString& Subdomain)
{
const TSharedPtr<FJsonObject> DataObject = MakeShared<FJsonObject>();
DataObject->SetStringField(JSON_FIELD_CODE, Code);
DataObject->SetStringField(JSON_FIELD_APP_NAME, Subdomain);
return FDataJsonUtils::MakePayload(DataObject);
}

FString FUserDataExtractor::MakeAuthAnonymousPayload(const FString& Subdomain)
{
const TSharedPtr<FJsonObject> DataObject = MakeShared<FJsonObject>();
DataObject->SetStringField(JSON_FIELD_APP_NAME, Subdomain);
DataObject->SetBoolField(JSON_FIELD_REQUEST_TOKEN, true);
return FDataJsonUtils::MakeDataPayload(DataObject);
}


FString FUserDataExtractor::MakeTokenRefreshPayload(const FRpmUserData& UserData)
{
const TSharedPtr<FJsonObject> DataObject = MakeShared<FJsonObject>();
DataObject->SetStringField(JSON_FIELD_REFRESH_TOKEN, UserData.RefreshToken);
DataObject->SetStringField(JSON_FIELD_TOKEN, UserData.Token);
return FDataJsonUtils::MakeDataPayload(DataObject);
return FDataJsonUtils::MakePayload(DataObject);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ class FUserDataExtractor

static FRpmUserData ExtractRefreshedUserSession(const FString& JsonString);

static FString MakeAuthStartPayload(const FString& Email, const FString& UserId, bool bIsTypeCode);
static FString MakeRequestLoginCodePayload(const FString& Email, const FString& UserId, const FString& Subdomain);

static FString MakeConfirmCodePayload(const FString& Code);
static FString MakeConfirmCodePayload(const FString& Code, const FString& Subdomain);

static FString MakeAuthAnonymousPayload(const FString& Subdomain);

static FString MakeTokenRefreshPayload(const FRpmUserData& UserData);
};
21 changes: 10 additions & 11 deletions Source/RpmAvatarCreator/Private/Requests/Endpoints.cpp
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
// Copyright © 2023++ Ready Player Me


#include "Endpoints.h"
#include "RpmAvatarCreatorTypes.h"

static const TCHAR* API_ENDPOINT = TEXT("https://{0}.readyplayer.me/api{1}");
static const TCHAR* API_ENDPOINT = TEXT("https://api.readyplayer.me/v1{0}");
static const TCHAR* AVATAR_API_V2_ENDPOINT = TEXT("https://api.readyplayer.me/v2/avatars");
static const TCHAR* AVATAR_API_V1_ENDPOINT = TEXT("https://api.readyplayer.me/v1/avatars");
static const TCHAR* ASSET_ENDPOINT = TEXT("https://api.readyplayer.me/v1/assets?type={0}&limit={1}&page={2}&filter=viewable-by-user-and-app&filterUserId={3}&filterApplicationId={4}");
static const TCHAR* REQUEST_OPTIMIZATION_PARAMS = TEXT("morphTargets=none&textureAtlas=none&textureSizeLimit=768&lod=0&useHands=false");
static const TCHAR* MODELS_URL_PREFIX = TEXT("https://models.readyplayer.me");

FString FEndpoints::GetAuthAnonymousEndpoint(const FString& Subdomain)
FString FEndpoints::GetAuthAnonymousEndpoint()
{
return FString::Format(API_ENDPOINT, {Subdomain, TEXT("/users")});
return FString::Format(API_ENDPOINT, {TEXT("/users")});
}

FString FEndpoints::GetAuthStartEndpoint(const FString& Subdomain)
FString FEndpoints::GetRequestLoginCodeEndpoint()
{
return FString::Format(API_ENDPOINT, {Subdomain, TEXT("/auth/start")});
return FString::Format(API_ENDPOINT, {TEXT("/auth/request-login-code")});
}

FString FEndpoints::GetConfirmCodeEndpoint(const FString& Subdomain)
FString FEndpoints::GetConfirmCodeEndpoint()
{
return FString::Format(API_ENDPOINT, {Subdomain, TEXT("/auth/login")});
return FString::Format(API_ENDPOINT, {TEXT("/auth/login")});
}

FString FEndpoints::GetTokenRefreshEndpoint(const FString& Subdomain)
FString FEndpoints::GetTokenRefreshEndpoint()
{
return FString::Format(API_ENDPOINT, {Subdomain, TEXT("/auth/refresh")});
return FString::Format(API_ENDPOINT, {TEXT("/auth/refresh")});
}

FString FEndpoints::GetAssetEndpoint(const FString& AssetTypeStr, int32 Limit, int32 Page, const FString& UserId, const FString& AppId)
{
return FString::Format(ASSET_ENDPOINT, { AssetTypeStr, Limit, Page, UserId, AppId});
return FString::Format(ASSET_ENDPOINT, {AssetTypeStr, Limit, Page, UserId, AppId});
}

FString FEndpoints::GetColorEndpoint(const FString& AvatarId)
Expand Down
8 changes: 4 additions & 4 deletions Source/RpmAvatarCreator/Private/Requests/Endpoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ enum class ERpmAvatarTemplateType : uint8;
class FEndpoints
{
public:
static FString GetAuthAnonymousEndpoint(const FString& Subdomain);
static FString GetAuthAnonymousEndpoint();

static FString GetAuthStartEndpoint(const FString& Subdomain);
static FString GetRequestLoginCodeEndpoint();

static FString GetConfirmCodeEndpoint(const FString& Subdomain);
static FString GetConfirmCodeEndpoint();

static FString GetTokenRefreshEndpoint(const FString& Subdomain);
static FString GetTokenRefreshEndpoint();

static FString GetCreateFromTemplateEndpoint(const FString& TemplateId = "");

Expand Down
13 changes: 6 additions & 7 deletions Source/RpmAvatarCreator/Private/Requests/RequestFactory.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright © 2023++ Ready Player Me


#include "RequestFactory.h"

#include "CoreMinimal.h"
Expand Down Expand Up @@ -55,24 +54,24 @@ void FRequestFactory::CancelRequests() const
CancellationDelegate->Broadcast();
}

TSharedPtr<IBaseRequest> FRequestFactory::CreateAuthStartRequest(const FString& PayloadJson) const
TSharedPtr<IBaseRequest> FRequestFactory::CreateRequestLoginCodeRequest(const FString& PayloadJson) const
{
return CreateBaseRequest(FEndpoints::GetAuthStartEndpoint(Subdomain), ERequestVerb::Post, PayloadJson);
return CreateBaseRequest(FEndpoints::GetRequestLoginCodeEndpoint(), ERequestVerb::Post, PayloadJson);
}

TSharedPtr<IBaseRequest> FRequestFactory::CreateConfirmCodeRequest(const FString& PayloadJson) const
{
return CreateBaseRequest(FEndpoints::GetConfirmCodeEndpoint(Subdomain), ERequestVerb::Post, PayloadJson);
return CreateBaseRequest(FEndpoints::GetConfirmCodeEndpoint(), ERequestVerb::Post, PayloadJson);
}

TSharedPtr<IBaseRequest> FRequestFactory::CreateTokenRefreshRequest() const
{
return CreateBaseRequest(FEndpoints::GetTokenRefreshEndpoint(Subdomain), ERequestVerb::Post, FUserDataExtractor::MakeTokenRefreshPayload(UserData));
return CreateBaseRequest(FEndpoints::GetTokenRefreshEndpoint(), ERequestVerb::Post, FUserDataExtractor::MakeTokenRefreshPayload(UserData));
}

TSharedPtr<IBaseRequest> FRequestFactory::CreateAuthAnonymousRequest() const
TSharedPtr<IBaseRequest> FRequestFactory::CreateAuthAnonymousRequest(const FString& PayloadJson) const
{
return CreateBaseRequest(FEndpoints::GetAuthAnonymousEndpoint(Subdomain), ERequestVerb::Post);
return CreateBaseRequest(FEndpoints::GetAuthAnonymousEndpoint(), ERequestVerb::Post, PayloadJson);
}

TSharedPtr<IBaseRequest> FRequestFactory::CreateAvatarTemplatesRequest(const EAvatarBodyType& BodyType) const
Expand Down
4 changes: 2 additions & 2 deletions Source/RpmAvatarCreator/Private/Requests/RequestFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ class FRequestFactory

void CancelRequests() const;

TSharedPtr<IBaseRequest> CreateAuthStartRequest(const FString& PayloadJson) const;
TSharedPtr<IBaseRequest> CreateRequestLoginCodeRequest(const FString& PayloadJson) const;
TSharedPtr<IBaseRequest> CreateConfirmCodeRequest(const FString& PayloadJson) const;
TSharedPtr<IBaseRequest> CreateTokenRefreshRequest() const;
TSharedPtr<IBaseRequest> CreateAuthAnonymousRequest() const;
TSharedPtr<IBaseRequest> CreateAuthAnonymousRequest(const FString& PayloadJson) const;
TSharedPtr<IBaseRequest> CreateAssetRequest(const FString& AssetTypeStr, int32 Limit, int32 Page) const;
TSharedPtr<IBaseRequest> CreateColorRequest(const FString& AvatarId) const;
TSharedPtr<IBaseRequest> CreateAvatarModelRequest(const FString& AvatarId, bool bIsPreview) const;
Expand Down
6 changes: 3 additions & 3 deletions Source/RpmAvatarCreator/Private/RpmAvatarCreatorApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ void URpmAvatarCreatorApi::AuthAnonymous(const FAuthenticationCompleted& Complet
AuthManager->AuthAnonymous(Completed, Failed);
}

void URpmAvatarCreatorApi::AuthStart(const FString& Email, bool bIsTypeCode, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed)
void URpmAvatarCreatorApi::RequestLoginCode(const FString& Email, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed)
{
AuthManager->AuthStart(Email, bIsTypeCode, Completed, Failed);
AuthManager->RequestLoginCode(Email, Completed, Failed);
}

void URpmAvatarCreatorApi::ConfirmActivationCode(const FString& Code, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed)
void URpmAvatarCreatorApi::ConfirmLoginCode(const FString& Code, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed)
{
AuthManager->ConfirmActivationCode(Code, Completed, Failed);
}
Expand Down
8 changes: 4 additions & 4 deletions Source/RpmAvatarCreator/Public/RpmAvatarCreatorApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ class RPMAVATARCREATOR_API URpmAvatarCreatorApi : public UObject
UFUNCTION(BlueprintCallable, Category = "Ready Player Me", meta = (DisplayName = "Authorize Anonymous"))
void AuthAnonymous(const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);

UFUNCTION(BlueprintCallable, Category = "Ready Player Me", meta = (DisplayName = "Authorization Start"))
void AuthStart(const FString& Email, bool bIsTypeCode, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);
UFUNCTION(BlueprintCallable, Category = "Ready Player Me", meta = (DisplayName = "Request Login Code"))
void RequestLoginCode(const FString& Email, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);

UFUNCTION(BlueprintCallable, Category = "Ready Player Me", meta = (DisplayName = "Confirm Activation Code"))
void ConfirmActivationCode(const FString& Code, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);
UFUNCTION(BlueprintCallable, Category = "Ready Player Me", meta = (DisplayName = "Confirm Login Code"))
void ConfirmLoginCode(const FString& Code, const FAuthenticationCompleted& Completed, const FAvatarCreatorFailed& Failed);

UFUNCTION(BlueprintCallable, Category = "Ready Player Me", meta = (DisplayName = "LogOut"))
void LogOut();
Expand Down

0 comments on commit e6c6424

Please sign in to comment.