Skip to content

Commit

Permalink
Feature/asset panel element (#175)
Browse files Browse the repository at this point in the history
- Adds an asset panel element and prefab
- includes some major refactoring and other breaking API changes
  • Loading branch information
HarrisonHough authored Dec 5, 2023
1 parent 72b4cc3 commit 6bc99aa
Show file tree
Hide file tree
Showing 55 changed files with 2,806 additions and 403 deletions.
24 changes: 14 additions & 10 deletions Runtime/AvatarCreator/AvatarManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ReadyPlayerMe.Core;
Expand Down Expand Up @@ -160,21 +161,21 @@ public async Task<GameObject> GetAvatar(string id, BodyType bodyType, bool isPre
/// Update an asset of the avatar.
/// </summary>
/// <param name="assetId"></param>
/// <param name="category"></param>
/// <param name="assetType"></param>
/// <returns>Avatar gameObject</returns>
public async Task<GameObject> UpdateAsset(Category category,BodyType bodyType, object assetId)
public async Task<GameObject> UpdateAsset(AssetType assetType, BodyType bodyType, object assetId)
{
var payload = new AvatarProperties
{
Assets = new Dictionary<Category, object>()
Assets = new Dictionary<AssetType, object>()
};

if (category == Category.Top || category == Category.Bottom || category == Category.Footwear)
if (assetType == AssetType.Top || assetType == AssetType.Bottom || assetType == AssetType.Footwear)
{
payload.Assets.Add(Category.Outfit, string.Empty);
payload.Assets.Add(AssetType.Outfit, string.Empty);
}

payload.Assets.Add(category, assetId);
payload.Assets.Add(assetType, assetId);

byte[] data;
try
Expand All @@ -195,19 +196,22 @@ public async Task<GameObject> UpdateAsset(Category category,BodyType bodyType, o
return await inCreatorAvatarLoader.Load(avatarId, bodyType, gender, data);
}

public async Task<ColorPalette[]> LoadAvatarColors()
public async Task<Dictionary<AssetType, AssetColor[]>> LoadAvatarColors()
{
ColorPalette[] colors = null;
var assetColorsByAssetType = new Dictionary<AssetType, AssetColor[]>();
try
{
colors = await avatarAPIRequests.GetAllAvatarColors(avatarId);
var assetColors = await avatarAPIRequests.GetAvatarColors(avatarId);
assetColorsByAssetType = assetColors
.GroupBy(color => color.AssetType)
.ToDictionary(group => group.Key, group => group.ToArray());
}
catch (Exception e)
{
OnError?.Invoke(e.Message);
}

return colors;
return assetColorsByAssetType;
}

/// <summary>
Expand Down
15 changes: 9 additions & 6 deletions Runtime/AvatarCreator/AvatarTemplateFetcher.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ReadyPlayerMe.Core;

namespace ReadyPlayerMe.AvatarCreator
{
Expand Down Expand Up @@ -33,20 +35,21 @@ public async Task<List<AvatarTemplateData>> GetTemplates()
/// This will wait for all the icons to be downloaded.
/// </summary>
/// <returns></returns>
public async Task<List<AvatarTemplateData>> GetTemplatesWithRenders()
public async Task<List<AvatarTemplateData>> GetTemplatesWithRenders(Action<AvatarTemplateData> onIconDownloaded = null)
{
var templates = await avatarAPIRequests.GetAvatarTemplates();
return await FetchTemplateRenders(templates);
return await FetchTemplateRenders(await avatarAPIRequests.GetAvatarTemplates(), onIconDownloaded);
}

/// <summary>
/// Fetches the renders for all the templates provided.
/// </summary>
public async Task<List<AvatarTemplateData>> FetchTemplateRenders(List<AvatarTemplateData> templates)
public async Task<List<AvatarTemplateData>> FetchTemplateRenders(List<AvatarTemplateData> templates, Action<AvatarTemplateData> onIconDownloaded = null)
{
var tasks = templates.Select(async templateData =>
{
templateData.Texture = await avatarAPIRequests.GetAvatarTemplateImage(templateData.ImageUrl);
var requestDispatcher = new WebRequestDispatcher();
templateData.Texture = await requestDispatcher.DownloadTexture(templateData.ImageUrl, ctx);
onIconDownloaded?.Invoke(templateData);
}).ToList();

while (!tasks.All(x => x.IsCompleted) &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace ReadyPlayerMe.AvatarCreator
{
public enum Category
public enum AssetType
{
None,
SkinColor,
Expand All @@ -23,6 +23,7 @@ public enum Category
BeardColor,
Bottom,
Top,
Footwear
Footwear,
AvatarTemplate
}
}
File renamed without changes.
2 changes: 1 addition & 1 deletion Runtime/AvatarCreator/Data/AvatarProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public struct AvatarProperties
[JsonConverter(typeof(BodyTypeConverter))]
public BodyType BodyType;
[JsonConverter(typeof(CategoryDictionaryConverter))]
public Dictionary<Category, object> Assets;
public Dictionary<AssetType, object> Assets;
public string Base64Image;
}
}
42 changes: 21 additions & 21 deletions Runtime/AvatarCreator/Data/AvatarPropertiesConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@ namespace ReadyPlayerMe.AvatarCreator
{
public static class AvatarPropertiesConstants
{
public static readonly Dictionary<Category, object> MaleDefaultAssets =
new Dictionary<Category, object>
public static readonly Dictionary<AssetType, object> MaleDefaultAssets =
new Dictionary<AssetType, object>
{
{ Category.SkinColor, 5 },
{ Category.EyeColor, "9781796" },
{ Category.HairStyle, "9247476" },
{ Category.EyebrowStyle, "16858292" },
{ Category.Outfit, "109373713" },
{ Category.HairColor, 0 },
{ Category.EyebrowColor, 0 },
{ Category.BeardColor, 0 }
{ AssetType.SkinColor, 5 },
{ AssetType.EyeColor, "9781796" },
{ AssetType.HairStyle, "9247476" },
{ AssetType.EyebrowStyle, "16858292" },
{ AssetType.Outfit, "109373713" },
{ AssetType.HairColor, 0 },
{ AssetType.EyebrowColor, 0 },
{ AssetType.BeardColor, 0 }
};
public static readonly Dictionary<Category, object> FemaleDefaultAssets =
new Dictionary<Category, object>

public static readonly Dictionary<AssetType, object> FemaleDefaultAssets =
new Dictionary<AssetType, object>
{
{ Category.SkinColor, 5 },
{ Category.EyeColor, "9781796" },
{ Category.HairStyle, "9247476" },
{ Category.EyebrowStyle, "16858292" },
{ Category.Outfit, "109376347" },
{ Category.HairColor, 0 },
{ Category.EyebrowColor, 0 },
{ Category.BeardColor, 0 }
{ AssetType.SkinColor, 5 },
{ AssetType.EyeColor, "9781796" },
{ AssetType.HairStyle, "9247476" },
{ AssetType.EyebrowStyle, "16858292" },
{ AssetType.Outfit, "109376347" },
{ AssetType.HairColor, 0 },
{ AssetType.EyebrowColor, 0 },
{ AssetType.BeardColor, 0 }
};
}
}
5 changes: 3 additions & 2 deletions Runtime/AvatarCreator/Data/AvatarTemplateData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
namespace ReadyPlayerMe.AvatarCreator
{
[Serializable]
public class AvatarTemplateData
public class AvatarTemplateData : IAssetData
{
public string Id { get; set; }
public AssetType AssetType { get; set; } = AssetType.AvatarTemplate;
public string ImageUrl;
[JsonConverter(typeof(GenderConverter))]
public OutfitGender Gender;
public string Id;
public Texture Texture;
}
}
28 changes: 28 additions & 0 deletions Runtime/AvatarCreator/Data/ColorLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System;

namespace ReadyPlayerMe.AvatarCreator
{
[Serializable]
public struct ColorLibrary
{
public AssetColor[] Skin;
public AssetColor[] Eyebrow;
public AssetColor[] Beard;
public AssetColor[] Hair;
}

[Serializable]
public struct AssetColor : IAssetData
{
public string Id { get; set; }
public AssetType AssetType { get; set; }
public string HexColor;

public AssetColor(string id, AssetType assetType, string hexColor)
{
Id = id;
AssetType = assetType;
HexColor = hexColor;
}
}
}
17 changes: 0 additions & 17 deletions Runtime/AvatarCreator/Data/ColorPalette.cs

This file was deleted.

8 changes: 5 additions & 3 deletions Runtime/AvatarCreator/Data/PartnerAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

namespace ReadyPlayerMe.AvatarCreator
{
public struct PartnerAsset
public struct PartnerAsset : IAssetData
{
public string Id;
public string Id { get; set; }

[JsonProperty("type"), JsonConverter(typeof(CategoryConverter))]
public Category Category;
public AssetType AssetType { get; set; }

[JsonConverter(typeof(GenderConverter))]
public OutfitGender Gender;
[JsonProperty("iconUrl")]
Expand Down
8 changes: 8 additions & 0 deletions Runtime/AvatarCreator/IAssetData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ReadyPlayerMe.AvatarCreator
{
public interface IAssetData
{
public string Id { get; set; }
public AssetType AssetType { get; set; }
}
}
11 changes: 11 additions & 0 deletions Runtime/AvatarCreator/IAssetData.cs.meta

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

8 changes: 4 additions & 4 deletions Runtime/AvatarCreator/JsonHelpers/CategoryConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class CategoryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Category);
return objectType == typeof(AssetType);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
Expand All @@ -23,12 +23,12 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
{
throw new JsonSerializationException("Expected string value");
}

if (!CategoryHelper.PartnerCategoryMap.ContainsKey(token.ToString()))
{
return Category.None;
return AssetType.None;
}

return CategoryHelper.PartnerCategoryMap[token.ToString()];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

namespace ReadyPlayerMe.AvatarCreator
{
public class CategoryDictionaryConverter : JsonConverter<Dictionary<Category, object>>
public class CategoryDictionaryConverter : JsonConverter<Dictionary<AssetType, object>>
{
public override void WriteJson(JsonWriter writer, Dictionary<Category, object> value, JsonSerializer serializer)
public override void WriteJson(JsonWriter writer, Dictionary<AssetType, object> value, JsonSerializer serializer)
{
var newValue = new Dictionary<string, object>();
foreach (var element in value)
Expand All @@ -20,11 +20,11 @@ public override void WriteJson(JsonWriter writer, Dictionary<Category, object> v
serializer.Serialize(writer, newValue);
}

public override Dictionary<Category, object> ReadJson(JsonReader reader, Type objectType,
Dictionary<Category, object> existingValue, bool hasExistingValue, JsonSerializer serializer)
public override Dictionary<AssetType, object> ReadJson(JsonReader reader, Type objectType,
Dictionary<AssetType, object> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var token = JToken.Load(reader);
var assets = new Dictionary<Category, object>();
var assets = new Dictionary<AssetType, object>();
if (token.Type == JTokenType.Object)
{
foreach (var element in token.ToObject<Dictionary<string, object>>())
Expand All @@ -35,18 +35,18 @@ public override Dictionary<Category, object> ReadJson(JsonReader reader, Type ob
}

var pascalCaseKey = char.ToUpperInvariant(element.Key[0]) + element.Key.Substring(1);
if (!Enum.IsDefined(typeof(Category), pascalCaseKey))
if (!Enum.IsDefined(typeof(AssetType), pascalCaseKey))
{
continue;
}
var category = (Category) Enum.Parse(typeof(Category), pascalCaseKey);
var category = (AssetType) Enum.Parse(typeof(AssetType), pascalCaseKey);
assets.Add(category, element.Value);
}
}

return assets;
}

private bool CanSkipProperty(string propertyName)
{
return propertyName == "createdAt" || propertyName == "updatedAt" || propertyName == "skinColorHex";
Expand Down
Loading

0 comments on commit 6bc99aa

Please sign in to comment.