diff --git a/Runtime/AvatarCreator/AvatarTemplateFetcher.cs b/Runtime/AvatarCreator/AvatarTemplateFetcher.cs new file mode 100644 index 00000000..ea9b2fbe --- /dev/null +++ b/Runtime/AvatarCreator/AvatarTemplateFetcher.cs @@ -0,0 +1,61 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ReadyPlayerMe.AvatarCreator +{ + /// + /// This class can be used to fetch avatar template data including icon renders from the avatarAPI. + /// + public class AvatarTemplateFetcher + { + private readonly CancellationToken ctx; + private readonly AvatarAPIRequests avatarAPIRequests; + + public AvatarTemplateFetcher(CancellationToken ctx = default) + { + this.ctx = ctx; + avatarAPIRequests = new AvatarAPIRequests(ctx); + } + + /// + /// Fetches all avatar templates without the icon renders via the avatarAPI. + /// + /// + public async Task> GetTemplates() + { + return await avatarAPIRequests.GetAvatarTemplates(); + } + + /// + /// Fetches all avatar template data with the icon renders via the avatarAPI. + /// This will wait for all the icons to be downloaded. + /// + /// + public async Task> GetTemplatesWithRenders() + { + var templates = await avatarAPIRequests.GetAvatarTemplates(); + return await FetchTemplateRenders(templates); + } + + /// + /// Fetches the renders for all the templates provided. + /// + public async Task> FetchTemplateRenders(List 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; + } + } +} diff --git a/Runtime/AvatarCreator/TemplateFetcher.cs.meta b/Runtime/AvatarCreator/AvatarTemplateFetcher.cs.meta similarity index 100% rename from Runtime/AvatarCreator/TemplateFetcher.cs.meta rename to Runtime/AvatarCreator/AvatarTemplateFetcher.cs.meta diff --git a/Runtime/AvatarCreator/Data/AssetLibrary.cs b/Runtime/AvatarCreator/Data/AssetLibrary.cs new file mode 100644 index 00000000..7262f5df --- /dev/null +++ b/Runtime/AvatarCreator/Data/AssetLibrary.cs @@ -0,0 +1,13 @@ +namespace ReadyPlayerMe.AvatarCreator +{ + public struct AssetLibrary + { + public PartnerAsset[] Assets; + public Pagination Pagination; + } + + public struct Pagination + { + public int TotalPages; + } +} diff --git a/Runtime/AvatarCreator/Data/AssetData.cs.meta b/Runtime/AvatarCreator/Data/AssetLibrary.cs.meta similarity index 100% rename from Runtime/AvatarCreator/Data/AssetData.cs.meta rename to Runtime/AvatarCreator/Data/AssetLibrary.cs.meta diff --git a/Runtime/AvatarCreator/Data/TemplateData.cs b/Runtime/AvatarCreator/Data/AvatarTemplateData.cs similarity index 90% rename from Runtime/AvatarCreator/Data/TemplateData.cs rename to Runtime/AvatarCreator/Data/AvatarTemplateData.cs index 2a6b33df..8a2e2e82 100644 --- a/Runtime/AvatarCreator/Data/TemplateData.cs +++ b/Runtime/AvatarCreator/Data/AvatarTemplateData.cs @@ -6,7 +6,7 @@ namespace ReadyPlayerMe.AvatarCreator { [Serializable] - public class TemplateData + public class AvatarTemplateData { public string ImageUrl; [JsonConverter(typeof(GenderConverter))] diff --git a/Runtime/AvatarCreator/Data/TemplateData.cs.meta b/Runtime/AvatarCreator/Data/AvatarTemplateData.cs.meta similarity index 100% rename from Runtime/AvatarCreator/Data/TemplateData.cs.meta rename to Runtime/AvatarCreator/Data/AvatarTemplateData.cs.meta diff --git a/Runtime/AvatarCreator/Data/AssetData.cs b/Runtime/AvatarCreator/Data/PartnerAsset.cs similarity index 59% rename from Runtime/AvatarCreator/Data/AssetData.cs rename to Runtime/AvatarCreator/Data/PartnerAsset.cs index 3068e399..2be6205e 100644 --- a/Runtime/AvatarCreator/Data/AssetData.cs +++ b/Runtime/AvatarCreator/Data/PartnerAsset.cs @@ -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; @@ -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; - } } diff --git a/Runtime/AvatarCreator/Data/PartnerAsset.cs.meta b/Runtime/AvatarCreator/Data/PartnerAsset.cs.meta new file mode 100644 index 00000000..7f07bb17 --- /dev/null +++ b/Runtime/AvatarCreator/Data/PartnerAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2719f45a60bfd443829b433870e2b2f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/PartnerAssetsManager.cs b/Runtime/AvatarCreator/PartnerAssetsManager.cs index 0b04661b..a10ec13f 100644 --- a/Runtime/AvatarCreator/PartnerAssetsManager.cs +++ b/Runtime/AvatarCreator/PartnerAssetsManager.cs @@ -29,7 +29,7 @@ public PartnerAssetsManager() assetsByCategory = new Dictionary>(); } - public async Task>> GetAssets(BodyType bodyType, OutfitGender gender, CancellationToken token = default) + public async Task>> GetAssets(BodyType bodyType, OutfitGender gender, CancellationToken token = default) { var startTime = Time.time; @@ -96,7 +96,7 @@ private async Task DownloadIcons(List chunk, Action { @@ -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()); diff --git a/Samples~/AvatarCreatorSamples/Animation.meta b/Runtime/AvatarCreator/Prefabs/Buttons.meta similarity index 77% rename from Samples~/AvatarCreatorSamples/Animation.meta rename to Runtime/AvatarCreator/Prefabs/Buttons.meta index 07df5826..3e0d12b6 100644 --- a/Samples~/AvatarCreatorSamples/Animation.meta +++ b/Runtime/AvatarCreator/Prefabs/Buttons.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 00c61768e54e74847ae8eae5451e814c +guid: 1905c62487498da4fa24e3814cb88488 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab b/Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab new file mode 100644 index 00000000..f24f91ca --- /dev/null +++ b/Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab @@ -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} diff --git a/Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab.meta b/Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab.meta new file mode 100644 index 00000000..e1938e66 --- /dev/null +++ b/Runtime/AvatarCreator/Prefabs/Buttons/ButtonElement.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ce3fe0e72fd9a77428b183a9cd5e759d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Samples~/AvatarCreatorSamples.meta b/Runtime/AvatarCreator/Prefabs/Elements.meta similarity index 77% rename from Samples~/AvatarCreatorSamples.meta rename to Runtime/AvatarCreator/Prefabs/Elements.meta index 05cbb749..061f1f46 100644 --- a/Samples~/AvatarCreatorSamples.meta +++ b/Runtime/AvatarCreator/Prefabs/Elements.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 70001abd8d1cd8340abd6780f341090d +guid: 5444cb4a645f5c247ba946120c4f6961 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Runtime/AvatarCreator/Prefabs/Gender Select Element.prefab b/Runtime/AvatarCreator/Prefabs/Elements/Gender Select Element.prefab similarity index 100% rename from Runtime/AvatarCreator/Prefabs/Gender Select Element.prefab rename to Runtime/AvatarCreator/Prefabs/Elements/Gender Select Element.prefab diff --git a/Runtime/AvatarCreator/Prefabs/Gender Select Element.prefab.meta b/Runtime/AvatarCreator/Prefabs/Elements/Gender Select Element.prefab.meta similarity index 100% rename from Runtime/AvatarCreator/Prefabs/Gender Select Element.prefab.meta rename to Runtime/AvatarCreator/Prefabs/Elements/Gender Select Element.prefab.meta diff --git a/Runtime/AvatarCreator/Prefabs/Login Element.prefab b/Runtime/AvatarCreator/Prefabs/Elements/Login Element.prefab similarity index 100% rename from Runtime/AvatarCreator/Prefabs/Login Element.prefab rename to Runtime/AvatarCreator/Prefabs/Elements/Login Element.prefab diff --git a/Runtime/AvatarCreator/Prefabs/Login Element.prefab.meta b/Runtime/AvatarCreator/Prefabs/Elements/Login Element.prefab.meta similarity index 100% rename from Runtime/AvatarCreator/Prefabs/Login Element.prefab.meta rename to Runtime/AvatarCreator/Prefabs/Elements/Login Element.prefab.meta diff --git a/Runtime/AvatarCreator/Prefabs/Elements/TemplateAvatarElement.prefab b/Runtime/AvatarCreator/Prefabs/Elements/TemplateAvatarElement.prefab new file mode 100644 index 00000000..c81d5421 --- /dev/null +++ b/Runtime/AvatarCreator/Prefabs/Elements/TemplateAvatarElement.prefab @@ -0,0 +1,958 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &6589403853584343126 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403853584343121} + - component: {fileID: 6589403853584343122} + - component: {fileID: 6589403853584343123} + - component: {fileID: 6589403853584343120} + m_Layer: 5 + m_Name: Viewport + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403853584343121 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853584343126} + 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: 6589403854928128197} + m_Father: {fileID: 6589403853685394405} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!222 &6589403853584343122 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853584343126} + m_CullTransparentMesh: 1 +--- !u!114 &6589403853584343123 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853584343126} + 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: 1} + 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: 10917, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + 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 &6589403853584343120 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853584343126} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 31a19414c41e5ae4aae2af33fee712f6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ShowMaskGraphic: 0 +--- !u!1 &6589403853685394426 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403853685394405} + - component: {fileID: 6589403853685394406} + - component: {fileID: 6589403853685394407} + - component: {fileID: 6589403853685394404} + m_Layer: 5 + m_Name: Scroll View + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403853685394405 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853685394426} + 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: 6589403853584343121} + - {fileID: 6589403854428310035} + - {fileID: 6589403854979376061} + m_Father: {fileID: 6589403854911528367} + 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 &6589403853685394406 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853685394426} + m_CullTransparentMesh: 1 +--- !u!114 &6589403853685394407 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853685394426} + 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.392} + 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: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + 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 &6589403853685394404 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853685394426} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1aa08ab6e0800fa44ae55d278d1423e3, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Content: {fileID: 6589403854928128197} + m_Horizontal: 1 + m_Vertical: 1 + m_MovementType: 1 + m_Elasticity: 0.1 + m_Inertia: 1 + m_DecelerationRate: 0.135 + m_ScrollSensitivity: 1 + m_Viewport: {fileID: 6589403853584343121} + m_HorizontalScrollbar: {fileID: 6589403854428310034} + m_VerticalScrollbar: {fileID: 6589403854979376060} + m_HorizontalScrollbarVisibility: 2 + m_VerticalScrollbarVisibility: 2 + m_HorizontalScrollbarSpacing: -3 + m_VerticalScrollbarSpacing: -3 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6589403853780214098 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403853780214109} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403853780214109 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853780214098} + 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: 6589403853870299954} + m_Father: {fileID: 6589403854979376061} + 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: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &6589403853870299955 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403853870299954} + - component: {fileID: 6589403853870299964} + - component: {fileID: 6589403853870299965} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403853870299954 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853870299955} + 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: 6589403853780214109} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6589403853870299964 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853870299955} + m_CullTransparentMesh: 1 +--- !u!114 &6589403853870299965 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403853870299955} + 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: 1} + 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: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + 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!1 &6589403854428310032 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403854428310035} + - component: {fileID: 6589403854428310044} + - component: {fileID: 6589403854428310045} + - component: {fileID: 6589403854428310034} + m_Layer: 5 + m_Name: Scrollbar Horizontal + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403854428310035 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854428310032} + 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: 6589403855242158143} + m_Father: {fileID: 6589403853685394405} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 20} + m_Pivot: {x: 0, y: 0} +--- !u!222 &6589403854428310044 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854428310032} + m_CullTransparentMesh: 1 +--- !u!114 &6589403854428310045 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854428310032} + 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: 1} + 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: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + 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 &6589403854428310034 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854428310032} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, 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: 6589403855323154307} + m_HandleRect: {fileID: 6589403855323154304} + m_Direction: 0 + m_Value: 0 + m_Size: 1 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6589403854911528364 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403854911528367} + - component: {fileID: 6589403854911528366} + m_Layer: 5 + m_Name: TemplateAvatarElement + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403854911528367 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854911528364} + 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: 6589403853685394405} + - {fileID: 5637435583784712114} + 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: 600, y: 600} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &6589403854911528366 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854911528364} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8f457777c7050774eabede44ca3068b9, type: 3} + m_Name: + m_EditorClassIdentifier: + buttonElementPrefab: {fileID: 313019200304032556, guid: ce3fe0e72fd9a77428b183a9cd5e759d, + type: 3} + buttonContainer: {fileID: 6589403854928128197} + selectedIcon: {fileID: 5637435583784712115} + onTemplateSelected: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6589403854928128218 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403854928128197} + - component: {fileID: 6589403854928128199} + - component: {fileID: 6589403854928128196} + m_Layer: 5 + m_Name: ButtonContainer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403854928128197 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854928128218} + 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: 6589403853584343121} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 1} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 1} +--- !u!114 &6589403854928128199 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854928128218} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8a8695521f0d02e499659fee002a26c2, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Padding: + m_Left: 0 + m_Right: 0 + m_Top: 0 + m_Bottom: 0 + m_ChildAlignment: 1 + m_StartCorner: 0 + m_StartAxis: 0 + m_CellSize: {x: 180, y: 180} + m_Spacing: {x: 20, y: 20} + m_Constraint: 0 + m_ConstraintCount: 2 +--- !u!114 &6589403854928128196 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854928128218} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3245ec927659c4140ac4f8d17403cc18, type: 3} + m_Name: + m_EditorClassIdentifier: + m_HorizontalFit: 0 + m_VerticalFit: 1 +--- !u!1 &6589403854979376050 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403854979376061} + - component: {fileID: 6589403854979376062} + - component: {fileID: 6589403854979376063} + - component: {fileID: 6589403854979376060} + m_Layer: 5 + m_Name: Scrollbar Vertical + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403854979376061 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854979376050} + 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: 6589403853780214109} + m_Father: {fileID: 6589403853685394405} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0} + m_AnchorMax: {x: 1, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 0} + m_Pivot: {x: 1, y: 1} +--- !u!222 &6589403854979376062 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854979376050} + m_CullTransparentMesh: 1 +--- !u!114 &6589403854979376063 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854979376050} + 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: 1} + 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: 10907, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + 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 &6589403854979376060 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403854979376050} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 2a4db7a114972834c8e4117be1d82ba3, 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: 6589403853870299965} + m_HandleRect: {fileID: 6589403853870299954} + m_Direction: 2 + m_Value: 0 + m_Size: 1 + m_NumberOfSteps: 0 + m_OnValueChanged: + m_PersistentCalls: + m_Calls: [] +--- !u!1 &6589403855242158140 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403855242158143} + m_Layer: 5 + m_Name: Sliding Area + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403855242158143 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403855242158140} + 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: 6589403855323154304} + m_Father: {fileID: 6589403854428310035} + 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: -20, y: -20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1 &6589403855323154305 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6589403855323154304} + - component: {fileID: 6589403855323154306} + - component: {fileID: 6589403855323154307} + m_Layer: 5 + m_Name: Handle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6589403855323154304 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403855323154305} + 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: 6589403855242158143} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 20, y: 20} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &6589403855323154306 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403855323154305} + m_CullTransparentMesh: 1 +--- !u!114 &6589403855323154307 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589403855323154305} + 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: 1} + 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: 10905, guid: 0000000000000000f000000000000000, type: 0} + m_Type: 1 + 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!1001 &3297507354955669938 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 6589403854911528367} + m_Modifications: + - target: {fileID: 3067042867859571005, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_Color.b + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3067042867859571005, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_Color.g + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3067042867859571005, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_Color.r + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_RootOrder + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_AnchorMax.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_AnchorMax.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_AnchorMin.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_AnchorMin.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_SizeDelta.x + value: 180 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_SizeDelta.y + value: 180 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870081, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_Name + value: SelectIcon + objectReference: {fileID: 0} + - target: {fileID: 7205522718613870081, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: d9b672212a2f80d4e9d3a90957f01b4a, type: 3} +--- !u!1 &5637435583784712115 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 7205522718613870081, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + m_PrefabInstance: {fileID: 3297507354955669938} + m_PrefabAsset: {fileID: 0} +--- !u!224 &5637435583784712114 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 7205522718613870080, guid: d9b672212a2f80d4e9d3a90957f01b4a, + type: 3} + m_PrefabInstance: {fileID: 3297507354955669938} + m_PrefabAsset: {fileID: 0} diff --git a/Runtime/AvatarCreator/Prefabs/Elements/TemplateAvatarElement.prefab.meta b/Runtime/AvatarCreator/Prefabs/Elements/TemplateAvatarElement.prefab.meta new file mode 100644 index 00000000..2f6e61af --- /dev/null +++ b/Runtime/AvatarCreator/Prefabs/Elements/TemplateAvatarElement.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f50201018cf1fde428ce508968a48aab +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/Prefabs/SelectIcon.prefab b/Runtime/AvatarCreator/Prefabs/SelectIcon.prefab new file mode 100644 index 00000000..919709ae --- /dev/null +++ b/Runtime/AvatarCreator/Prefabs/SelectIcon.prefab @@ -0,0 +1,153 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &5149030114720533458 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1691293831886794332} + - component: {fileID: 1426928142945932389} + - component: {fileID: 3067042867859571005} + m_Layer: 5 + m_Name: Image + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1691293831886794332 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5149030114720533458} + 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: 7205522718613870080} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 20, y: 20} + m_SizeDelta: {x: 30, y: 30} + m_Pivot: {x: 0, y: 0} +--- !u!222 &1426928142945932389 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5149030114720533458} + m_CullTransparentMesh: 1 +--- !u!114 &3067042867859571005 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5149030114720533458} + 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: 0, g: 0.9706273, 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_Sprite: {fileID: 10913, guid: 0000000000000000f000000000000000, type: 0} + 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!1 &7205522718613870081 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7205522718613870080} + - component: {fileID: 7205522718613870085} + - component: {fileID: 7205522718613870086} + m_Layer: 5 + m_Name: SelectIcon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7205522718613870080 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7205522718613870081} + 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: 1691293831886794332} + 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 &7205522718613870085 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7205522718613870081} + m_CullTransparentMesh: 1 +--- !u!114 &7205522718613870086 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7205522718613870081} + 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: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 diff --git a/Runtime/AvatarCreator/Prefabs/SelectIcon.prefab.meta b/Runtime/AvatarCreator/Prefabs/SelectIcon.prefab.meta new file mode 100644 index 00000000..67c29b40 --- /dev/null +++ b/Runtime/AvatarCreator/Prefabs/SelectIcon.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d9b672212a2f80d4e9d3a90957f01b4a +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/TemplateFetcher.cs b/Runtime/AvatarCreator/TemplateFetcher.cs deleted file mode 100644 index 7c524c37..00000000 --- a/Runtime/AvatarCreator/TemplateFetcher.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace ReadyPlayerMe.AvatarCreator -{ - public class TemplateFetcher - { - private readonly CancellationToken ctx; - private readonly AvatarAPIRequests avatarAPIRequests; - private readonly List templates; - - public TemplateFetcher(CancellationToken ctx = default) - { - this.ctx = ctx; - avatarAPIRequests = new AvatarAPIRequests(ctx); - templates = new List(); - } - - public async Task> GetTemplates() - { - var avatarTemplates = await avatarAPIRequests.GetTemplates(); - await GetAllTemplateRenders(avatarTemplates); - return templates; - } - - private async Task GetAllTemplateRenders(IEnumerable templateAvatars) - { - var downloadRenderTasks = templateAvatars.Select(GetAvatarRender).ToList(); - - while (!downloadRenderTasks.All(x => x.IsCompleted) && !ctx.IsCancellationRequested) - { - await Task.Yield(); - } - } - - private async Task GetAvatarRender(TemplateData templateData) - { - templateData.Texture = await avatarAPIRequests.GetTemplateAvatarImage(templateData.ImageUrl); - templates.Add(templateData); - } - } -} diff --git a/Runtime/AvatarCreator/UI/Buttons.meta b/Runtime/AvatarCreator/UI/Buttons.meta new file mode 100644 index 00000000..5bc5d170 --- /dev/null +++ b/Runtime/AvatarCreator/UI/Buttons.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 63f8c7f7b91dd6544b6c0005d8193c91 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/UI/Buttons/ButtonElement.cs b/Runtime/AvatarCreator/UI/Buttons/ButtonElement.cs new file mode 100644 index 00000000..eaad4c21 --- /dev/null +++ b/Runtime/AvatarCreator/UI/Buttons/ButtonElement.cs @@ -0,0 +1,36 @@ +using System; +using UnityEngine; +using UnityEngine.UI; + +namespace ReadyPlayerMe.AvatarCreator +{ + /// + /// A basic button element with an icon and functionality to bind an action to the + /// buttons onClick event. + /// + public class ButtonElement : MonoBehaviour + { + [SerializeField] private Button button; + [SerializeField] private RawImage rawImage; + + /// + /// Adds a listener to the button's onClick event. + /// + /// A function to run when the button is clicked + public void AddListener(Action action) + { + button.onClick.AddListener(action.Invoke); + } + + /// + /// Sets the icon on the rawImage component + /// + /// The texture to be assigned to the RawImage component + /// If true the icon will resize itself to fit inside the parent RectTransform + public void SetIcon(Texture texture, bool sizeToParent = true) + { + rawImage.texture = texture; + if (sizeToParent) rawImage.SizeToParent(); + } + } +} diff --git a/Runtime/AvatarCreator/UI/Buttons/ButtonElement.cs.meta b/Runtime/AvatarCreator/UI/Buttons/ButtonElement.cs.meta new file mode 100644 index 00000000..db02d20e --- /dev/null +++ b/Runtime/AvatarCreator/UI/Buttons/ButtonElement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2bb8ce1b8cb99c40b9103b9350c8105 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/UI/Elements.meta b/Runtime/AvatarCreator/UI/Elements.meta new file mode 100644 index 00000000..db80f69f --- /dev/null +++ b/Runtime/AvatarCreator/UI/Elements.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9737a9df6a271cc469285aefce58e439 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/UI/Elements/AvatarTemplateElement.cs b/Runtime/AvatarCreator/UI/Elements/AvatarTemplateElement.cs new file mode 100644 index 00000000..596e7d36 --- /dev/null +++ b/Runtime/AvatarCreator/UI/Elements/AvatarTemplateElement.cs @@ -0,0 +1,119 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using ReadyPlayerMe.Core; +using UnityEngine; +using UnityEngine.Events; + +namespace ReadyPlayerMe.AvatarCreator +{ + /// + /// This class can be used as a self contained UI element that can fetch AvatarTemplates + /// and create it's own buttons. + /// + public class AvatarTemplateElement : MonoBehaviour + { + private const string TAG = nameof(AvatarTemplateElement); + + [Header("UI Elements")] + [Space(5)] + [SerializeField] private ButtonElement buttonElementPrefab; + [SerializeField] private Transform buttonContainer; + [SerializeField] private GameObject selectedIcon; + + [Header("Events")] + [Space(5)] + public UnityEvent onTemplateSelected; + + private List avatarTemplateDataList; + private ButtonElement[] templateAvatarButtons; + private AvatarTemplateFetcher avatarTemplateFetcher; + + private void Awake() + { + avatarTemplateFetcher = new AvatarTemplateFetcher(); + } + + /// + /// This function will automatically fetch the template data including the icon renders and create buttons. + /// + public async void LoadAndCreateButtons() + { + await LoadTemplateRenders(); + CreateButtons(); + } + + /// + /// Loads avatar template data without fetching the icon renders. + /// + public async void LoadTemplateData() + { + avatarTemplateDataList = await avatarTemplateFetcher.GetTemplates(); + if (avatarTemplateDataList == null || avatarTemplateDataList.Count == 0) + { + SDKLogger.LogWarning(TAG, "No templates found"); + } + } + + /// + /// Loads avatar template data and icon renders. This will wait for all the icons to be downloaded. + /// + public async Task LoadTemplateRenders() + { + avatarTemplateDataList = await avatarTemplateFetcher.GetTemplatesWithRenders(); + } + + /// + /// Creates buttons from the loaded template data and sets the icon and button event. + /// + public void CreateButtons() + { + if (avatarTemplateDataList.Count == 0) + { + SDKLogger.LogWarning(TAG, "No templates found. You need to load fetch the template data first."); + return; + } + templateAvatarButtons = new ButtonElement[avatarTemplateDataList.Count]; + for (var i = 0; i < avatarTemplateDataList.Count; i++) + { + var button = Instantiate(buttonElementPrefab, buttonContainer); + var templateData = avatarTemplateDataList[i]; + button.SetIcon(templateData.Texture); + button.AddListener(() => TemplateSelected(button.transform, templateData)); + templateAvatarButtons[i] = button; + } + } + + private void ClearButtons() + { + if (templateAvatarButtons == null) return; + + foreach (var button in templateAvatarButtons) + { + Destroy(button.gameObject); + } + templateAvatarButtons = null; + } + + /// + /// This function is called when a template button is clicked. + /// + /// The buttonTransform is used to position the selectedIcon to indicate which button was last selected + /// This data is used passed in the onSelectedTemplate event + private void TemplateSelected(Transform buttonTransform, AvatarTemplateData avatarTemplateData) + { + onTemplateSelected?.Invoke(avatarTemplateData); + SetButtonSelected(buttonTransform); + } + + /// + /// Sets the position and parent of the SelectedIcon to indicate which button was last selected. + /// + /// + private void SetButtonSelected(Transform buttonTransform) + { + selectedIcon.transform.SetParent(buttonTransform); + selectedIcon.transform.localPosition = Vector3.zero; + selectedIcon.SetActive(true); + } + } +} diff --git a/Runtime/AvatarCreator/UI/Elements/AvatarTemplateElement.cs.meta b/Runtime/AvatarCreator/UI/Elements/AvatarTemplateElement.cs.meta new file mode 100644 index 00000000..2429a5dc --- /dev/null +++ b/Runtime/AvatarCreator/UI/Elements/AvatarTemplateElement.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f457777c7050774eabede44ca3068b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/AvatarCreator/UI/GenderSelectElement.cs b/Runtime/AvatarCreator/UI/Elements/GenderSelectElement.cs similarity index 100% rename from Runtime/AvatarCreator/UI/GenderSelectElement.cs rename to Runtime/AvatarCreator/UI/Elements/GenderSelectElement.cs diff --git a/Runtime/AvatarCreator/UI/GenderSelectElement.cs.meta b/Runtime/AvatarCreator/UI/Elements/GenderSelectElement.cs.meta similarity index 100% rename from Runtime/AvatarCreator/UI/GenderSelectElement.cs.meta rename to Runtime/AvatarCreator/UI/Elements/GenderSelectElement.cs.meta diff --git a/Runtime/AvatarCreator/UI/LoginElement.cs b/Runtime/AvatarCreator/UI/Elements/LoginElement.cs similarity index 90% rename from Runtime/AvatarCreator/UI/LoginElement.cs rename to Runtime/AvatarCreator/UI/Elements/LoginElement.cs index a483dca5..65faa22d 100644 --- a/Runtime/AvatarCreator/UI/LoginElement.cs +++ b/Runtime/AvatarCreator/UI/Elements/LoginElement.cs @@ -6,6 +6,10 @@ namespace ReadyPlayerMe.AvatarCreator { + /// + /// This class provides all the functionality required to create a basic Login UI element + /// for building a Custom Avatar Creator. + /// public class LoginElement : MonoBehaviour { private const string TAG = nameof(LoginElement); diff --git a/Runtime/AvatarCreator/UI/LoginElement.cs.meta b/Runtime/AvatarCreator/UI/Elements/LoginElement.cs.meta similarity index 100% rename from Runtime/AvatarCreator/UI/LoginElement.cs.meta rename to Runtime/AvatarCreator/UI/Elements/LoginElement.cs.meta diff --git a/Samples~/AvatarCreatorSamples/Scripts/Utils/RawImageExtensions.cs b/Runtime/AvatarCreator/Utils/RawImageExtensions.cs similarity index 97% rename from Samples~/AvatarCreatorSamples/Scripts/Utils/RawImageExtensions.cs rename to Runtime/AvatarCreator/Utils/RawImageExtensions.cs index f42c0f79..69e5e953 100644 --- a/Samples~/AvatarCreatorSamples/Scripts/Utils/RawImageExtensions.cs +++ b/Runtime/AvatarCreator/Utils/RawImageExtensions.cs @@ -1,7 +1,7 @@ using UnityEngine; using UnityEngine.UI; -namespace ReadyPlayerMe +namespace ReadyPlayerMe.AvatarCreator { public static class RawImageExtensions { diff --git a/Samples~/AvatarCreatorSamples/Scripts/Utils/RawImageExtensions.cs.meta b/Runtime/AvatarCreator/Utils/RawImageExtensions.cs.meta similarity index 100% rename from Samples~/AvatarCreatorSamples/Scripts/Utils/RawImageExtensions.cs.meta rename to Runtime/AvatarCreator/Utils/RawImageExtensions.cs.meta diff --git a/Runtime/AvatarCreator/WebRequests/AvatarAPIRequests.cs b/Runtime/AvatarCreator/WebRequests/AvatarAPIRequests.cs index 0d247eb5..b8447cb5 100644 --- a/Runtime/AvatarCreator/WebRequests/AvatarAPIRequests.cs +++ b/Runtime/AvatarCreator/WebRequests/AvatarAPIRequests.cs @@ -44,7 +44,7 @@ public async Task> GetUserAvatars(string userId) return data.ToDictionary(element => element[ID]!.ToString(), element => element[PARTNER]!.ToString()); } - public async Task> GetTemplates() + public async Task> GetAvatarTemplates() { var response = await authorizedRequest.SendRequest( new RequestData @@ -58,10 +58,10 @@ public async Task> GetTemplates() var json = JObject.Parse(response.Text); var data = json[DATA]!; - return JsonConvert.DeserializeObject>(data.ToString()); + return JsonConvert.DeserializeObject>(data.ToString()); } - public async Task GetTemplateAvatarImage(string url) + public async Task GetAvatarTemplateImage(string url) { var downloadHandler = new DownloadHandlerTexture(); var webRequestDispatcher = new WebRequestDispatcher(); diff --git a/Runtime/AvatarCreator/WebRequests/PartnerAssetsRequests.cs b/Runtime/AvatarCreator/WebRequests/PartnerAssetsRequests.cs index d24e0522..d424bfec 100644 --- a/Runtime/AvatarCreator/WebRequests/PartnerAssetsRequests.cs +++ b/Runtime/AvatarCreator/WebRequests/PartnerAssetsRequests.cs @@ -30,21 +30,21 @@ public PartnerAssetsRequests(string appId) public async Task Get(BodyType bodyType, OutfitGender gender, CancellationToken ctx = new CancellationToken()) { var assets = new HashSet(); - AssetData assetData; + AssetLibrary assetLibrary; try { - assetData = await GetRequest(LIMIT, 1, null, gender, bodyType, ctx: ctx); - assets.UnionWith(assetData.Assets); + assetLibrary = await GetRequest(LIMIT, 1, null, gender, bodyType, ctx: ctx); + assets.UnionWith(assetLibrary.Assets); } catch (Exception) { return assets.ToArray(); } - var assetRequests = new Task[assetData.Pagination.TotalPages - 1]; + var assetRequests = new Task[assetLibrary.Pagination.TotalPages - 1]; - for (var i = 2; i <= assetData.Pagination.TotalPages; i++) + for (var i = 2; i <= assetLibrary.Pagination.TotalPages; i++) { assetRequests[i - 2] = GetRequest(LIMIT, i, null, gender, bodyType, ctx: ctx); } @@ -84,7 +84,7 @@ public PartnerAssetsRequests(string appId) return assets.ToArray(); } - private async Task GetRequest(int limit, int pageNumber, Category? category, OutfitGender gender, BodyType bodyType, CancellationToken ctx = new CancellationToken()) + private async Task GetRequest(int limit, int pageNumber, Category? category, OutfitGender gender, BodyType bodyType, CancellationToken ctx = new CancellationToken()) { var startTime = Time.time; @@ -93,9 +93,9 @@ public PartnerAssetsRequests(string appId) { type = CategoryHelper.PartnerCategoryMap.First(x => x.Value == category).Key; } - + var url = AssetEndpoints.GetAssetEndpoint(type, limit, pageNumber, AuthManager.UserSession.Id, appId, gender == OutfitGender.Masculine ? "male" : "female"); - + var response = await authorizedRequest.SendRequest(new RequestData { Url = url, @@ -116,7 +116,7 @@ public PartnerAssetsRequests(string appId) SDKLogger.Log(TAG, $"Asset with page {pageNumber} received: {Time.time - startTime}s"); } - return new AssetData + return new AssetLibrary { Assets = partnerAssets, Pagination = pagination diff --git a/Samples~/AvatarCreatorSamples/Scripts/UI/AssetButtonCreator.cs b/Samples~/AvatarCreatorSamples/Scripts/UI/AssetButtonCreator.cs index c6febd8a..341b5f03 100644 --- a/Samples~/AvatarCreatorSamples/Scripts/UI/AssetButtonCreator.cs +++ b/Samples~/AvatarCreatorSamples/Scripts/UI/AssetButtonCreator.cs @@ -145,17 +145,13 @@ private void AddAssetButton(string assetId, Transform parent, Category category, SelectButton(category, assetButton); onClick?.Invoke(assetId, category); }); - if (category == Category.EyeColor) - { - assetButton.SetEyeColorConfig(); - } buttonsById.Add(assetId, assetButton); } - + private void SelectButton(Category category, AssetButton assetButton) { ConfigureOutfitSelection(category); - + if (selectedButtonsByCategory.ContainsKey(category)) { selectedButtonsByCategory[category].SetSelect(false); @@ -188,12 +184,12 @@ private void ConfigureOutfitSelection(Category category) { topButton.SetSelect(false); } - + if (selectedButtonsByCategory.TryGetValue(Category.Bottom, out AssetButton bottomButton)) { bottomButton.SetSelect(false); } - + if (selectedButtonsByCategory.TryGetValue(Category.Footwear, out AssetButton footwearButton)) { footwearButton.SetSelect(false); @@ -228,6 +224,5 @@ private bool IsSelectedAssetNotPresentForCategory(Category category) string.IsNullOrEmpty(selectedAssetIdByCategory[category] as string); } - } } diff --git a/Samples~/AvatarCreatorSamples/Scripts/UI/Buttons/AssetButton.cs b/Samples~/AvatarCreatorSamples/Scripts/UI/Buttons/AssetButton.cs index c3cd6548..6a9d98c4 100644 --- a/Samples~/AvatarCreatorSamples/Scripts/UI/Buttons/AssetButton.cs +++ b/Samples~/AvatarCreatorSamples/Scripts/UI/Buttons/AssetButton.cs @@ -6,14 +6,12 @@ namespace ReadyPlayerMe { public class AssetButton : MonoBehaviour { - private readonly Vector2 defaultEyeSize = new Vector2(210, 210); - [SerializeField] private RawImage icon; [SerializeField] private GameObject selected; [SerializeField] private Button button; [SerializeField] private GameObject mask; [SerializeField] private GameObject loading; - + public void AddListener(Action action) { button.onClick.AddListener(action.Invoke); @@ -25,13 +23,6 @@ public void SetColor(string colorHex) icon.color = color; } - public void SetEyeColorConfig() - { - EnableMask(); - icon.rectTransform.localPosition = Vector3.zero; - icon.rectTransform.sizeDelta = defaultEyeSize; - } - public void SetIcon(Texture texture) { icon.texture = texture; diff --git a/Samples~/AvatarCreatorSamples/Scripts/UI/SelectionScreens/DefaultAvatarSelection.cs b/Samples~/AvatarCreatorSamples/Scripts/UI/SelectionScreens/DefaultAvatarSelection.cs index c9fe89f6..11715932 100644 --- a/Samples~/AvatarCreatorSamples/Scripts/UI/SelectionScreens/DefaultAvatarSelection.cs +++ b/Samples~/AvatarCreatorSamples/Scripts/UI/SelectionScreens/DefaultAvatarSelection.cs @@ -19,13 +19,13 @@ public class DefaultAvatarSelection : State public override StateType StateType => StateType.DefaultAvatarSelection; public override StateType NextState => StateType.Editor; - private Dictionary avatarRenderByTemplateData; + private Dictionary avatarRenderByTemplateData; private CancellationTokenSource ctxSource; - private TemplateFetcher templateFetcher; + private AvatarTemplateFetcher templateFetcher; private void Awake() { - avatarRenderByTemplateData = new Dictionary(); + avatarRenderByTemplateData = new Dictionary(); } private void OnDestroy() @@ -69,19 +69,19 @@ private async Task FetchTemplates() { var startTime = Time.time; ctxSource = new CancellationTokenSource(); - templateFetcher = new TemplateFetcher(ctxSource.Token); + templateFetcher = new AvatarTemplateFetcher(ctxSource.Token); - var templates = await templateFetcher.GetTemplates(); + var templates = await templateFetcher.GetTemplatesWithRenders(); SDKLogger.Log(TAG, $"Fetched all avatar templates in {Time.time - startTime:F2}s "); foreach (var template in templates) { - var button = CreateAvatarRender(template.Id, template.Texture); + var button = CreateRenderButton(template.Id, template.Texture); avatarRenderByTemplateData.Add(template, button); } } - private GameObject CreateAvatarRender(string id, Texture renderImage) + private GameObject CreateRenderButton(string id, Texture renderImage) { var button = Instantiate(buttonPrefab, parent); var rawImage = button.GetComponentInChildren(); @@ -96,7 +96,7 @@ private void OnAvatarSelected(string avatarId) AvatarCreatorData.AvatarProperties.Id = avatarId; AvatarCreatorData.AvatarProperties.Base64Image = string.Empty; AvatarCreatorData.IsExistingAvatar = false; - + StateMachine.SetState(StateType.Editor); } }