| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835 | 
							- #if UNITY_EDITOR
 
- using System.Collections.Generic;
 
- using System.IO;
 
- using System.Linq;
 
- using System.Text;
 
- using System.Text.RegularExpressions;
 
- using GPUECSAnimationBaker.Engine.AnimatorSystem;
 
- using GpuEcsAnimationBaker.Engine.Data;
 
- using Unity.Collections;
 
- using Unity.Mathematics;
 
- using UnityEditor;
 
- using UnityEngine;
 
- namespace GPUECSAnimationBaker.Engine.Baker
 
- {
 
-     public static class GpuEcsAnimationBakerServices
 
-     {
 
-         private static readonly int AnimatedBoneMatrices = Shader.PropertyToID("_AnimatedBoneMatrices");
 
-         private static readonly int EnableAnimation = Shader.PropertyToID("_EnableAnimation");
 
-         public static bool ValidateAnimationBakerData(GpuEcsAnimationBakerData bakerData, GameObject sourceModel, out string errors)
 
-         {
 
-             StringBuilder sbErrors = new StringBuilder();
 
-             if (bakerData.animations.Length == 0)
 
-                 sbErrors.AppendLine("At least one animation must be baked.");
 
-             foreach (AnimationData animation in bakerData.animations)
 
-             {
 
-                 if (string.IsNullOrWhiteSpace(animation.animationID))
 
-                     sbErrors.AppendLine("Animation ID is mandatory");
 
-                 if (!Regex.IsMatch(animation.animationID, @"^[a-zA-Z_][a-zA-Z0-9_]+$"))
 
-                     sbErrors.AppendLine("Animation ID must be only letters, numbers or underscore, must not start with number");
 
-                 if (string.IsNullOrWhiteSpace(animation.animatorStateName))
 
-                     sbErrors.AppendLine("Animation State Name is mandatory");
 
-                 if (animation.animationType == AnimationTypes.SingleClip)
 
-                 {
 
-                     if (animation.singleClipData.animationClip == null)
 
-                         sbErrors.AppendLine("Animation Clip is mandatory");
 
-                 }
 
-                 else if (animation.animationType == AnimationTypes.DualClipBlend)
 
-                 {
 
-                     if (string.IsNullOrWhiteSpace(animation.dualClipBlendData.blendParameterName))
 
-                         sbErrors.AppendLine("Blend parameter name is mandatory");
 
-                     if (animation.dualClipBlendData.clip1.animationClip == null)
 
-                         sbErrors.AppendLine("Animation Clip 1 is mandatory");
 
-                     if (animation.dualClipBlendData.clip1.animationClip == null)
 
-                         sbErrors.AppendLine("Animation Clip 2 is mandatory");
 
-                     if (animation.dualClipBlendData.nbrOfInBetweenSamples < 2)
 
-                         sbErrors.AppendLine("Nbr of in between samples must be at least 2");
 
-                     if (animation.dualClipBlendData.nbrOfInBetweenSamples > 100)
 
-                         sbErrors.AppendLine("Nbr of in between samples is maximum 100");
 
-                 }
 
-                 foreach (AnimatorParameter parameterValue in animation.additionalAnimatorParameterValues)
 
-                 {
 
-                     if (string.IsNullOrWhiteSpace(parameterValue.parameterName))
 
-                         sbErrors.AppendLine("Additional animator parameter name is mandatory");
 
-                 }
 
-             }
 
-             bool foundDouble = false;
 
-             for (int i = 0; i < bakerData.animations.Length; i++)
 
-             {
 
-                 for (int j = i + 1; j < bakerData.animations.Length; j++)
 
-                 {
 
-                     if (bakerData.animations[i].animationID == bakerData.animations[j].animationID)
 
-                     {
 
-                         foundDouble = true; break;
 
-                     }
 
-                 }
 
-                 if(foundDouble) break;
 
-             }
 
-             if(foundDouble) sbErrors.AppendLine("Animation IDs must be unique");
 
-             foreach (AttachmentAnchor attachmentAnchor in bakerData.attachmentAnchors)
 
-             {
 
-                 if (string.IsNullOrWhiteSpace(attachmentAnchor.attachmentAnchorID))
 
-                     sbErrors.AppendLine("Attachment Anchor ID is mandatory");
 
-                 if(attachmentAnchor.attachmentAnchorTransform == null)
 
-                     sbErrors.AppendLine("Attachment Anchor reference transform is mandatory");
 
-                 else if(!hasParent(attachmentAnchor.attachmentAnchorTransform, sourceModel.transform))
 
-                     sbErrors.AppendLine($"Attachment Anchor reference transform must be nested inside {sourceModel.name}");
 
-             }
 
-             
 
-             if(bakerData.boneUsage.numberOfBonesPerVertex < 1) 
 
-                 sbErrors.AppendLine("Nbr of bones per vertex must be at least 1");
 
-             foreach (BoneUsagePerLoD boneUsagePerLOD in bakerData.boneUsage.boneUsagesPerLoD)
 
-             {
 
-                 if(boneUsagePerLOD.maxNumberOfBonesPerVertex < 1) 
 
-                     sbErrors.AppendLine("Nbr of bones per vertex must be at least 1");
 
-             }
 
-             
 
-             errors = sbErrors.ToString();
 
-             return sbErrors.Length == 0;
 
-         }
 
-         private static bool hasParent(Transform child, Transform parent)
 
-         {
 
-             if (child.parent == null) return false;
 
-             if (child.parent.gameObject == parent.gameObject) return true;
 
-             else return hasParent(child.parent, parent);
 
-         }
 
-         public static GameObject GenerateAnimationObject(string assetPath, 
 
-             GpuEcsAnimationBakerData bakerData, string animatorName, string generatedAssetsFolder, 
 
-             string nameSuffixAsset = "_GpuEcsAnimator",
 
-             string nameSuffixAnimationIDsEnum = "_AnimationIDs",
 
-             string nameSuffixAnimationInitializerBehaviour = "_AnimationInitializerBehaviour",
 
-             string nameSuffixAnimationEventIDsEnum = "_AnimationEventIDs",
 
-             string nameSuffixAnimationAnchorIDsEnum = "_AttachmentAnchorIDs",
 
-             string nameSuffixAttachmentInitializerBehaviour = "_AttachmentInitializerBehaviour",
 
-             string meshPartSuffix = "Mesh",
 
-             string animationMatricesTexturePartSuffix = "AnimationMatricesTexture", 
 
-             string materialPartSuffix = "Material"
 
-             )
 
-         {
 
-             GameObject sourceModel = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
 
-             GameObject refModel = PrefabUtility.LoadPrefabContents(assetPath);
 
-             Debug.Log($"Generating Animation object for {assetPath}");
 
-             GameObject animationObject = GenerateAnimationObjectFromModel(refModel, sourceModel, bakerData, animatorName, generatedAssetsFolder,
 
-                 nameSuffixAsset, nameSuffixAnimationIDsEnum, nameSuffixAnimationInitializerBehaviour, nameSuffixAnimationEventIDsEnum,
 
-                 nameSuffixAnimationAnchorIDsEnum, nameSuffixAttachmentInitializerBehaviour, meshPartSuffix, animationMatricesTexturePartSuffix, materialPartSuffix);
 
-             PrefabUtility.UnloadPrefabContents(refModel);
 
-             
 
-             return animationObject;
 
-         }
 
-         
 
-         public static GameObject GenerateAnimationObjectFromModel(GameObject refModel, GameObject sourceModel, 
 
-             GpuEcsAnimationBakerData bakerData, string animatorName, string generatedAssetsFolder,
 
-             string nameSuffixAsset = "_GpuEcsAnimator",
 
-             string nameSuffixAnimationIDsEnum = "_AnimationIDs",
 
-             string nameSuffixAnimationInitializerBehaviour = "_AnimationInitializerBehaviour",
 
-             string nameSuffixAnimationEventIDsEnum = "_AnimationEventIDs",
 
-             string nameSuffixAnimationAnchorIDsEnum = "_AttachmentAnchorIDs",
 
-             string nameSuffixAttachmentInitializerBehaviour = "_AttachmentInitializerBehaviour",
 
-             string meshPartSuffix = "Mesh",
 
-             string animationMatricesTexturePartSuffix = "AnimationMatricesTexture", 
 
-             string materialPartSuffix = "Material"
 
-             ) 
 
-         {
 
-             if(!ValidateAnimationBakerData(bakerData, sourceModel, out string errors))
 
-             {
 
-                 Debug.LogError(errors);
 
-                 return null;
 
-             }
 
-             string targetAssetPath =
 
-                 Path.Combine(generatedAssetsFolder, $"{animatorName}{nameSuffixAsset}.prefab");
 
-             string targetAnimationEnumAssetPath =
 
-                 Path.Combine(generatedAssetsFolder, $"{animatorName}{nameSuffixAnimationIDsEnum}.cs");
 
-             string targetAnimationInitializerBehaviourAssetPath =
 
-                 Path.Combine(generatedAssetsFolder, $"{animatorName}{nameSuffixAnimationInitializerBehaviour}.cs");
 
-             string targetAnimationEventEnumAssetPath =
 
-                 Path.Combine(generatedAssetsFolder, $"{animatorName}{nameSuffixAnimationEventIDsEnum}.cs");
 
-             string targetAttachmentAnchorEnumAssetPath =
 
-                 Path.Combine(generatedAssetsFolder, $"{animatorName}{nameSuffixAnimationAnchorIDsEnum}.cs");
 
-             string targetAttachmentInitializerBehaviourAssetPath =
 
-                 Path.Combine(generatedAssetsFolder, $"{animatorName}{nameSuffixAttachmentInitializerBehaviour}.cs");
 
-             
 
-             refModel.transform.position = Vector3.zero;
 
-             refModel.transform.rotation = quaternion.identity;
 
-             Animator refModelAnimator = refModel.GetComponent<Animator>();
 
-             refModelAnimator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
 
-             LODGroup refModelLoDGroup = refModel.GetComponent<LODGroup>();
 
-             LOD[] refModelLoDs = refModelLoDGroup == null ? null : refModelLoDGroup.GetLODs();
 
-             List<AnimationMatricesTexture> animationMatricesTexturesCache = new List<AnimationMatricesTexture>();
 
-             List<EcsGpuMaterial> ecsGpuMaterialsCache = new List<EcsGpuMaterial>();
 
-             GameObject test = AssetDatabase.LoadAssetAtPath<GameObject>(targetAssetPath);
 
-             if (test == null)
 
-             {
 
-                 GameObject empty = new GameObject(refModel.name);
 
-                 PrefabUtility.SaveAsPrefabAsset(empty, targetAssetPath);
 
-                 GameObject.DestroyImmediate(empty, allowDestroyingAssets:true);
 
-             }
 
-             GameObject target = PrefabUtility.LoadPrefabContents(targetAssetPath);
 
-             target.transform.localScale = refModel.transform.localScale;
 
-             GameObject[] toDestroy = new GameObject[target.transform.childCount];
 
-             for (int childIndex = 0; childIndex < target.transform.childCount; childIndex++)
 
-                 toDestroy[childIndex] = target.transform.GetChild(childIndex).gameObject;
 
-             foreach(GameObject go in toDestroy) Object.DestroyImmediate(go, allowDestroyingAssets: true);
 
-             RemoveComponent<MeshRenderer>(target);
 
-             RemoveComponent<MeshFilter>(target);
 
-             RemoveComponent<LODGroup>(target);
 
-             RemoveComponent<GpuEcsAnimatorBehaviour>(target);
 
-             RemoveComponent<GpuEcsAnimatedMeshBehaviour>(target);
 
-             
 
-             GpuEcsAnimatorBehaviour gpuEcsAnimator = AddGpuEcsAnimationBehaviour(target, bakerData, out string[] eventNames);
 
-             gpuEcsAnimator.transformUsageFlags = bakerData.transformUsageFlagsParent;
 
-             Dictionary<GameObject, GameObject> sourceToTargetMapping = new Dictionary<GameObject, GameObject>();
 
-             ProcessAnimationObjectRecursive(refModel, target, sourceToTargetMapping, animatorName,
 
-                 meshPartSuffix, animationMatricesTexturePartSuffix, materialPartSuffix,
 
-                 refModelAnimator, refModelLoDs, animationMatricesTexturesCache, ecsGpuMaterialsCache,
 
-                 bakerData, gpuEcsAnimator.animations, gpuEcsAnimator.totalNbrOfFrames, generatedAssetsFolder, gpuEcsAnimator);
 
-             if (refModelLoDs != null)
 
-             {
 
-                 LODGroup targetLoDGroup = target.AddComponent<LODGroup>();
 
-                 LOD[] targetLoDs = new LOD[refModelLoDs.Length];
 
-                 for (int lodIndex = 0; lodIndex < refModelLoDs.Length; lodIndex++)
 
-                 {
 
-                     targetLoDs[lodIndex] = refModelLoDs[lodIndex];
 
-                     Renderer[] refModelRenderers = refModelLoDs[lodIndex].renderers;
 
-                     for (int rendererIndex = 0; rendererIndex < refModelRenderers.Length; rendererIndex++)
 
-                     {
 
-                         targetLoDs[lodIndex].renderers[rendererIndex] =
 
-                             sourceToTargetMapping[refModelRenderers[rendererIndex].gameObject].GetComponent<MeshRenderer>();
 
-                     }
 
-                 }
 
-                 targetLoDGroup.SetLODs(targetLoDs);
 
-             }
 
-             
 
-             if(bakerData.generateAnimationIdsEnum)
 
-                 GenerateAnimationsEnumCode(bakerData, targetAnimationEnumAssetPath, targetAnimationInitializerBehaviourAssetPath);
 
-             
 
-             if(bakerData.generateAnimationEventIdsEnum)
 
-                 GenerateAnimationEventsEnumCode(bakerData, targetAnimationEventEnumAssetPath, eventNames );
 
-             gpuEcsAnimator.nbrOfAttachmentAnchors = bakerData.attachmentAnchors.Length;
 
-             gpuEcsAnimator.attachmentAnchorData = BakeAttachmentAnchorTransforms(generatedAssetsFolder, sourceModel, animatorName, 
 
-                 refModelAnimator, bakerData, gpuEcsAnimator.animations, gpuEcsAnimator.totalNbrOfFrames,gpuEcsAnimator);
 
-             
 
-             if(bakerData.generateAttachmentAnchorIdsEnum)
 
-                 GenerateAttachmentAnchorsEnumCode(bakerData, targetAttachmentAnchorEnumAssetPath, targetAttachmentInitializerBehaviourAssetPath);
 
-             
 
-             PrefabUtility.SaveAsPrefabAsset(target, targetAssetPath);
 
-             PrefabUtility.UnloadPrefabContents(target);
 
-             
 
-             return AssetDatabase.LoadAssetAtPath<GameObject>(targetAssetPath);
 
-         }
 
-         private const string enumFileTemplate = "namespace GPUECSAnimationBaker.Engine.AnimatorSystem\n"
 
-                                                 + "{\n"
 
-                                                 + "    public enum @ENUMNAME@\n"
 
-                                                 + "    {\n"
 
-                                                 + "@IDLIST@\n"
 
-                                                 + "    }\n"
 
-                                                 + "}";
 
-         private const string behaviourFileTemplate = "namespace GPUECSAnimationBaker.Engine.AnimatorSystem\n"
 
-                                                 + "{\n"
 
-                                                 + "    public class @CLASSNAME_@ENUMNAME@_Behaviour : @CLASSNAMEBehaviour<@ENUMNAME@> { } \n"
 
-                                                 + "}";
 
-         
 
-         private static void GenerateAnimationsEnumCode(GpuEcsAnimationBakerData bakerData, string targetEnumAssetPath, string targetEnumBehaviourAssetPath)
 
-         {
 
-             GenerateEnumCodeFiles<AnimationData>($"AnimationIds{bakerData.animationIdsEnumName}", "GpuEcsAnimatorInitializer",
 
-                 bakerData.animations, (animationData) => animationData.animationID, targetEnumAssetPath, targetEnumBehaviourAssetPath);
 
-         }
 
-         private static void GenerateAnimationEventsEnumCode(GpuEcsAnimationBakerData bakerData, string targetEnumAssetPath, string[] eventNames)
 
-         {
 
-             GenerateEnumCodeFiles<string>($"AnimationEventIds{bakerData.animationEventIdsEnumName}", null,
 
-                 eventNames, (name) => name, targetEnumAssetPath, null);
 
-         }
 
-         
 
-         private static void GenerateAttachmentAnchorsEnumCode(GpuEcsAnimationBakerData bakerData, string targetEnumAssetPath, string targetEnumBehaviourAssetPath)
 
-         {
 
-             GenerateEnumCodeFiles<AttachmentAnchor>($"AnchorIds{bakerData.attachmentAnchorIdsEnumName}", "GpuEcsAttachmentInitializer", 
 
-                 bakerData.attachmentAnchors, (attachmentAnchor) => attachmentAnchor.attachmentAnchorID, targetEnumAssetPath, targetEnumBehaviourAssetPath);
 
-         }
 
-         
 
-         private static void GenerateEnumCodeFiles<T>(string enumName, string className, T[] list, System.Func<T, string> listIdGetter, 
 
-             string targetEnumAssetPath, string targetEnumBehaviourAssetPath)
 
-         {
 
-             StringBuilder idList = new StringBuilder();
 
-             for (int index = 0; index < list.Length; index++)
 
-             {
 
-                 idList.Append($"        {listIdGetter(list[index])} = {index.ToString()}");
 
-                 if (index < list.Length - 1)
 
-                 {
 
-                     idList.AppendLine(",");
 
-                 }
 
-             }
 
-             
 
-             string enumCodeText = enumFileTemplate
 
-                 .Replace("@ENUMNAME@", enumName)
 
-                 .Replace("@IDLIST@", idList.ToString());
 
-             string enumCodePath = Path.Combine(Application.dataPath, "../" + targetEnumAssetPath); 
 
-             File.WriteAllText(enumCodePath, enumCodeText);
 
-             if (targetEnumBehaviourAssetPath != null)
 
-             {
 
-                 string enumBehaviourText = behaviourFileTemplate
 
-                     .Replace("@CLASSNAME", className)
 
-                     .Replace("@ENUMNAME@", enumName);
 
-                 string enumBehaviourPath = Path.Combine(Application.dataPath, "../" + targetEnumBehaviourAssetPath);
 
-                 File.WriteAllText(enumBehaviourPath, enumBehaviourText);
 
-             }
 
-             AssetDatabase.Refresh();
 
-         }
 
-         private static GpuEcsAnimatorBehaviour AddGpuEcsAnimationBehaviour(GameObject target,
 
-             GpuEcsAnimationBakerData bakerData, out string[] eventNames)
 
-         {
 
-             GpuEcsAnimatorBehaviour gpuEcsAnimator = target.AddComponent<GpuEcsAnimatorBehaviour>();
 
-             gpuEcsAnimator.animations = new GpuEcsAnimationData[bakerData.animations.Length];
 
-             // gpuEcsAnimator.BackAnimationDatas= new AnimationData[bakerData.animations.Length];
 
-             List<GpuEcsAnimationEventOccurence> occurences = new List<GpuEcsAnimationEventOccurence>();
 
-             List<string> foundEvents = new List<string>();
 
-             int currentFrameIndex = 0;
 
-             int currentEventOccurenceId = 0;
 
-             int currentFoundEventId = 0;
 
-             for (int animationIndex = 0; animationIndex < bakerData.animations.Length; animationIndex++)
 
-             {
 
-                 AnimationData animationData = bakerData.animations[animationIndex];
 
-                 int nbrOfFramesPerSample = 0;
 
-                 int nbrOfInBetweenSamples = 0;
 
-                 float blendTimeCorrection = 1;
 
-                 int startEventOccurenceId = currentEventOccurenceId;
 
-                 int nbrOfEventOccurenceIds = 0;
 
-                 if (animationData.animationType == AnimationTypes.SingleClip)
 
-                 {
 
-                     SingleClipData singleClipData = animationData.singleClipData;
 
-                     nbrOfFramesPerSample = (int)(singleClipData.animationClip.length * GlobalConstants.SampleFrameRate) + 1;
 
-                     nbrOfInBetweenSamples = 1;
 
-                     blendTimeCorrection = 1;
 
-                     AddAnimationEvents(bakerData, animationData, occurences, ref currentEventOccurenceId, ref nbrOfEventOccurenceIds, foundEvents, 
 
-                         ref currentFoundEventId, singleClipData.animationClip);
 
-                 }
 
-                 else if (animationData.animationType == AnimationTypes.DualClipBlend)
 
-                 {
 
-                     DualClipBlendData dualClipBlendData = animationData.dualClipBlendData;
 
-                     int clip1NbrOfFrames = (int)(dualClipBlendData.clip1.animationClip.length * GlobalConstants.SampleFrameRate) + 1;
 
-                     int clip2NbrOfFrames = (int)(dualClipBlendData.clip2.animationClip.length * GlobalConstants.SampleFrameRate) + 1;
 
-                     nbrOfFramesPerSample = math.max(clip1NbrOfFrames, clip2NbrOfFrames);
 
-                     blendTimeCorrection = dualClipBlendData.clip1.animationClip.length / dualClipBlendData.clip2.animationClip.length;
 
-                     nbrOfInBetweenSamples = dualClipBlendData.nbrOfInBetweenSamples;
 
-                     AddAnimationEvents(bakerData, animationData, occurences, ref currentEventOccurenceId, ref nbrOfEventOccurenceIds, foundEvents, 
 
-                         ref currentFoundEventId, dualClipBlendData.clip1.animationClip);
 
-                     AddAnimationEvents(bakerData, animationData, occurences, ref currentEventOccurenceId, ref nbrOfEventOccurenceIds, foundEvents, 
 
-                         ref currentFoundEventId, dualClipBlendData.clip2.animationClip);
 
-                 }
 
-                 bool loop = animationData.loop;
 
-                 
 
-                 gpuEcsAnimator.animations[animationIndex] = new GpuEcsAnimationData()
 
-                 {
 
-                     startFrameIndex = currentFrameIndex,
 
-                     nbrOfFramesPerSample = nbrOfFramesPerSample,
 
-                     nbrOfInBetweenSamples = nbrOfInBetweenSamples,
 
-                     blendTimeCorrection = blendTimeCorrection,
 
-                     startEventOccurenceId = startEventOccurenceId,
 
-                     nbrOfEventOccurenceIds = nbrOfEventOccurenceIds,
 
-                     loop = loop,
 
-                     animationID = animationData.animationID,
 
-                     stateName = animationData.animatorStateName
 
-                 };
 
-                 currentFrameIndex += nbrOfFramesPerSample * nbrOfInBetweenSamples;
 
-             }
 
-             gpuEcsAnimator.totalNbrOfFrames = currentFrameIndex;
 
-             gpuEcsAnimator.animationEventOccurences = occurences.ToArray();
 
-             eventNames = bakerData.usePredefinedAnimationEventIds ? bakerData.predefinedAnimationEventIds : foundEvents.ToArray();
 
-             return gpuEcsAnimator;
 
-         }
 
-         private static void AddAnimationEvents(GpuEcsAnimationBakerData bakerData, AnimationData animationData, 
 
-             List<GpuEcsAnimationEventOccurence> occurences, 
 
-             ref int currentEventOccurenceId, ref int nbrOfEventOccurenceIds, 
 
-             List<string> foundEvents, ref int currentFoundEventId, AnimationClip animationClip)
 
-         {
 
-             AnimationEvent[] animationEvents = AnimationUtility.GetAnimationEvents(animationClip);
 
-             foreach (AnimationEvent animationEvent in animationEvents)
 
-             {
 
-                 int eventId = -1;
 
-                 if (bakerData.usePredefinedAnimationEventIds)
 
-                 {
 
-                     eventId = bakerData.predefinedAnimationEventIds.ToList().FindIndex((n) => n.Equals(animationEvent.stringParameter));
 
-                     if(eventId == -1) Debug.LogWarning(
 
-                         $"Found event {animationEvent.stringParameter} that is not in the predefined event Ids list, so it will be ignored.");
 
-                 }
 
-                 else
 
-                 {
 
-                     string name = $"{animationData.animationID}_{animationEvent.stringParameter}";
 
-                     eventId = foundEvents.FindIndex((n) => n.Equals(name));
 
-                     if (eventId == -1)
 
-                     {
 
-                         eventId = currentFoundEventId;
 
-                         foundEvents.Add(name);
 
-                         currentFoundEventId++;
 
-                     }
 
-                 }
 
-                 if (eventId != -1)
 
-                 {
 
-                     occurences.Add(new GpuEcsAnimationEventOccurence()
 
-                     {
 
-                         eventId = eventId,
 
-                         eventNormalizedTime = animationEvent.time / animationClip.length,
 
-                     });
 
-                     currentEventOccurenceId++;
 
-                     nbrOfEventOccurenceIds++;
 
-                 }
 
-             }
 
-         }
 
-         
 
-         private static void ProcessAnimationObjectRecursive(GameObject sourceNode, GameObject targetNode, 
 
-             Dictionary<GameObject, GameObject> sourceToTargetMapping, string animatorName, string meshPartSuffix,
 
-             string animationMatricesTexturePartSuffix, string materialPartSuffix,
 
-             Animator refModelAnimator, LOD[] refModelLoDs, 
 
-             List<AnimationMatricesTexture> animationMatricesTexturesCache, List<EcsGpuMaterial> ecsGpuMaterialsCache, 
 
-             GpuEcsAnimationBakerData bakerData, GpuEcsAnimationData[] animations, int totalNbrOfFrames,
 
-             string generatedAssetsFolder, GpuEcsAnimatorBehaviour gpuEcsAnimator)
 
-         {
 
-             sourceToTargetMapping.Add(sourceNode, targetNode);
 
-             SkinnedMeshRenderer existingSkinnedMeshRenderer = sourceNode.GetComponent<SkinnedMeshRenderer>();
 
-             if (existingSkinnedMeshRenderer != null)
 
-             {
 
-                 Texture2D animationMatricesTexture = BakeAndSaveAnimationMatricesTexture(
 
-                     animationMatricesTexturesCache, generatedAssetsFolder, animatorName, animationMatricesTexturePartSuffix,
 
-                     refModelAnimator, bakerData, existingSkinnedMeshRenderer, animations, totalNbrOfFrames);
 
-                 Mesh newMesh = BakeAndSaveBoneWeightsIntoMesh(refModelLoDs, generatedAssetsFolder, animatorName,
 
-                     meshPartSuffix, bakerData, existingSkinnedMeshRenderer);
 
-                 MeshFilter meshFilter = targetNode.AddComponent<MeshFilter>();
 
-                 MeshRenderer meshRenderer = targetNode.AddComponent<MeshRenderer>();
 
-                 Material newMaterial = CreateAndSaveEcsGpuMaterial(ecsGpuMaterialsCache, generatedAssetsFolder,
 
-                     animatorName, materialPartSuffix, existingSkinnedMeshRenderer);
 
-                 newMaterial.SetTexture(AnimatedBoneMatrices, animationMatricesTexture);
 
-                 meshRenderer.sharedMaterial = newMaterial;
 
-                 meshFilter.sharedMesh = newMesh;
 
-                 GpuEcsAnimatedMeshBehaviour gpuEcsAnimatedMesh = targetNode.AddComponent<GpuEcsAnimatedMeshBehaviour>();
 
-                 gpuEcsAnimatedMesh.animator = gpuEcsAnimator;
 
-                 gpuEcsAnimatedMesh.transformUsageFlags = bakerData.transformUsageFlagsChildren;
 
-             }
 
-             for (int childIndex = 0; childIndex < sourceNode.transform.childCount; childIndex++)
 
-             {
 
-                 GameObject sourceChild = sourceNode.transform.GetChild(childIndex).gameObject;
 
-                 if (sourceChild.gameObject.activeSelf && !CheckEmptyRecursive(sourceChild))
 
-                 {
 
-                     GameObject targetChild = new GameObject(sourceChild.name);
 
-                     targetChild.transform.parent = targetNode.transform;
 
-                     targetChild.transform.localPosition = sourceChild.transform.localPosition;
 
-                     targetChild.transform.localRotation = sourceChild.transform.localRotation;
 
-                     targetChild.transform.localScale = sourceChild.transform.localScale;
 
-                     ProcessAnimationObjectRecursive(sourceChild, targetChild, sourceToTargetMapping,
 
-                         animatorName, meshPartSuffix, animationMatricesTexturePartSuffix, materialPartSuffix,
 
-                         refModelAnimator, refModelLoDs, animationMatricesTexturesCache, ecsGpuMaterialsCache,
 
-                         bakerData, animations, totalNbrOfFrames, generatedAssetsFolder, gpuEcsAnimator);
 
-                 }
 
-             }
 
-         }
 
-         private static void RemoveComponent<T>(GameObject gameObject)  where T : Component 
 
-         {
 
-             T component = gameObject.GetComponent<T>();
 
-             if(component != null) Object.DestroyImmediate(component, allowDestroyingAssets:true);
 
-         }
 
-         
 
-         private static bool CheckEmptyRecursive(GameObject node)
 
-         {
 
-             Component[] components = node.GetComponents<Component>();
 
-             bool empty = !components.Any(c => (c is SkinnedMeshRenderer));
 
-             if (empty)
 
-             {
 
-                 for (int childIndex = 0; childIndex < node.transform.childCount; childIndex++)
 
-                 {
 
-                     empty = CheckEmptyRecursive(node.transform.GetChild(childIndex).gameObject);
 
-                     if (!empty) break;
 
-                 }
 
-             }
 
-             return empty;
 
-         }
 
-         
 
-         private static Mesh BakeAndSaveBoneWeightsIntoMesh(LOD[] refModelLoDs,
 
-             string generatedAssetsFolder, string animatorName, string meshPartSuffix, GpuEcsAnimationBakerData bakerData,
 
-             SkinnedMeshRenderer skinnedMeshRenderer)
 
-         {
 
-             int maxNumberOfBonesPerVertex = GetMaxNumberOfBonesPerVertex(refModelLoDs, bakerData, skinnedMeshRenderer);
 
-             Mesh newMesh = BakeBoneWeightsIntoMesh(skinnedMeshRenderer.sharedMesh, maxNumberOfBonesPerVertex);
 
-             SavePartAsAsset(newMesh, generatedAssetsFolder, animatorName, skinnedMeshRenderer, meshPartSuffix, "mesh");
 
-             return newMesh;
 
-         }
 
-         private static Texture2D BakeAndSaveAnimationMatricesTexture(List<AnimationMatricesTexture> cache,
 
-             string generatedAssetsFolder, string animatorName, string animationMatricesTexturePartSuffix,
 
-             Animator refModelAnimator, GpuEcsAnimationBakerData bakerData,
 
-             SkinnedMeshRenderer skinnedMeshRenderer, GpuEcsAnimationData[] animations, int totalNbrOfFrames)
 
-         {
 
-             if (!CheckAnimationMatricesTextureInCache(cache, skinnedMeshRenderer, out Texture2D animationMatricesTexture))
 
-             {
 
-                 animationMatricesTexture = BakeAnimationMatricesTexture(skinnedMeshRenderer, refModelAnimator, bakerData,
 
-                     animations, totalNbrOfFrames);
 
-                 SavePartAsAsset(animationMatricesTexture, generatedAssetsFolder, animatorName, skinnedMeshRenderer,
 
-                     animationMatricesTexturePartSuffix, "asset");
 
-                     
 
-                 cache.Add(new AnimationMatricesTexture()
 
-                 {
 
-                     texture = animationMatricesTexture,
 
-                     skinnedMeshRenderer = skinnedMeshRenderer
 
-                 });
 
-             }
 
-             return animationMatricesTexture;
 
-         }
 
-         private static Material CreateAndSaveEcsGpuMaterial(List<EcsGpuMaterial> cache,
 
-             string generatedAssetsFolder, string animatorName, string materialPartSuffix,
 
-             SkinnedMeshRenderer skinnedMeshRenderer)
 
-         {
 
-             if (!CheckEcsGpuMaterialInCache(cache, skinnedMeshRenderer, out Material ecsGpuMaterial))
 
-             {
 
-                 ecsGpuMaterial = Object.Instantiate<Material>(skinnedMeshRenderer.sharedMaterial);
 
-                 ecsGpuMaterial.shader = Shader.Find("Shader Graphs/GPUECSAnimator_URP_SimpleShader");
 
-                 ecsGpuMaterial.SetFloat(EnableAnimation, 0);
 
-                 ecsGpuMaterial.enableInstancing = true;
 
-                 SavePartAsAsset(ecsGpuMaterial, generatedAssetsFolder, animatorName, skinnedMeshRenderer,
 
-                     materialPartSuffix, "mat");
 
-                 cache.Add(new EcsGpuMaterial()
 
-                 {
 
-                     material = ecsGpuMaterial,
 
-                     skinnedMeshRenderer = skinnedMeshRenderer
 
-                 });
 
-             }
 
-             return ecsGpuMaterial;
 
-         }
 
-         private static string GenerateAssetPath(string generatedAssetsFolder, string animatorName,
 
-             string assetName, string assetFileExtension)
 
-         {
 
-             return Path.Combine(generatedAssetsFolder, $"{animatorName}_{assetName}.{assetFileExtension}");
 
-         }
 
-         
 
-         private static void SavePartAsAsset(Object asset, string generatedAssetsFolder, string animatorName,
 
-             SkinnedMeshRenderer skinnedMeshRenderer, string partName, string assetFileExtension)
 
-         {
 
-             string assetName = $"{partName}_{skinnedMeshRenderer.name}";
 
-             string assetPath = GenerateAssetPath(generatedAssetsFolder, animatorName, assetName, assetFileExtension);
 
-             AssetDatabase.CreateAsset(asset, assetPath);
 
-         }
 
-         
 
-         private static int GetMaxNumberOfBonesPerVertex(LOD[] refModelLoDs, GpuEcsAnimationBakerData bakerData,
 
-             SkinnedMeshRenderer skinnedMeshRenderer)
 
-         {
 
-             int maxNumberOfBonesPerVertex = bakerData.boneUsage.numberOfBonesPerVertex;
 
-             if (refModelLoDs != null)
 
-             {
 
-                 for (int lodIndex = 0; lodIndex < refModelLoDs.Length; lodIndex++)
 
-                 {
 
-                     if (refModelLoDs[lodIndex].renderers.Any(r => r == (Renderer)skinnedMeshRenderer))
 
-                     {
 
-                         BoneUsagePerLoD boneUsagePerLoD = bakerData.boneUsage.boneUsagesPerLoD
 
-                             .SingleOrDefault(b => b.lodIndex == lodIndex);
 
-                         if (boneUsagePerLoD != null)
 
-                             maxNumberOfBonesPerVertex = boneUsagePerLoD.maxNumberOfBonesPerVertex;
 
-                         break;
 
-                     }
 
-                 }
 
-             }
 
-             return maxNumberOfBonesPerVertex;
 
-         }
 
-         private static bool CheckAnimationMatricesTextureInCache(List<AnimationMatricesTexture> cache,
 
-             SkinnedMeshRenderer skinnedMeshRenderer, out Texture2D foundTexture)
 
-         {
 
-             bool found = false;
 
-             foundTexture = null; 
 
-             foreach (AnimationMatricesTexture cachedTexture in cache)
 
-             {
 
-                 if (CheckSkinnedMeshRendererHasSameBones(cachedTexture.skinnedMeshRenderer,
 
-                         skinnedMeshRenderer))
 
-                 {
 
-                     found = true;
 
-                     foundTexture = cachedTexture.texture;
 
-                     break;
 
-                 }
 
-             }
 
-             return found;
 
-         }
 
-         private static bool CheckEcsGpuMaterialInCache(List<EcsGpuMaterial> cache,
 
-             SkinnedMeshRenderer skinnedMeshRenderer, out Material foundMaterial)
 
-         {
 
-             bool found = false;
 
-             foundMaterial = null;
 
-             foreach (EcsGpuMaterial cachedEcsGpuMaterial in cache)
 
-             {
 
-                 if (cachedEcsGpuMaterial.skinnedMeshRenderer.sharedMaterial == skinnedMeshRenderer.sharedMaterial
 
-                     && CheckSkinnedMeshRendererHasSameBones(cachedEcsGpuMaterial.skinnedMeshRenderer,
 
-                         skinnedMeshRenderer))
 
-                 {
 
-                     found = true;
 
-                     foundMaterial = cachedEcsGpuMaterial.material;
 
-                     break;
 
-                 }
 
-             }
 
-             return found;
 
-         }
 
-         
 
-         private static bool CheckSkinnedMeshRendererHasSameBones(SkinnedMeshRenderer skinnedMeshRendererA,
 
-             SkinnedMeshRenderer skinnedMeshRendererB)
 
-         {
 
-             bool hasSameBones = false;
 
-             if (skinnedMeshRendererA.bones.Length == skinnedMeshRendererB.bones.Length)
 
-             {
 
-                 hasSameBones = true;
 
-                 for (int i = 0; i < skinnedMeshRendererA.bones.Length; i++)
 
-                 {
 
-                     if (!CheckMatrixEquality(skinnedMeshRendererA.bones[i].localToWorldMatrix,
 
-                             skinnedMeshRendererB.bones[i].localToWorldMatrix))
 
-                     {
 
-                         hasSameBones = false; break;
 
-                     }
 
-                     if (!CheckMatrixEquality(skinnedMeshRendererA.sharedMesh.bindposes[i],
 
-                             skinnedMeshRendererB.sharedMesh.bindposes[i]))
 
-                     {
 
-                         hasSameBones = false; break;
 
-                     }
 
-                 }
 
-             }
 
-             return hasSameBones;
 
-         }
 
-         private static bool CheckMatrixEquality(Matrix4x4 m1, Matrix4x4 m2)
 
-         {
 
-             return m1.m00 == m2.m00 && m1.m01 == m2.m01 && m1.m02 == m2.m02 && m1.m03 == m2.m03
 
-                    && m1.m10 == m2.m10 && m1.m11 == m2.m11 && m1.m12 == m2.m12 && m1.m13 == m2.m13
 
-                    && m1.m20 == m2.m20 && m1.m21 == m2.m21 && m1.m22 == m2.m22 && m1.m23 == m2.m23
 
-                    && m1.m30 == m2.m30 && m1.m31 == m2.m31 && m1.m32 == m2.m32 && m1.m33 == m2.m33;
 
-         }
 
-         private static void IterateOverAllFramesThroughAnimator(
 
-             Animator refModelAnimator, GpuEcsAnimationBakerData bakerData, GpuEcsAnimationData[] animations,
 
-             System.Action<int> actionPerFrame)
 
-         {
 
-             refModelAnimator.speed = 0;
 
-             int currentFrameIndex = 0;
 
-             for (int animationIndex = 0; animationIndex < bakerData.animations.Length; animationIndex++)
 
-             {
 
-                 AnimationData animationData = bakerData.animations[animationIndex];
 
-                 GpuEcsAnimationData gpuEcsAnimationData = animations[animationIndex];
 
-                 foreach (AnimatorParameter parameterValue in animationData.additionalAnimatorParameterValues)
 
-                 {
 
-                     if(parameterValue.parameterType == AnimatorParameterTypes.Bool)
 
-                         refModelAnimator.SetBool(parameterValue.parameterName, parameterValue.boolValue);
 
-                     else if(parameterValue.parameterType == AnimatorParameterTypes.Float)
 
-                         refModelAnimator.SetFloat(parameterValue.parameterName, parameterValue.floatValue);
 
-                     else if(parameterValue.parameterType == AnimatorParameterTypes.Integer)
 
-                         refModelAnimator.SetInteger(parameterValue.parameterName, parameterValue.intValue);
 
-                 }
 
-                 
 
-                 for (int sampleIndex = 0; sampleIndex < gpuEcsAnimationData.nbrOfInBetweenSamples; sampleIndex++)
 
-                 {
 
-                     if (animationData.animationType == AnimationTypes.DualClipBlend)
 
-                     {
 
-                         DualClipBlendData dualClipBlendData = animationData.dualClipBlendData;
 
-                         float sampleRatio = (float)sampleIndex / (float)(gpuEcsAnimationData.nbrOfInBetweenSamples - 1);
 
-                         float blendValue = dualClipBlendData.clip1.parameterValue +
 
-                             (dualClipBlendData.clip2.parameterValue - dualClipBlendData.clip1.parameterValue) * sampleRatio;
 
-                         refModelAnimator.SetFloat(dualClipBlendData.blendParameterName, blendValue);
 
-                     }
 
-                     for (int frameIndex = 0; frameIndex < gpuEcsAnimationData.nbrOfFramesPerSample; frameIndex++)
 
-                     {
 
-                         float progressRatio = (float)frameIndex / (float)(gpuEcsAnimationData.nbrOfFramesPerSample - 1);
 
-                         refModelAnimator.Play(animationData.animatorStateName, -1, progressRatio);
 
-                         foreach(AnimatorState animatorState in animationData.additionalAnimatorStatesPerLayer)
 
-                             refModelAnimator.Play(animatorState.stateName, animatorState.layer, progressRatio);
 
-                         refModelAnimator.Update(0);
 
-                         actionPerFrame(currentFrameIndex);
 
-                         
 
-                         currentFrameIndex++;
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         private static GpuEcsAttachmentAnchorData BakeAttachmentAnchorTransforms(string generatedAssetsFolder, GameObject sourceModel,
 
-             string animatorName, Animator refModelAnimator, GpuEcsAnimationBakerData bakerData, GpuEcsAnimationData[] animations,
 
-             int totalNbrOfFrames,GpuEcsAnimatorBehaviour gpuEcsAnimator)
 
-         {
 
-             int nbrOfAttachments = bakerData.attachmentAnchors.Length;
 
-             if (nbrOfAttachments == 0) return null;
 
-             else
 
-             {
 
-                 GpuEcsAttachmentAnchorData gpuEcsAttachmentAnchorData = ScriptableObject.CreateInstance<GpuEcsAttachmentAnchorData>();
 
-                 gpuEcsAttachmentAnchorData.anchorTransforms = new float4x4[totalNbrOfFrames * nbrOfAttachments];
 
-                 gpuEcsAnimator.anchorNames.Clear();
 
-                 for (int attachmentAnchorIndex = 0; attachmentAnchorIndex < nbrOfAttachments; attachmentAnchorIndex++)
 
-                 {
 
-                     AttachmentAnchor attachmentAnchor = bakerData.attachmentAnchors[attachmentAnchorIndex];
 
-                     gpuEcsAnimator.anchorNames.Add(attachmentAnchor.attachmentAnchorID);
 
-                     Transform referenceAnchorTransform = attachmentAnchor.attachmentAnchorTransform;
 
-                     Stack<int> siblingIndexStack = new Stack<int>();
 
-                     GetSiblingIndexStack(referenceAnchorTransform, sourceModel.transform, siblingIndexStack);
 
-                     Transform anchorTransform = refModelAnimator.transform;
 
-                     while (siblingIndexStack.Count > 0)
 
-                         anchorTransform = anchorTransform.GetChild(siblingIndexStack.Pop());
 
-                     Debug.Assert(anchorTransform.name.Equals(referenceAnchorTransform.name));
 
-                     int baseIndex = attachmentAnchorIndex * totalNbrOfFrames;
 
-                     IterateOverAllFramesThroughAnimator(refModelAnimator, bakerData, animations,
 
-                         (currentFrameIndex) =>
 
-                         {
 
-                             gpuEcsAttachmentAnchorData.anchorTransforms[baseIndex + currentFrameIndex] = anchorTransform.localToWorldMatrix;
 
-                         });
 
-                 }
 
-                 string assetPath = GenerateAssetPath(generatedAssetsFolder, animatorName, "AttachmentAnchors", "asset");
 
-                 AssetDatabase.CreateAsset(gpuEcsAttachmentAnchorData, assetPath);
 
-                 return gpuEcsAttachmentAnchorData;
 
-             }
 
-         }
 
-         private static void GetSiblingIndexStack(Transform current, Transform root, Stack<int> currentStack)
 
-         {
 
-             if(current.gameObject == root.gameObject) return;
 
-             currentStack.Push(current.GetSiblingIndex());
 
-             GetSiblingIndexStack(current.parent, root, currentStack);
 
-         }
 
-         
 
-         private static Texture2D BakeAnimationMatricesTexture(SkinnedMeshRenderer skinnedMeshRenderer, 
 
-             Animator refModelAnimator, GpuEcsAnimationBakerData bakerData, GpuEcsAnimationData[] animations,
 
-             int totalNbrOfFrames)
 
-         {
 
-             int boneCount = skinnedMeshRenderer.bones.Length;
 
-             int animationMatricesTextureWidth = boneCount * 3;
 
-             NativeArray<half4> animatedBoneMatricesTextureData = new NativeArray<half4>(
 
-                 totalNbrOfFrames * animationMatricesTextureWidth, Allocator.Temp);
 
-             float4x4 invSkinnedMeshRendererLocalToWorld =  math.inverse(skinnedMeshRenderer.transform.localToWorldMatrix);
 
-             IterateOverAllFramesThroughAnimator(refModelAnimator, bakerData, animations,
 
-                 (currentFrameIndex) =>
 
-                 {
 
-                     for (int boneIndex = 0; boneIndex < boneCount; boneIndex++)
 
-                     {
 
-                         Transform boneTransform = skinnedMeshRenderer.bones[boneIndex];
 
-                         if (boneTransform != null)
 
-                         {
 
-                             float4x4 matrix = math.mul(
 
-                                 math.mul(invSkinnedMeshRendererLocalToWorld, boneTransform.localToWorldMatrix),
 
-                                 skinnedMeshRenderer.sharedMesh.bindposes[boneIndex]
 
-                             );
 
-                             Debug.Assert(Mathf.Approximately(matrix[0][3], 0f)
 
-                                 && Mathf.Approximately(matrix[1][3], 0f)
 
-                                 && Mathf.Approximately(matrix[2][3], 0f)
 
-                                 && Mathf.Approximately(matrix[3][3], 1f), "matrix row 4 must be 0,0,0,1");
 
-                             int matrixIndex = (currentFrameIndex * animationMatricesTextureWidth) + (boneIndex * 3);
 
-                             for (int i = 0; i < 3; i++)
 
-                                 animatedBoneMatricesTextureData[matrixIndex + i] = new half4(
 
-                                     (half)matrix[0][i], (half)matrix[1][i], (half)matrix[2][i], (half)matrix[3][i]);
 
-                         }
 
-                     }
 
-                 });
 
-             Texture2D animationMatricesTexture = new Texture2D(animationMatricesTextureWidth, totalNbrOfFrames, 
 
-                 TextureFormat.RGBAHalf, false);
 
-             animationMatricesTexture.SetPixelData(animatedBoneMatricesTextureData, 0);
 
-             animationMatricesTexture.Apply();
 
-             animatedBoneMatricesTextureData.Dispose();
 
-             return animationMatricesTexture;
 
-         }
 
-         
 
-         private static Mesh BakeBoneWeightsIntoMesh(Mesh sourceMesh, int maxNumberOfBonesPerVertex)
 
-         {
 
-             Mesh mesh = GameObject.Instantiate(sourceMesh);
 
-             
 
-             int vertexCount = mesh.vertices.Length;
 
-             NativeArray<Vector4> uvs1 = new NativeArray<Vector4>(vertexCount, Allocator.Temp);
 
-             NativeArray<Vector4> uvs2 = new NativeArray<Vector4>(vertexCount, Allocator.Temp);
 
-             NativeArray<Vector4> uvs3 = new NativeArray<Vector4>(vertexCount, Allocator.Temp);
 
-             NativeArray<byte> bonesPerVertex = mesh.GetBonesPerVertex();
 
-             NativeArray<BoneWeight1> boneWeightsSource = mesh.GetAllBoneWeights();
 
-             int startBoneWeightIndex = 0;
 
-             for (int vertIndex = 0; vertIndex < vertexCount; vertIndex++)
 
-             {
 
-                 float totalWeight = 0f;
 
-                 float totalWeightCapped = 0f;
 
-                 int numberOfBonesForThisVertex = bonesPerVertex[vertIndex];
 
-                 int boneWeightIndexTemp = startBoneWeightIndex;
 
-                 for (int i = 0; i < numberOfBonesForThisVertex; i++)
 
-                 {
 
-                     BoneWeight1 currentBoneWeight = boneWeightsSource[boneWeightIndexTemp];
 
-                     totalWeight += currentBoneWeight.weight;
 
-                     if (i < maxNumberOfBonesPerVertex) totalWeightCapped += currentBoneWeight.weight;
 
-                     if (i > 0) Debug.Assert(boneWeightsSource[boneWeightIndexTemp - 1].weight >= currentBoneWeight.weight);
 
-                     boneWeightIndexTemp++;
 
-                 }
 
-                 Debug.Assert(Mathf.Approximately(1f, totalWeight));
 
-                 float weightMultiplier = totalWeight / totalWeightCapped;
 
-                 int nbrOfBonesToBake = math.min(maxNumberOfBonesPerVertex, numberOfBonesForThisVertex);
 
-                 totalWeight = 0f;
 
-                 boneWeightIndexTemp = startBoneWeightIndex;
 
-                 float4 uv1 = float4.zero;
 
-                 float4 uv2 = float4.zero;
 
-                 float4 uv3 = float4.zero;
 
-                 for (int i = 0; i < nbrOfBonesToBake; i++)
 
-                 {
 
-                     BoneWeight1 currentBoneWeight = boneWeightsSource[boneWeightIndexTemp];
 
-                     float adjustedWeight = currentBoneWeight.weight * weightMultiplier; 
 
-                     totalWeight += adjustedWeight;
 
-                     boneWeightIndexTemp++;
 
-                     if      (i == 0) uv1 = new float4(currentBoneWeight.boneIndex, adjustedWeight, uv1.z, uv1.w);
 
-                     else if (i == 1) uv1 = new float4(uv1.x, uv1. y, currentBoneWeight.boneIndex, adjustedWeight);
 
-                     else if (i == 2) uv2 = new float4(currentBoneWeight.boneIndex, adjustedWeight, uv2.z, uv2.w);
 
-                     else if (i == 3) uv2 = new float4(uv2.x, uv2. y, currentBoneWeight.boneIndex, adjustedWeight);
 
-                     else if (i == 4) uv3 = new float4(currentBoneWeight.boneIndex, adjustedWeight, uv3.z, uv3.w);
 
-                     else if (i == 5) uv3 = new float4(uv3.x, uv3. y, currentBoneWeight.boneIndex, adjustedWeight);
 
-                 }
 
-                 Debug.Assert(Mathf.Approximately(1f, totalWeight));
 
-                 uvs1[vertIndex] = uv1;
 
-                 uvs2[vertIndex] = uv2;
 
-                 uvs3[vertIndex] = uv3;
 
-                 startBoneWeightIndex += numberOfBonesForThisVertex;
 
-             }
 
-             
 
-             mesh.SetUVs(1, uvs1);
 
-             mesh.SetUVs(2, uvs2);
 
-             mesh.SetUVs(3, uvs3);
 
-             
 
-             uvs1.Dispose();
 
-             uvs2.Dispose();
 
-             uvs3.Dispose();
 
-             bonesPerVertex.Dispose();
 
-             boneWeightsSource.Dispose();
 
-             return mesh;
 
-         }
 
-     }
 
- }
 
- #endif
 
 
  |