Files
Fishing2/Assets/KINEMATION/MagicBlend/Runtime/MagicBlendLibrary.cs

151 lines
5.2 KiB
C#

// Designed by KINEMATION, 2025.
using KINEMATION.KAnimationCore.Runtime.Core;
using KINEMATION.KAnimationCore.Runtime.Rig;
using System;
using System.Collections.Generic;
using KINEMATION.KAnimationCore.Runtime.Attributes;
using Unity.Collections;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Playables;
namespace KINEMATION.MagicBlend.Runtime
{
public struct AtomPose
{
public KTransform basePose;
public KTransform overlayPose;
public Quaternion localOverlayRotation;
public float baseWeight;
public float additiveWeight;
public float localWeight;
public static AtomPose Lerp(AtomPose a, AtomPose b, float alpha)
{
AtomPose outPose = new AtomPose();
outPose.basePose = KTransform.Lerp(a.basePose, b.basePose, alpha);
outPose.overlayPose = KTransform.Lerp(a.overlayPose, b.overlayPose, alpha);
outPose.localOverlayRotation = Quaternion.Slerp(a.localOverlayRotation, b.localOverlayRotation, alpha);
outPose.additiveWeight = Mathf.Lerp(a.additiveWeight, b.additiveWeight, alpha);
outPose.baseWeight = Mathf.Lerp(a.baseWeight, b.baseWeight, alpha);
outPose.localWeight = Mathf.Lerp(a.localWeight, b.localWeight, alpha);
return outPose;
}
}
public struct BlendStreamAtom
{
[Unity.Collections.ReadOnly] public TransformStreamHandle handle;
[Unity.Collections.ReadOnly] public float baseWeight;
[Unity.Collections.ReadOnly] public float additiveWeight;
[Unity.Collections.ReadOnly] public float localWeight;
public KTransform meshStreamPose;
public AtomPose activePose;
public AtomPose cachedPose;
public AtomPose GetBlendedAtomPose(float blendWeight)
{
return AtomPose.Lerp(cachedPose, activePose, blendWeight);
}
}
[Serializable]
public struct LayeredBlend
{
[CustomElementChainDrawer(false, true)]
public KRigElementChain layer;
[Range(0f, 1f)] public float baseWeight;
[Range(0f, 1f)] public float additiveWeight;
[Range(0f, 1f)] public float localWeight;
}
[Serializable]
public struct OverrideOverlay
{
public AnimationClip overlay;
public AvatarMask mask;
[Range(0f, 1f)] public float weight;
}
public class MagicBlendLibrary
{
public static NativeArray<BlendStreamAtom> SetupBlendAtoms(Animator animator, KRigComponent rigComponent)
{
var bones = rigComponent.GetRigTransforms();
int num = bones.Length;
var blendAtoms = new NativeArray<BlendStreamAtom>(num, Allocator.Persistent);
for (int i = 0; i < num; i++)
{
Transform bone = bones[i];
blendAtoms[i] = new BlendStreamAtom()
{
handle = animator.BindStreamTransform(bone)
};
}
return blendAtoms;
}
public static void ConnectPose(AnimationScriptPlayable playable, PlayableGraph graph, AnimationClip pose,
float speed = 0f)
{
if (playable.GetInput(0).IsValid())
{
playable.DisconnectInput(0);
}
var posePlayable = AnimationClipPlayable.Create(graph, pose);
posePlayable.SetSpeed(speed);
posePlayable.SetApplyFootIK(false);
playable.ConnectInput(0, posePlayable, 0, 1f);
}
public static void ConnectOverlays(AnimationScriptPlayable playable, PlayableGraph graph,
AnimationClip pose, List<OverrideOverlay> overrides, float speed = 0f)
{
if (playable.GetInput(0).IsValid())
{
playable.DisconnectInput(0);
}
if (overrides == null || overrides.Count == 0)
{
ConnectPose(playable, graph, pose, speed);
return;
}
var mixer = AnimationLayerMixerPlayable.Create(graph);
var overlayPlayable = AnimationClipPlayable.Create(graph, pose);
overlayPlayable.SetDuration(pose.length);
overlayPlayable.SetSpeed(speed);
overlayPlayable.SetApplyFootIK(false);
mixer.AddInput(overlayPlayable, 0, 1f);
foreach (var overlayOverride in overrides)
{
var posePlayable = AnimationClipPlayable.Create(graph, overlayOverride.overlay);
posePlayable.SetDuration(overlayOverride.overlay.length);
posePlayable.SetSpeed(speed);
posePlayable.SetApplyFootIK(false);
var index = mixer.AddInput(posePlayable, 0, overlayOverride.weight);
var mask = overlayOverride.mask == null ? new AvatarMask() : overlayOverride.mask;
mixer.SetLayerMaskFromAvatarMask((uint) index, mask);
}
playable.ConnectInput(0, mixer, 0, 1f);
}
}
}