Skip to content

Commit

Permalink
[SDK-600] Feature/avatar template element (#164)
Browse files Browse the repository at this point in the history
- added avatar template element and other required logic and classes + prefabs
  • Loading branch information
HarrisonHough authored and rYuuk committed Nov 29, 2023
1 parent 5fc145b commit c986eac
Show file tree
Hide file tree
Showing 39 changed files with 1,658 additions and 105 deletions.
61 changes: 61 additions & 0 deletions Runtime/AvatarCreator/AvatarTemplateFetcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace ReadyPlayerMe.AvatarCreator
{
/// <summary>
/// This class can be used to fetch avatar template data including icon renders from the avatarAPI.
/// </summary>
public class AvatarTemplateFetcher
{
private readonly CancellationToken ctx;
private readonly AvatarAPIRequests avatarAPIRequests;

public AvatarTemplateFetcher(CancellationToken ctx = default)
{
this.ctx = ctx;
avatarAPIRequests = new AvatarAPIRequests(ctx);
}

/// <summary>
/// Fetches all avatar templates without the icon renders via the avatarAPI.
/// </summary>
/// <returns></returns>
public async Task<List<AvatarTemplateData>> GetTemplates()
{
return await avatarAPIRequests.GetAvatarTemplates();
}

/// <summary>
/// Fetches all avatar template data with the icon renders via the avatarAPI.
/// This will wait for all the icons to be downloaded.
/// </summary>
/// <returns></returns>
public async Task<List<AvatarTemplateData>> GetTemplatesWithRenders()
{
var templates = await avatarAPIRequests.GetAvatarTemplates();
return await FetchTemplateRenders(templates);
}

/// <summary>
/// Fetches the renders for all the templates provided.
/// </summary>
public async Task<List<AvatarTemplateData>> FetchTemplateRenders(List<AvatarTemplateData> templates)
{
var tasks = templates.Select(async templateData =>
{
templateData.Texture = await avatarAPIRequests.GetAvatarTemplateImage(templateData.ImageUrl);
}).ToList();

while (!tasks.All(x => x.IsCompleted) &&
!ctx.IsCancellationRequested)
{
await Task.Yield();
}

return templates;
}
}
}
13 changes: 13 additions & 0 deletions Runtime/AvatarCreator/Data/AssetLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace ReadyPlayerMe.AvatarCreator
{
public struct AssetLibrary
{
public PartnerAsset[] Assets;
public Pagination Pagination;
}

public struct Pagination
{
public int TotalPages;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace ReadyPlayerMe.AvatarCreator
{
[Serializable]
public class TemplateData
public class AvatarTemplateData
{
public string ImageUrl;
[JsonConverter(typeof(GenderConverter))]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
using Newtonsoft.Json;
using Newtonsoft.Json;
using ReadyPlayerMe.Core;

namespace ReadyPlayerMe.AvatarCreator
{
public struct AssetData
{
public PartnerAsset[] Assets;
public Pagination Pagination;
}

public struct PartnerAsset
{
public string Id;
Expand All @@ -17,15 +11,8 @@ public struct PartnerAsset
[JsonConverter(typeof(GenderConverter))]
public OutfitGender Gender;
[JsonProperty("iconUrl")]
public string Icon;
[JsonProperty("maskUrl")]
public string Mask;
public string ImageUrl;
[JsonProperty("lockedCategories")]
public string[] LockedCategories;
}

public struct Pagination
{
public int TotalPages;
}
}
11 changes: 11 additions & 0 deletions Runtime/AvatarCreator/Data/PartnerAsset.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Runtime/AvatarCreator/PartnerAssetsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public PartnerAssetsManager()
assetsByCategory = new Dictionary<Category, List<PartnerAsset>>();
}

public async Task<Dictionary<Category,List<PartnerAsset>>> GetAssets(BodyType bodyType, OutfitGender gender, CancellationToken token = default)
public async Task<Dictionary<Category, List<PartnerAsset>>> GetAssets(BodyType bodyType, OutfitGender gender, CancellationToken token = default)
{
var startTime = Time.time;

Expand Down Expand Up @@ -96,7 +96,7 @@ private async Task DownloadIcons(List<PartnerAsset> chunk, Action<string, Textur

foreach (var asset in chunk)
{
var url = asset.Category == Category.EyeColor ? asset.Mask + EYE_MASK_SIZE_SIZE : asset.Icon + ASSET_ICON_SIZE;
var url = $"{asset.ImageUrl}{ASSET_ICON_SIZE}";
var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
var iconTask = partnerAssetsRequests.GetAssetIcon(url, icon =>
{
Expand Down Expand Up @@ -126,7 +126,7 @@ public PrecompileData GetPrecompileData(Category[] categories, int numberOfAsset
.Select(kvp => kvp.Key)
.ToArray();

var dictionary = categoriesFromMap.ToDictionary(category => category, category =>
var dictionary = categoriesFromMap.ToDictionary(category => category, category =>
GetAssetsByCategory(CategoryHelper.PartnerCategoryMap[category])
.Take(numberOfAssetsPerCategory)
.ToArray());
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

210 changes: 210 additions & 0 deletions Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &313019198674256499
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 313019198674256498}
- component: {fileID: 313019198674256496}
- component: {fileID: 313019198674256497}
m_Layer: 5
m_Name: RawImage
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &313019198674256498
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019198674256499}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 313019200304032552}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &313019198674256496
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019198674256499}
m_CullTransparentMesh: 1
--- !u!114 &313019198674256497
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019198674256499}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
--- !u!1 &313019200304032553
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 313019200304032552}
- component: {fileID: 313019200304032557}
- component: {fileID: 313019200304032558}
- component: {fileID: 313019200304032559}
- component: {fileID: 313019200304032556}
m_Layer: 5
m_Name: ButtonElement
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &313019200304032552
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019200304032553}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 313019198674256498}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 180, y: 180}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &313019200304032557
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019200304032553}
m_CullTransparentMesh: 1
--- !u!114 &313019200304032558
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019200304032553}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 0}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 4d267838cc649284dac0e347a0072f24, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &313019200304032559
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019200304032553}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 313019200304032558}
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &313019200304032556
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 313019200304032553}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f2bb8ce1b8cb99c40b9103b9350c8105, type: 3}
m_Name:
m_EditorClassIdentifier:
button: {fileID: 313019200304032559}
rawImage: {fileID: 313019198674256497}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c986eac

Please sign in to comment.