259 lines
7.9 KiB
C#
259 lines
7.9 KiB
C#
#if UNITY_EDITOR
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Rukhanka.Toolbox;
|
|
using Unity.Collections;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
using Unity.Entities;
|
|
using UnityEditor;
|
|
using UnityEditor.Animations;
|
|
using UnityEngine;
|
|
using Hash128 = Unity.Entities.Hash128;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace Rukhanka.Hybrid
|
|
{
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
public partial class AnimatorControllerBaker: Baker<Animator>
|
|
{
|
|
public override void Bake(Animator a)
|
|
{
|
|
// Skip animators without rig definition
|
|
var rd = a.GetComponent<RigDefinitionAuthoring>();
|
|
if (rd == null)
|
|
return;
|
|
|
|
if (a.runtimeAnimatorController == null)
|
|
{
|
|
Debug.LogWarning($"There is no controller attached to '{a.name}' animator. Skipping this object");
|
|
return;
|
|
}
|
|
|
|
var e = GetEntity(TransformUsageFlags.Dynamic);
|
|
|
|
var rac = GetRuntimeAnimatorController(a);
|
|
var ac = GetAnimatorControllerFromRuntime(rac);
|
|
var controllerBlob = BuildControllerBlob(ac, rd);
|
|
var controllerAnimationHashesBlob = BuildControllerAnimationHashesBlob(ac, a.avatar);
|
|
|
|
var animationsFromOverrideController = GetAnimationsFromOverrideController(a);
|
|
var allClips = new AnimationClip[animationsFromOverrideController.Length + ac.animationClips.Length];
|
|
animationsFromOverrideController.CopyTo(allClips, 0);
|
|
ac.animationClips.CopyTo(allClips, animationsFromOverrideController.Length);
|
|
BakeAllControllerAnimations(e, a.avatar, allClips, a.gameObject);
|
|
BakeAllUsedAvatarMasks(e, ac, rd);
|
|
|
|
CreateControllerEntityComponents(rd, e, controllerBlob, controllerAnimationHashesBlob);
|
|
CreateOverrideAnimationsBuffer(e, a, ac);
|
|
|
|
DependsOn(ac);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
RuntimeAnimatorController GetRuntimeAnimatorController(Animator a)
|
|
{
|
|
var rv = a.runtimeAnimatorController;
|
|
// Check for animator override controller
|
|
var aoc = rv as AnimatorOverrideController;
|
|
if (aoc != null)
|
|
{
|
|
rv = aoc.runtimeAnimatorController;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
AnimatorController GetAnimatorControllerFromRuntime(RuntimeAnimatorController rac)
|
|
{
|
|
if (rac == null)
|
|
return null;
|
|
|
|
var acPath = AssetDatabase.GetAssetPath(rac);
|
|
var controller = AssetDatabase.LoadAssetAtPath<AnimatorController>(acPath);
|
|
return controller;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
AnimationClip[] GetAnimationsFromOverrideController(Animator animator)
|
|
{
|
|
var aoc = GetOverrideController(animator);
|
|
if (aoc == null)
|
|
return Array.Empty<AnimationClip>();
|
|
|
|
var overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
|
|
aoc.GetOverrides(overrides);
|
|
|
|
var rv = new List<AnimationClip>();
|
|
for (var i = 0; i < overrides.Count; ++i)
|
|
{
|
|
var dstAnm = overrides[i].Value;
|
|
if (dstAnm != null)
|
|
rv.Add(dstAnm);
|
|
}
|
|
return rv.ToArray();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void BakeAllUsedAvatarMasks(Entity e, AnimatorController controller, RigDefinitionAuthoring rd)
|
|
{
|
|
var bakedAvatarMasks = new NativeList<AvatarMaskBakingData>(Allocator.Temp);
|
|
for (int i = 0; i < controller.layers.Length; ++i)
|
|
{
|
|
var l = controller.layers[i];
|
|
if (l.avatarMask != null)
|
|
{
|
|
var amb = new AvatarMaskBaker();
|
|
var avatarMaskBlobAsset = amb.CreateAvatarMaskBlob(this, l.avatarMask, rd);
|
|
var newAvatarMaskBlob = new AvatarMaskBakingData()
|
|
{
|
|
rigEntity = e,
|
|
dataBlob = avatarMaskBlobAsset
|
|
};
|
|
bakedAvatarMasks.Add(newAvatarMaskBlob);
|
|
}
|
|
}
|
|
|
|
if (bakedAvatarMasks.Length > 0)
|
|
{
|
|
var buf = AddBuffer<AvatarMaskBakingData>(e);
|
|
buf.AddRange(bakedAvatarMasks.AsArray());
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void BakeAllControllerAnimations(Entity e, Avatar avatar, AnimationClip[] animationClips, GameObject go)
|
|
{
|
|
var animationBaker = new AnimationClipBaker();
|
|
var bakedClipBlobs = animationBaker.BakeAnimations(this, animationClips, avatar, go);
|
|
var newAnimationClips = AddBuffer<NewBlobAssetDatabaseRecord<AnimationClipBlob>>(e);
|
|
foreach (var bcb in bakedClipBlobs)
|
|
{
|
|
if (!bcb.IsCreated)
|
|
continue;
|
|
|
|
newAnimationClips.Add(new ()
|
|
{
|
|
value = bcb,
|
|
hash = bcb.Value.hash
|
|
});
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CreateControllerParametersComponents(Entity e, BlobAssetReference<ControllerBlob> cb)
|
|
{
|
|
ref var parameters = ref cb.Value.parameters;
|
|
if (parameters.Length == 0)
|
|
return;
|
|
|
|
// Add dynamic parameters
|
|
var paramArray = AddBuffer<AnimatorControllerParameterComponent>(e);
|
|
for (int p = 0; p < parameters.Length; ++p)
|
|
{
|
|
ref var pm = ref parameters[p];
|
|
var acpc = new AnimatorControllerParameterComponent()
|
|
{
|
|
value = pm.defaultValue,
|
|
hash = pm.hash,
|
|
type = pm.type,
|
|
};
|
|
|
|
#if RUKHANKA_DEBUG_INFO
|
|
pm.name.CopyToWithTruncate(ref acpc.name);
|
|
#endif
|
|
|
|
paramArray.Add(acpc);
|
|
}
|
|
|
|
// Add perfect hash table used to fast runtime parameter value lookup
|
|
var parametersPerfectHashTableBlob = CreateParametersPerfectHashTableBlob(cb);
|
|
var pht = new AnimatorControllerParameterIndexTableComponent()
|
|
{
|
|
value = parametersPerfectHashTableBlob
|
|
};
|
|
AddComponent(e, pht);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
AnimatorOverrideController GetOverrideController(Animator animator)
|
|
{
|
|
var rac = animator.runtimeAnimatorController;
|
|
var aoc = rac as AnimatorOverrideController;
|
|
return aoc;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CreateOverrideAnimationsBuffer(Entity e, Animator animator, AnimatorController ac)
|
|
{
|
|
var aoc = GetOverrideController(animator);
|
|
if (aoc == null)
|
|
return;
|
|
|
|
var overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
|
|
aoc.GetOverrides(overrides);
|
|
|
|
var bb = new BlobBuilder(Allocator.Temp);
|
|
ref var cab = ref bb.ConstructRoot<ControllerAnimationsBlob>();
|
|
var animsArr = bb.Allocate(ref cab.animations, ac.animationClips.Length);
|
|
for (var i = 0; i < overrides.Count; ++i)
|
|
{
|
|
var kv = overrides[i];
|
|
if (kv.Value == null)
|
|
continue;
|
|
|
|
var replacedIndex = Array.IndexOf(ac.animationClips, kv.Key);
|
|
if (replacedIndex >= 0)
|
|
animsArr[replacedIndex] = BakingUtils.ComputeAnimationHash(kv.Value, animator.avatar);
|
|
}
|
|
|
|
var blobAsset = bb.CreateBlobAssetReference<ControllerAnimationsBlob>(Allocator.Persistent);
|
|
AddBlobAsset(ref blobAsset, out _);
|
|
|
|
AddComponent(e, new AnimatorOverrideAnimations() { value = blobAsset });
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CreateControllerEntityComponents
|
|
(
|
|
RigDefinitionAuthoring rda,
|
|
Entity e,
|
|
BlobAssetReference<ControllerBlob> controllerBlob,
|
|
BlobAssetReference<ControllerAnimationsBlob> controllerAnimationsBlob
|
|
)
|
|
{
|
|
var acc = new AnimatorControllerLayerComponent();
|
|
acc.rtd = RuntimeAnimatorData.MakeDefault();
|
|
acc.controller = controllerBlob;
|
|
acc.animations = controllerAnimationsBlob;
|
|
acc.speed = 1;
|
|
|
|
var buf = AddBuffer<AnimatorControllerLayerComponent>(e);
|
|
ref var cb = ref controllerBlob.Value;
|
|
for (int k = 0; k < cb.layers.Length; ++k)
|
|
{
|
|
acc.layerIndex = k;
|
|
acc.weight = cb.layers[k].initialWeight;
|
|
buf.Add(acc);
|
|
}
|
|
|
|
if (rda.hasAnimatorControllerEvents)
|
|
AddBuffer<AnimatorControllerEventComponent>(e);
|
|
|
|
CreateControllerParametersComponents(e, controllerBlob);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif |