Skip to content

Commit

Permalink
Merge branch 'release/v6.3.0' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
HarrisonHough committed Jun 11, 2024
2 parents aaebf80 + d7c8963 commit 444efae
Show file tree
Hide file tree
Showing 51 changed files with 2,857 additions and 4,021 deletions.
14 changes: 13 additions & 1 deletion .github/latest.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@

## Changelog

### Updated

- XR animation avatars now have DOF enabled by default [#288](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/288)
- Updated InCreatorAvatarLoader to use avatar config [#286](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/286)
- Avatar Creator Icon categories updated [#272](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/272)

### Fixed

- Updated XR template prefab meshes to prevent missing bone references to fix mexh transfer [#266](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/266)
- Fixed an issue preventing LOD's from updating [#277](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/277)
- An issue causing multiple signup requests [#275](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/275)

### Added
- Avatar template type filter [#270](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/270)
- Handle failed body shape requests [#281](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/281)
- Option to filter Templates by gender [#273](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/273)
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,29 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [6.3.0] - 2024.06.11

### Updated

- XR animation avatars now have DOF enabled by default [#288](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/288)
- Updated InCreatorAvatarLoader to use avatar config [#286](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/286)
- Avatar Creator Icon categories updated [#272](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/272)

### Fixed

- Fixed an issue preventing LOD's from updating [#277](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/277)
- An issue causing multiple signup requests [#275](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/275)

### Added
- Avatar template type filter [#270](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/270)
- Handle failed body shape requests [#281](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/281)
- Option to filter Templates by gender [#273](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/273)

## [6.2.4] - 2024.05.03

### Fixed

- Updated XR template prefab meshes to prevent missing bone references to fix mexh transfer [#266](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/266)
- Updated XR template prefab meshes to prevent missing bone references to fix mesh transfer [#266](https://github.com/readyplayerme/rpm-unity-sdk-core/pull/266)

## [6.2.3] - 2024.04.29

Expand Down
2 changes: 1 addition & 1 deletion Editor/Core/Scripts/Analytics/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static class Links
{
public const string DOCS_PARTNERS_LINK = "https://docs.readyplayer.me/ready-player-me/what-is-ready-player-me#url";
public const string DOCS_DEFER_AGENT_LINK = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/optimize/defer-agents";
public const string DOCS_LOAD_AVATAR = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/load-avatars#save-avatars-as-npcs-in-your-project";
public const string DOCS_AVATAR_LOADER_WINDOW = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/avatar-loader-window";
public const string DOCS_AVATAR_CONFIG_LINK = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/optimize/avatar-configuration";
public const string DOCS_AVATAR_CACHING = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/optimize/avatar-caching";
public const string APP_ID = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/avatar-creator/custom-avatar-creator#prerequisites";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class SettingsEditor : EditorWindow
private const string LOGGING_ENABLED_TOGGLE = "LoggingEnabledToggle";
private const string DOCUMENTATION_BUTTON = "DocumentationButton";
private const string FAQ_BUTTON = "FaqButton";
private const string DISCORD_BUTTON = "DiscordButton";
private const string FORUM_BUTTON = "ForumButton";
private const string CLEAR_CACHE = "Clear Cache";
private const string CACHE_IS_ALREADY_EMPTY = "Cache is already empty";
private const string OK = "OK";
Expand All @@ -39,7 +39,7 @@ public class SettingsEditor : EditorWindow

private const string DOCS_URL = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity";
private const string FAQ_URL = "https://docs.readyplayer.me/ready-player-me/integration-guides/unity/faq-for-unity";
private const string DISCORD_URL = "https://bit.ly/UnitySDKDiscord";
private const string FORUM_URL = "https://forum.readyplayer.me/";
private const string PRIVACY_POLICY_LABEL = "PrivacyPolicyLabel";

[SerializeField] private VisualTreeAsset visualTreeAsset;
Expand Down Expand Up @@ -94,7 +94,7 @@ public void CreateGUI()

rootVisualElement.Q<Button>(DOCUMENTATION_BUTTON).clicked += () => Application.OpenURL(DOCS_URL);
rootVisualElement.Q<Button>(FAQ_BUTTON).clicked += () => Application.OpenURL(FAQ_URL);
rootVisualElement.Q<Button>(DISCORD_BUTTON).clicked += () => Application.OpenURL(DISCORD_URL);
rootVisualElement.Q<Button>(FORUM_BUTTON).clicked += () => Application.OpenURL(FORUM_URL);
}

private void OnCachingHelpClick()
Expand All @@ -105,7 +105,7 @@ private void OnCachingHelpClick()

private void OnAvatarCachingToggle(ChangeEvent<bool> evt)
{
AvatarLoaderSettingsHelper.AvatarLoaderSettings.AvatarCachingEnabled = evt.newValue;
AvatarLoaderSettingsHelper.SetAvatarCaching(evt.newValue);
AnalyticsEditorLogger.EventLogger.LogSetCachingEnabled(evt.newValue);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<ui:VisualElement name="Buttons" style="flex-grow: 0; background-color: rgba(0, 0, 0, 0); flex-direction: row; align-self: auto; justify-content: space-between; align-items: center; height: 40px; margin-left: 15px; margin-right: 15px; margin-top: 10px; width: 450px; flex-shrink: 0;">
<ui:Button text="Documentation" display-tooltip-when-elided="true" name="DocumentationButton" style="width: 150px; align-items: auto; flex-grow: 0; justify-content: space-around; align-self: stretch; margin-left: 0; margin-right: 0;" />
<ui:Button text="FAQ" display-tooltip-when-elided="true" name="FaqButton" style="width: 150px; justify-content: space-around; align-self: stretch; align-items: auto; margin-left: 6px;" />
<ui:Button text="Discord" display-tooltip-when-elided="true" name="DiscordButton" style="width: 150px; justify-content: space-around; align-self: stretch; align-items: auto; margin-right: 0;" />
<ui:Button text="Forum" display-tooltip-when-elided="true" name="ForumButton" style="width: 150px; justify-content: space-around; align-self: stretch; align-items: auto; margin-right: 0;" />
</ui:VisualElement>
</ui:VisualElement>
</ui:VisualElement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class AvatarUrlTemplate : VisualElement
private const string URL_ELEMENT = "UrlField";
private const string ERROR_LABEL = "ErrorLabel";
private const string HELP_BUTTON = "HelpButton";
private const string ERROR_HELP_URL = "https://docs.readyplayer.me/ready-player-me/avatars/avatar-creator#avatar-url-and-data-format";
private const string ERROR_HELP_URL = "https://docs.readyplayer.me/ready-player-me/customizing-guides/avatar-creator/avatar-urls";

public new class UxmlFactory : UxmlFactory<AvatarUrlTemplate, UxmlTraits>
{
Expand Down Expand Up @@ -48,7 +48,7 @@ public AvatarUrlTemplate()
helpButton.clicked += () =>
{
AnalyticsEditorLogger.EventLogger.LogFindOutMore(HelpSubject.LoadingAvatars);
Application.OpenURL(Constants.Links.DOCS_LOAD_AVATAR);
Application.OpenURL(Constants.Links.DOCS_AVATAR_LOADER_WINDOW);
};
}

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
7 changes: 7 additions & 0 deletions Runtime/AvatarCreator/Scripts/AvatarTemplateFetcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

namespace ReadyPlayerMe.AvatarCreator
{
public enum TemplateVersions
{
All,
V1,
V2
}

/// <summary>
/// This class can be used to fetch avatar template data including icon renders from the avatarAPI.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions Runtime/AvatarCreator/Scripts/Data/AvatarTemplateData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ public class AvatarTemplateData : IAssetData
[JsonConverter(typeof(GenderConverter))]
public OutfitGender Gender;
public Texture Texture;
public string UsageType;
}
}
2 changes: 2 additions & 0 deletions Runtime/AvatarCreator/Scripts/Data/PartnerAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,7 @@ public struct PartnerAsset : IAssetData
public string ImageUrl;
[JsonProperty("lockedCategories")]
public string[] LockedCategories;
[JsonProperty("locked")]
public bool Locked;
}
}
13 changes: 12 additions & 1 deletion Runtime/AvatarCreator/Scripts/InCreatorAvatarLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ namespace ReadyPlayerMe.AvatarCreator
/// </summary>
public class InCreatorAvatarLoader
{
private readonly AvatarConfig avatarConfig;

public InCreatorAvatarLoader(AvatarConfig avatarConfig = null)
{
if (avatarConfig == null)
{
avatarConfig = AvatarLoaderSettings.LoadSettings().AvatarConfig;
}
this.avatarConfig = avatarConfig;
}

public async Task<GameObject> Load(string avatarId, BodyType bodyType, OutfitGender gender, byte[] data)
{
var avatarMetadata = new AvatarMetadata();
Expand All @@ -20,7 +31,7 @@ public async Task<GameObject> Load(string avatarId, BodyType bodyType, OutfitGen
context.AvatarUri.Guid = avatarId;
context.AvatarCachingEnabled = false;
context.Metadata = avatarMetadata;

context.AvatarConfig = avatarConfig;
var executor = new OperationExecutor<AvatarContext>(new IOperation<AvatarContext>[]
{
new GltFastAvatarImporter(),
Expand Down
20 changes: 17 additions & 3 deletions Runtime/AvatarCreator/Scripts/Managers/AuthManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using ReadyPlayerMe.Core;

Expand Down Expand Up @@ -42,7 +42,14 @@ public static void SetUser(UserSession session)

public static async void SendEmailCode(string email)
{
await AuthAPIRequests.SendCodeToEmail(email, userSession.Id);
try
{
await AuthAPIRequests.SendCodeToEmail(email, userSession.Id);
}
catch (Exception e)
{
OnSignInError?.Invoke(e.Message);
}
}

public static async Task<bool> LoginWithCode(string otp, string userIdToMerge = null)
Expand All @@ -63,7 +70,14 @@ public static async Task<bool> LoginWithCode(string otp, string userIdToMerge =

public static async void Signup(string email)
{
await AuthAPIRequests.Signup(email, userSession.Id);
try
{
await AuthAPIRequests.Signup(email, userSession.Id);
}
catch (Exception e)
{
OnSignInError?.Invoke(e.Message);
}
}

public static async Task RefreshToken()
Expand Down
28 changes: 27 additions & 1 deletion Runtime/AvatarCreator/Scripts/Managers/AvatarManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public AvatarCreationResponse(GameObject avatarObject, AvatarProperties properti
/// </summary>
public class AvatarManager : IDisposable
{
private const string ERROR_BODYSHAPES_NOT_ENABLED = "Failed to apply body shapes to the avatar. Please ensure body shapes are enabled in your studio application.";

private const string TAG = nameof(AvatarManager);
private readonly AvatarAPIRequests avatarAPIRequests;
private readonly string avatarConfigParameters;
Expand All @@ -48,7 +50,7 @@ public AvatarManager(AvatarConfig avatarConfig = null, CancellationToken token =
}

ctxSource = CancellationTokenSource.CreateLinkedTokenSource(token);
inCreatorAvatarLoader = new InCreatorAvatarLoader();
inCreatorAvatarLoader = new InCreatorAvatarLoader(avatarConfig);
avatarAPIRequests = new AvatarAPIRequests(ctxSource.Token);
}

Expand Down Expand Up @@ -288,9 +290,33 @@ public async Task<GameObject> UpdateAsset(AssetType assetType, BodyType bodyType
{
return null;
}
await ValidateBodyShapeUpdate(assetType, assetId);


return await inCreatorAvatarLoader.Load(avatarId, bodyType, gender, data);
}

/// <summary>
/// Function that checks if body shapes are enabled in the studio. This validation is performed only in the editor.
/// </summary>
/// <param name="assetType">Assets type that was updated</param>
/// <param name="assetId">Asset ID</param>
private async Task ValidateBodyShapeUpdate(AssetType assetType, object assetId)
{
if (assetType != AssetType.BodyShape)
{
return;
}

var data = await avatarAPIRequests.GetAvatarMetadata(avatarId, true);
var hasUpdatedAvatarWithAsset = data.Assets.ContainsKey(assetType) && data.Assets[assetType] == assetId;
if (hasUpdatedAvatarWithAsset)
{
return;
}
Debug.LogError(ERROR_BODYSHAPES_NOT_ENABLED);
}


public async Task<Dictionary<AssetType, AssetColor[]>> LoadAvatarColors()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ public class AssetSelectionElement : SelectionElement
[SerializeField] private int iconSize = 64;

private PartnerAsset[] assets;

private AssetAPIRequests assetsRequests;
private AssetAPIRequests AssetsRequests => assetsRequests ??= new AssetAPIRequests(CoreSettingsHandler.CoreSettings.AppId);

private void Awake()
{
assetsRequests = new AssetAPIRequests(CoreSettingsHandler.CoreSettings.AppId);
if (clearSelectionButton == null) return;
AddClearButton(clearSelectionButton, assetType);
}
Expand All @@ -52,7 +53,7 @@ public void SetBodyType(BodyType bodyType)
/// <returns>A Task representing the asynchronous operation of fetching and loading the partner asset data.</returns>
public async Task LoadAssetData(OutfitGender gender)
{
assets = await assetsRequests.Get(assetType, bodyType, gender);
assets = await AssetsRequests.Get(assetType, bodyType, gender);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ReadyPlayerMe.Core;
using UnityEngine;

namespace ReadyPlayerMe.AvatarCreator
{
Expand All @@ -13,29 +16,71 @@ namespace ReadyPlayerMe.AvatarCreator
public class TemplateSelectionElement : SelectionElement
{
private const string TAG = nameof(TemplateSelectionElement);
[SerializeField] private TemplateVersions templateVersions = TemplateVersions.V2;
private List<AvatarTemplateData> avatarTemplates;
private AvatarTemplateFetcher avatarTemplateFetcher;
private CancellationToken ctx;

private const string TEMPLATE_V2_USAGE_TYPE = "onboarding";
private const string TEMPLATE_V1_USAGE_TYPE = "randomize";

private void Awake()
{
avatarTemplateFetcher = new AvatarTemplateFetcher();
avatarTemplateFetcher = new AvatarTemplateFetcher(ctx);
}


/// <summary>
/// Asynchronously loads avatar template data and creates button elements for each template.
/// Each button is created with an icon fetched from the template's image URL.
/// </summary>
public async void LoadAndCreateButtons()
{
await LoadAndCreateButtons(OutfitGender.None);
}

/// <summary>
/// Asynchronously loads avatar template data and creates button elements for each template based on the gender.
/// Each button is created with an icon fetched from the template's image URL.
/// <param name="gender">Gender for which the templates are loaded for</param>
/// </summary>
public async Task LoadAndCreateButtons(OutfitGender gender)
{
await LoadTemplateData();
CreateButtons(avatarTemplates.ToArray(), async (button, asset) =>

var filteredTemplates = avatarTemplates!.Where(template => HasCorrectTemplateVersion(template) && HasCorrectGender(template, gender)).ToList();

CreateButtons(filteredTemplates!.ToArray(), async (button, asset) =>
{
var webRequestDispatcher = new WebRequestDispatcher();
var url = $"{asset.ImageUrl}";
var texture = await webRequestDispatcher.DownloadTexture(url);
button.SetIcon(texture);
});
}

private bool HasCorrectTemplateVersion(AvatarTemplateData template)
{
switch (templateVersions)
{
case TemplateVersions.V2:
return template.UsageType.Contains(TEMPLATE_V2_USAGE_TYPE);
case TemplateVersions.V1:
return template.UsageType.Contains(TEMPLATE_V1_USAGE_TYPE);
case TemplateVersions.All:
default:
return true;
}
}

private bool HasCorrectGender(AvatarTemplateData template, OutfitGender gender)
{
if (gender == OutfitGender.None || template.Gender == OutfitGender.None)
{
return true;
}
return gender == template.Gender;
}

/// <summary>
/// Loads avatar template data asynchronously.
Expand Down
Loading

0 comments on commit 444efae

Please sign in to comment.