导入角色动画,和增加角色控制
This commit is contained in:
3
Assets/KINEMATION/MagicBlend/Editor.meta
Normal file
3
Assets/KINEMATION/MagicBlend/Editor.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edcbba090fe44fdabe307c9f4b429dda
|
||||
timeCreated: 1723535182
|
||||
88
Assets/KINEMATION/MagicBlend/Editor/MagicBlendContextMenu.cs
Normal file
88
Assets/KINEMATION/MagicBlend/Editor/MagicBlendContextMenu.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
// Designed by KINEMATION, 2025.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using KINEMATION.KAnimationCore.Editor;
|
||||
using KINEMATION.KAnimationCore.Runtime.Rig;
|
||||
using KINEMATION.MagicBlend.Runtime;
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.MagicBlend.Editor
|
||||
{
|
||||
public class MagicBlendContextMenu
|
||||
{
|
||||
private const string ItemName = "Assets/Create Magic Blend";
|
||||
|
||||
public static KRigElementChain[] GetMatchingChains(KRig rig, string[] queries)
|
||||
{
|
||||
List<KRigElementChain> chains = new List<KRigElementChain>();
|
||||
|
||||
foreach (var elementChain in rig.rigElementChains)
|
||||
{
|
||||
foreach (var query in queries)
|
||||
{
|
||||
if (!elementChain.chainName.ToLower().Contains(query.ToLower())) continue;
|
||||
|
||||
chains.Add(elementChain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return chains.ToArray();
|
||||
}
|
||||
|
||||
public static KRigElementChain MergeChains(string name, in KRigElementChain[] chains)
|
||||
{
|
||||
KRigElementChain mergedChain = new KRigElementChain();
|
||||
mergedChain.chainName = name;
|
||||
|
||||
foreach (var chain in chains)
|
||||
{
|
||||
if(chain == null) continue;
|
||||
foreach (var element in chain.elementChain) mergedChain.elementChain.Add(element);
|
||||
}
|
||||
|
||||
return mergedChain;
|
||||
}
|
||||
|
||||
public static void AddCompositeChain(MagicBlendAsset blendAsset, string name, string[] queries)
|
||||
{
|
||||
blendAsset.layeredBlends.Add(new LayeredBlend()
|
||||
{
|
||||
layer = MergeChains(name, GetMatchingChains(blendAsset.rigAsset, queries))
|
||||
});
|
||||
}
|
||||
|
||||
[MenuItem(ItemName, true)]
|
||||
private static bool ValidateCreateRigMapping()
|
||||
{
|
||||
return Selection.activeObject is KRig;
|
||||
}
|
||||
|
||||
[MenuItem(ItemName)]
|
||||
private static void CreateRigMapping()
|
||||
{
|
||||
KRig rig = Selection.activeObject as KRig;
|
||||
if (rig == null) return;
|
||||
|
||||
MagicBlendAsset blendAsset = ScriptableObject.CreateInstance<MagicBlendAsset>();
|
||||
blendAsset.rigAsset = rig;
|
||||
|
||||
AddCompositeChain(blendAsset, "LowerBody", new[] {"pelvis", "hip", "leg", "thigh"});
|
||||
AddCompositeChain(blendAsset, "Spine", new[] {"spine"});
|
||||
AddCompositeChain(blendAsset, "Head", new[] {"neck", "head"});
|
||||
AddCompositeChain(blendAsset, "Arms", new[] {"arm", "clavicle", "shoulder"});
|
||||
AddCompositeChain(blendAsset, "Fingers", new[]
|
||||
{
|
||||
"finger", "index", "thumb", "pinky", "ring", "middle"
|
||||
});
|
||||
|
||||
string assetName = rig.name.Replace("Rig_", "");
|
||||
assetName = assetName.Replace("Rig", "");
|
||||
|
||||
KEditorUtility.SaveAsset(blendAsset, KEditorUtility.GetProjectActiveFolder(),
|
||||
$"MagicBlend_{assetName}.asset");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4d0f5047e1d4badb94456da709f642f
|
||||
timeCreated: 1723535203
|
||||
63
Assets/KINEMATION/MagicBlend/Editor/MagicDragAndDrop.cs
Normal file
63
Assets/KINEMATION/MagicBlend/Editor/MagicDragAndDrop.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
// Designed by KINEMATION, 2025.
|
||||
|
||||
using KINEMATION.MagicBlend.Runtime;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.MagicBlend.Editor
|
||||
{
|
||||
public class MagicDragAndDrop
|
||||
{
|
||||
private static DragAndDropVisualMode OnHierarchyDrop(int dropTargetInstanceID, HierarchyDropFlags dropMode,
|
||||
Transform parentForDraggedObjects, bool perform)
|
||||
{
|
||||
var asset = DragAndDrop.objectReferences[0] as MagicBlendAsset;
|
||||
if (asset == null)
|
||||
{
|
||||
return DragAndDropVisualMode.None;
|
||||
}
|
||||
|
||||
if (perform)
|
||||
{
|
||||
var selection = Selection.activeGameObject;
|
||||
if (selection != null)
|
||||
{
|
||||
var component = selection.GetComponent<MagicBlending>();
|
||||
if (component == null) component = selection.AddComponent<MagicBlending>();
|
||||
component.SetMagicBlendAsset(asset);
|
||||
}
|
||||
}
|
||||
|
||||
return DragAndDropVisualMode.Copy;
|
||||
}
|
||||
|
||||
private static DragAndDropVisualMode OnInspectorDrop(UnityEngine.Object[] targets, bool perform)
|
||||
{
|
||||
var asset = DragAndDrop.objectReferences[0] as MagicBlendAsset;
|
||||
if (asset == null)
|
||||
{
|
||||
return DragAndDropVisualMode.None;
|
||||
}
|
||||
|
||||
if (perform)
|
||||
{
|
||||
var selection = Selection.activeGameObject;
|
||||
if (selection != null)
|
||||
{
|
||||
var component = selection.GetComponent<MagicBlending>();
|
||||
if (component == null) component = selection.AddComponent<MagicBlending>();
|
||||
component.SetMagicBlendAsset(asset);
|
||||
}
|
||||
}
|
||||
|
||||
return DragAndDropVisualMode.Copy;
|
||||
}
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
private static void OnLoad()
|
||||
{
|
||||
DragAndDrop.AddDropHandler(OnInspectorDrop);
|
||||
DragAndDrop.AddDropHandler(OnHierarchyDrop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b975fde8b324849b0ea1eed6f492101
|
||||
timeCreated: 1734451661
|
||||
291
Assets/KINEMATION/MagicBlend/MagicBlend_Human_Male.asset
Normal file
291
Assets/KINEMATION/MagicBlend/MagicBlend_Human_Male.asset
Normal file
@@ -0,0 +1,291 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: cea8c2a1237b4b5b8bbfd16a4f12cc26, type: 3}
|
||||
m_Name: MagicBlend_Human_Male
|
||||
m_EditorClassIdentifier: Assembly-CSharp::KINEMATION.MagicBlend.Runtime.MagicBlendAsset
|
||||
rigAsset: {fileID: 11400000, guid: 14f74f4e0df7b30439cf0f73a77ef074, type: 2}
|
||||
blendTime: 0.15
|
||||
blendCurve:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0
|
||||
outWeight: 0
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 4
|
||||
basePose: {fileID: -2576967968662016515, guid: 56fd86b76fc74d24d83522069f5deb9b, type: 3}
|
||||
overlayPose: {fileID: 7400000, guid: 00da029521b8d2541bb4f6a7565e64b7, type: 2}
|
||||
overrideOverlays: []
|
||||
overlaySpeed: 1
|
||||
isAnimation: 1
|
||||
blendOutType: 0
|
||||
layeredBlends:
|
||||
- layer:
|
||||
chainName: LowerBody
|
||||
elementChain:
|
||||
- name: pelvis_wt
|
||||
index: 2
|
||||
depth: -1
|
||||
- name: thigh_l
|
||||
index: 113
|
||||
depth: -1
|
||||
- name: calf_l
|
||||
index: 114
|
||||
depth: -1
|
||||
- name: foot_l
|
||||
index: 117
|
||||
depth: -1
|
||||
- name: ball_l
|
||||
index: 118
|
||||
depth: -1
|
||||
- name: thigh_r
|
||||
index: 121
|
||||
depth: -1
|
||||
- name: calf_r
|
||||
index: 122
|
||||
depth: -1
|
||||
- name: foot_r
|
||||
index: 125
|
||||
depth: -1
|
||||
- name: ball_r
|
||||
index: 126
|
||||
depth: -1
|
||||
baseWeight: 0
|
||||
additiveWeight: 0
|
||||
localWeight: 0
|
||||
- layer:
|
||||
chainName: Spine
|
||||
elementChain:
|
||||
- name: spine_01
|
||||
index: 5
|
||||
depth: -1
|
||||
- name: spine_01_wt
|
||||
index: 6
|
||||
depth: -1
|
||||
- name: spine_02
|
||||
index: 7
|
||||
depth: -1
|
||||
- name: spine_02_wt
|
||||
index: 8
|
||||
depth: -1
|
||||
- name: spine_03
|
||||
index: 9
|
||||
depth: -1
|
||||
- name: spine_03_wt
|
||||
index: 10
|
||||
depth: -1
|
||||
- name: spine_04
|
||||
index: 11
|
||||
depth: -1
|
||||
- name: spine_04_wt
|
||||
index: 12
|
||||
depth: -1
|
||||
- name: spine_05
|
||||
index: 13
|
||||
depth: -1
|
||||
- name: spine_05_wt
|
||||
index: 110
|
||||
depth: -1
|
||||
baseWeight: 0
|
||||
additiveWeight: 0
|
||||
localWeight: 0
|
||||
- layer:
|
||||
chainName: Head
|
||||
elementChain:
|
||||
- name: neck_01
|
||||
index: 68
|
||||
depth: -1
|
||||
- name: neck_01_wt
|
||||
index: 69
|
||||
depth: -1
|
||||
- name: neck_02
|
||||
index: 70
|
||||
depth: -1
|
||||
- name: head
|
||||
index: 71
|
||||
depth: -1
|
||||
- name: facial_root
|
||||
index: 72
|
||||
depth: -1
|
||||
- name: neck_02_wt
|
||||
index: 109
|
||||
depth: -1
|
||||
baseWeight: 0
|
||||
additiveWeight: 0
|
||||
localWeight: 0
|
||||
- layer:
|
||||
chainName: Arms
|
||||
elementChain:
|
||||
- name: clavicle_l
|
||||
index: 14
|
||||
depth: -1
|
||||
- name: upperarm_l
|
||||
index: 15
|
||||
depth: -1
|
||||
- name: lowerarm_l
|
||||
index: 16
|
||||
depth: -1
|
||||
- name: hand_l
|
||||
index: 17
|
||||
depth: -1
|
||||
- name: clavicle_r
|
||||
index: 41
|
||||
depth: -1
|
||||
- name: upperarm_r
|
||||
index: 42
|
||||
depth: -1
|
||||
- name: lowerarm_r
|
||||
index: 43
|
||||
depth: -1
|
||||
- name: hand_r
|
||||
index: 44
|
||||
depth: -1
|
||||
baseWeight: 0
|
||||
additiveWeight: 0
|
||||
localWeight: 0
|
||||
- layer:
|
||||
chainName: Fingers
|
||||
elementChain:
|
||||
- name: index_metacarpal_l
|
||||
index: 18
|
||||
depth: -1
|
||||
- name: index_01_l
|
||||
index: 19
|
||||
depth: -1
|
||||
- name: index_02_l
|
||||
index: 20
|
||||
depth: -1
|
||||
- name: index_03_l
|
||||
index: 21
|
||||
depth: -1
|
||||
- name: middle_metacarpal_l
|
||||
index: 22
|
||||
depth: -1
|
||||
- name: middle_01_l
|
||||
index: 23
|
||||
depth: -1
|
||||
- name: middle_02_l
|
||||
index: 24
|
||||
depth: -1
|
||||
- name: middle_03_l
|
||||
index: 25
|
||||
depth: -1
|
||||
- name: pinky_metacarpal_l
|
||||
index: 26
|
||||
depth: -1
|
||||
- name: pinky_01_l
|
||||
index: 27
|
||||
depth: -1
|
||||
- name: pinky_02_l
|
||||
index: 28
|
||||
depth: -1
|
||||
- name: pinky_03_l
|
||||
index: 29
|
||||
depth: -1
|
||||
- name: ring_metacarpal_l
|
||||
index: 30
|
||||
depth: -1
|
||||
- name: ring_01_l
|
||||
index: 31
|
||||
depth: -1
|
||||
- name: ring_02_l
|
||||
index: 32
|
||||
depth: -1
|
||||
- name: ring_03_l
|
||||
index: 33
|
||||
depth: -1
|
||||
- name: thumb_01_l
|
||||
index: 34
|
||||
depth: -1
|
||||
- name: thumb_02_l
|
||||
index: 35
|
||||
depth: -1
|
||||
- name: thumb_03_l
|
||||
index: 36
|
||||
depth: -1
|
||||
- name: index_metacarpal_r
|
||||
index: 45
|
||||
depth: -1
|
||||
- name: index_01_r
|
||||
index: 46
|
||||
depth: -1
|
||||
- name: index_02_r
|
||||
index: 47
|
||||
depth: -1
|
||||
- name: index_03_r
|
||||
index: 48
|
||||
depth: -1
|
||||
- name: middle_metacarpal_r
|
||||
index: 49
|
||||
depth: -1
|
||||
- name: middle_01_r
|
||||
index: 50
|
||||
depth: -1
|
||||
- name: middle_02_r
|
||||
index: 51
|
||||
depth: -1
|
||||
- name: middle_03_r
|
||||
index: 52
|
||||
depth: -1
|
||||
- name: pinky_metacarpal_r
|
||||
index: 53
|
||||
depth: -1
|
||||
- name: pinky_01_r
|
||||
index: 54
|
||||
depth: -1
|
||||
- name: pinky_02_r
|
||||
index: 55
|
||||
depth: -1
|
||||
- name: pinky_03_r
|
||||
index: 56
|
||||
depth: -1
|
||||
- name: ring_metacarpal_r
|
||||
index: 57
|
||||
depth: -1
|
||||
- name: ring_01_r
|
||||
index: 58
|
||||
depth: -1
|
||||
- name: ring_02_r
|
||||
index: 59
|
||||
depth: -1
|
||||
- name: ring_03_r
|
||||
index: 60
|
||||
depth: -1
|
||||
- name: thumb_01_r
|
||||
index: 61
|
||||
depth: -1
|
||||
- name: thumb_02_r
|
||||
index: 62
|
||||
depth: -1
|
||||
- name: thumb_03_r
|
||||
index: 63
|
||||
depth: -1
|
||||
baseWeight: 0
|
||||
additiveWeight: 0
|
||||
localWeight: 0
|
||||
globalWeight: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7577c336826c904dbb602c236c862f9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/KINEMATION/MagicBlend/Offline Documentation.pdf
Normal file
BIN
Assets/KINEMATION/MagicBlend/Offline Documentation.pdf
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: deffcc421b0049141b8b8bcbf0f13256
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
5
Assets/KINEMATION/MagicBlend/Online Documentation.url
Normal file
5
Assets/KINEMATION/MagicBlend/Online Documentation.url
Normal file
@@ -0,0 +1,5 @@
|
||||
[{000214A0-0000-0000-C000-000000000046}]
|
||||
Prop3=19,11
|
||||
[InternetShortcut]
|
||||
IDList=
|
||||
URL=https://kinemation.gitbook.io/magic-blend-documentation/
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b06b12160ac408489f90daffebb4e25
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/KINEMATION/MagicBlend/README.pdf
Normal file
BIN
Assets/KINEMATION/MagicBlend/README.pdf
Normal file
Binary file not shown.
7
Assets/KINEMATION/MagicBlend/README.pdf.meta
Normal file
7
Assets/KINEMATION/MagicBlend/README.pdf.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2926bc3ed8bd5b5488b41e96ee273f43
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
880
Assets/KINEMATION/MagicBlend/Rig_Human_Male.asset
Normal file
880
Assets/KINEMATION/MagicBlend/Rig_Human_Male.asset
Normal file
@@ -0,0 +1,880 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 8c9c04639ae548bdb0a8e927492d029d, type: 3}
|
||||
m_Name: Rig_Human_Male
|
||||
m_EditorClassIdentifier: KAnimationCore.Runtime::KINEMATION.KAnimationCore.Runtime.Rig.KRig
|
||||
targetAnimator: {fileID: 0}
|
||||
rigHierarchy:
|
||||
- name: root
|
||||
index: 0
|
||||
depth: -1
|
||||
- name: pelvis
|
||||
index: 1
|
||||
depth: -1
|
||||
- name: pelvis_wt
|
||||
index: 2
|
||||
depth: -1
|
||||
- name: butt_l
|
||||
index: 3
|
||||
depth: -1
|
||||
- name: butt_r
|
||||
index: 4
|
||||
depth: -1
|
||||
- name: spine_01
|
||||
index: 5
|
||||
depth: -1
|
||||
- name: spine_01_wt
|
||||
index: 6
|
||||
depth: -1
|
||||
- name: spine_02
|
||||
index: 7
|
||||
depth: -1
|
||||
- name: spine_02_wt
|
||||
index: 8
|
||||
depth: -1
|
||||
- name: spine_03
|
||||
index: 9
|
||||
depth: -1
|
||||
- name: spine_03_wt
|
||||
index: 10
|
||||
depth: -1
|
||||
- name: spine_04
|
||||
index: 11
|
||||
depth: -1
|
||||
- name: spine_04_wt
|
||||
index: 12
|
||||
depth: -1
|
||||
- name: spine_05
|
||||
index: 13
|
||||
depth: -1
|
||||
- name: clavicle_l
|
||||
index: 14
|
||||
depth: -1
|
||||
- name: upperarm_l
|
||||
index: 15
|
||||
depth: -1
|
||||
- name: lowerarm_l
|
||||
index: 16
|
||||
depth: -1
|
||||
- name: hand_l
|
||||
index: 17
|
||||
depth: -1
|
||||
- name: index_metacarpal_l
|
||||
index: 18
|
||||
depth: -1
|
||||
- name: index_01_l
|
||||
index: 19
|
||||
depth: -1
|
||||
- name: index_02_l
|
||||
index: 20
|
||||
depth: -1
|
||||
- name: index_03_l
|
||||
index: 21
|
||||
depth: -1
|
||||
- name: middle_metacarpal_l
|
||||
index: 22
|
||||
depth: -1
|
||||
- name: middle_01_l
|
||||
index: 23
|
||||
depth: -1
|
||||
- name: middle_02_l
|
||||
index: 24
|
||||
depth: -1
|
||||
- name: middle_03_l
|
||||
index: 25
|
||||
depth: -1
|
||||
- name: pinky_metacarpal_l
|
||||
index: 26
|
||||
depth: -1
|
||||
- name: pinky_01_l
|
||||
index: 27
|
||||
depth: -1
|
||||
- name: pinky_02_l
|
||||
index: 28
|
||||
depth: -1
|
||||
- name: pinky_03_l
|
||||
index: 29
|
||||
depth: -1
|
||||
- name: ring_metacarpal_l
|
||||
index: 30
|
||||
depth: -1
|
||||
- name: ring_01_l
|
||||
index: 31
|
||||
depth: -1
|
||||
- name: ring_02_l
|
||||
index: 32
|
||||
depth: -1
|
||||
- name: ring_03_l
|
||||
index: 33
|
||||
depth: -1
|
||||
- name: thumb_01_l
|
||||
index: 34
|
||||
depth: -1
|
||||
- name: thumb_02_l
|
||||
index: 35
|
||||
depth: -1
|
||||
- name: thumb_03_l
|
||||
index: 36
|
||||
depth: -1
|
||||
- name: lowerarm_twist_01_l
|
||||
index: 37
|
||||
depth: -1
|
||||
- name: lowerarm_twist_02_l
|
||||
index: 38
|
||||
depth: -1
|
||||
- name: upperarm_twist_01_l
|
||||
index: 39
|
||||
depth: -1
|
||||
- name: upperarm_twist_02_l
|
||||
index: 40
|
||||
depth: -1
|
||||
- name: clavicle_r
|
||||
index: 41
|
||||
depth: -1
|
||||
- name: upperarm_r
|
||||
index: 42
|
||||
depth: -1
|
||||
- name: lowerarm_r
|
||||
index: 43
|
||||
depth: -1
|
||||
- name: hand_r
|
||||
index: 44
|
||||
depth: -1
|
||||
- name: index_metacarpal_r
|
||||
index: 45
|
||||
depth: -1
|
||||
- name: index_01_r
|
||||
index: 46
|
||||
depth: -1
|
||||
- name: index_02_r
|
||||
index: 47
|
||||
depth: -1
|
||||
- name: index_03_r
|
||||
index: 48
|
||||
depth: -1
|
||||
- name: middle_metacarpal_r
|
||||
index: 49
|
||||
depth: -1
|
||||
- name: middle_01_r
|
||||
index: 50
|
||||
depth: -1
|
||||
- name: middle_02_r
|
||||
index: 51
|
||||
depth: -1
|
||||
- name: middle_03_r
|
||||
index: 52
|
||||
depth: -1
|
||||
- name: pinky_metacarpal_r
|
||||
index: 53
|
||||
depth: -1
|
||||
- name: pinky_01_r
|
||||
index: 54
|
||||
depth: -1
|
||||
- name: pinky_02_r
|
||||
index: 55
|
||||
depth: -1
|
||||
- name: pinky_03_r
|
||||
index: 56
|
||||
depth: -1
|
||||
- name: ring_metacarpal_r
|
||||
index: 57
|
||||
depth: -1
|
||||
- name: ring_01_r
|
||||
index: 58
|
||||
depth: -1
|
||||
- name: ring_02_r
|
||||
index: 59
|
||||
depth: -1
|
||||
- name: ring_03_r
|
||||
index: 60
|
||||
depth: -1
|
||||
- name: thumb_01_r
|
||||
index: 61
|
||||
depth: -1
|
||||
- name: thumb_02_r
|
||||
index: 62
|
||||
depth: -1
|
||||
- name: thumb_03_r
|
||||
index: 63
|
||||
depth: -1
|
||||
- name: lowerarm_twist_01_r
|
||||
index: 64
|
||||
depth: -1
|
||||
- name: lowerarm_twist_02_r
|
||||
index: 65
|
||||
depth: -1
|
||||
- name: upperarm_twist_01_r
|
||||
index: 66
|
||||
depth: -1
|
||||
- name: upperarm_twist_02_r
|
||||
index: 67
|
||||
depth: -1
|
||||
- name: neck_01
|
||||
index: 68
|
||||
depth: -1
|
||||
- name: neck_01_wt
|
||||
index: 69
|
||||
depth: -1
|
||||
- name: neck_02
|
||||
index: 70
|
||||
depth: -1
|
||||
- name: head
|
||||
index: 71
|
||||
depth: -1
|
||||
- name: facial_root
|
||||
index: 72
|
||||
depth: -1
|
||||
- name: brow_center
|
||||
index: 73
|
||||
depth: -1
|
||||
- name: brow_inner_l
|
||||
index: 74
|
||||
depth: -1
|
||||
- name: brow_inner_r
|
||||
index: 75
|
||||
depth: -1
|
||||
- name: brow_outer_l
|
||||
index: 76
|
||||
depth: -1
|
||||
- name: brow_outer_r
|
||||
index: 77
|
||||
depth: -1
|
||||
- name: cheek_l
|
||||
index: 78
|
||||
depth: -1
|
||||
- name: cheek_r
|
||||
index: 79
|
||||
depth: -1
|
||||
- name: eye_l
|
||||
index: 80
|
||||
depth: -1
|
||||
- name: eye_l_inner
|
||||
index: 81
|
||||
depth: -1
|
||||
- name: eye_l_lower
|
||||
index: 82
|
||||
depth: -1
|
||||
- name: eye_l_outer
|
||||
index: 83
|
||||
depth: -1
|
||||
- name: eye_l_upper
|
||||
index: 84
|
||||
depth: -1
|
||||
- name: eye_r
|
||||
index: 85
|
||||
depth: -1
|
||||
- name: eye_r_inner
|
||||
index: 86
|
||||
depth: -1
|
||||
- name: eye_r_lower
|
||||
index: 87
|
||||
depth: -1
|
||||
- name: eye_r_outer
|
||||
index: 88
|
||||
depth: -1
|
||||
- name: eye_r_upper
|
||||
index: 89
|
||||
depth: -1
|
||||
- name: eyelid_lower_l
|
||||
index: 90
|
||||
depth: -1
|
||||
- name: eyelid_lower_r
|
||||
index: 91
|
||||
depth: -1
|
||||
- name: eyelid_upper_l
|
||||
index: 92
|
||||
depth: -1
|
||||
- name: eyelid_upper_r
|
||||
index: 93
|
||||
depth: -1
|
||||
- name: jaw
|
||||
index: 94
|
||||
depth: -1
|
||||
- name: jaw_back
|
||||
index: 95
|
||||
depth: -1
|
||||
- name: tongue_01
|
||||
index: 96
|
||||
depth: -1
|
||||
- name: lip_lower_l
|
||||
index: 97
|
||||
depth: -1
|
||||
- name: lip_lower_outside_l
|
||||
index: 98
|
||||
depth: -1
|
||||
- name: lip_lower_r
|
||||
index: 99
|
||||
depth: -1
|
||||
- name: lip_lower_outside_r
|
||||
index: 100
|
||||
depth: -1
|
||||
- name: lip_upper_l
|
||||
index: 101
|
||||
depth: -1
|
||||
- name: lip_upper_outside_l
|
||||
index: 102
|
||||
depth: -1
|
||||
- name: lip_upper_r
|
||||
index: 103
|
||||
depth: -1
|
||||
- name: lip_upper_outside_r
|
||||
index: 104
|
||||
depth: -1
|
||||
- name: mouth_l
|
||||
index: 105
|
||||
depth: -1
|
||||
- name: mouth_r
|
||||
index: 106
|
||||
depth: -1
|
||||
- name: nose_l
|
||||
index: 107
|
||||
depth: -1
|
||||
- name: nose_r
|
||||
index: 108
|
||||
depth: -1
|
||||
- name: neck_02_wt
|
||||
index: 109
|
||||
depth: -1
|
||||
- name: spine_05_wt
|
||||
index: 110
|
||||
depth: -1
|
||||
- name: breast_l
|
||||
index: 111
|
||||
depth: -1
|
||||
- name: breast_r
|
||||
index: 112
|
||||
depth: -1
|
||||
- name: thigh_l
|
||||
index: 113
|
||||
depth: -1
|
||||
- name: calf_l
|
||||
index: 114
|
||||
depth: -1
|
||||
- name: calf_twist_01_l
|
||||
index: 115
|
||||
depth: -1
|
||||
- name: calf_twist_02_l
|
||||
index: 116
|
||||
depth: -1
|
||||
- name: foot_l
|
||||
index: 117
|
||||
depth: -1
|
||||
- name: ball_l
|
||||
index: 118
|
||||
depth: -1
|
||||
- name: thigh_twist_01_l
|
||||
index: 119
|
||||
depth: -1
|
||||
- name: thigh_twist_02_l
|
||||
index: 120
|
||||
depth: -1
|
||||
- name: thigh_r
|
||||
index: 121
|
||||
depth: -1
|
||||
- name: calf_r
|
||||
index: 122
|
||||
depth: -1
|
||||
- name: calf_twist_01_r
|
||||
index: 123
|
||||
depth: -1
|
||||
- name: calf_twist_02_r
|
||||
index: 124
|
||||
depth: -1
|
||||
- name: foot_r
|
||||
index: 125
|
||||
depth: -1
|
||||
- name: ball_r
|
||||
index: 126
|
||||
depth: -1
|
||||
- name: thigh_twist_01_r
|
||||
index: 127
|
||||
depth: -1
|
||||
- name: thigh_twist_02_r
|
||||
index: 128
|
||||
depth: -1
|
||||
rigElementChains:
|
||||
- chainName: root
|
||||
elementChain:
|
||||
- name: root
|
||||
index: 0
|
||||
depth: -1
|
||||
- name: pelvis
|
||||
index: 1
|
||||
depth: -1
|
||||
- chainName: pelvis_wt
|
||||
elementChain:
|
||||
- name: pelvis_wt
|
||||
index: 2
|
||||
depth: -1
|
||||
- chainName: butt_l
|
||||
elementChain:
|
||||
- name: butt_l
|
||||
index: 3
|
||||
depth: -1
|
||||
- chainName: butt_r
|
||||
elementChain:
|
||||
- name: butt_r
|
||||
index: 4
|
||||
depth: -1
|
||||
- chainName: spine_01
|
||||
elementChain:
|
||||
- name: spine_01
|
||||
index: 5
|
||||
depth: -1
|
||||
- chainName: spine_01_wt
|
||||
elementChain:
|
||||
- name: spine_01_wt
|
||||
index: 6
|
||||
depth: -1
|
||||
- chainName: spine_02
|
||||
elementChain:
|
||||
- name: spine_02
|
||||
index: 7
|
||||
depth: -1
|
||||
- chainName: spine_02_wt
|
||||
elementChain:
|
||||
- name: spine_02_wt
|
||||
index: 8
|
||||
depth: -1
|
||||
- chainName: spine_03
|
||||
elementChain:
|
||||
- name: spine_03
|
||||
index: 9
|
||||
depth: -1
|
||||
- chainName: spine_03_wt
|
||||
elementChain:
|
||||
- name: spine_03_wt
|
||||
index: 10
|
||||
depth: -1
|
||||
- chainName: spine_04
|
||||
elementChain:
|
||||
- name: spine_04
|
||||
index: 11
|
||||
depth: -1
|
||||
- chainName: spine_04_wt
|
||||
elementChain:
|
||||
- name: spine_04_wt
|
||||
index: 12
|
||||
depth: -1
|
||||
- chainName: spine_05
|
||||
elementChain:
|
||||
- name: spine_05
|
||||
index: 13
|
||||
depth: -1
|
||||
- chainName: clavicle_l
|
||||
elementChain:
|
||||
- name: clavicle_l
|
||||
index: 14
|
||||
depth: -1
|
||||
- name: upperarm_l
|
||||
index: 15
|
||||
depth: -1
|
||||
- name: lowerarm_l
|
||||
index: 16
|
||||
depth: -1
|
||||
- name: hand_l
|
||||
index: 17
|
||||
depth: -1
|
||||
- chainName: index_metacarpal_l
|
||||
elementChain:
|
||||
- name: index_metacarpal_l
|
||||
index: 18
|
||||
depth: -1
|
||||
- name: index_01_l
|
||||
index: 19
|
||||
depth: -1
|
||||
- name: index_02_l
|
||||
index: 20
|
||||
depth: -1
|
||||
- name: index_03_l
|
||||
index: 21
|
||||
depth: -1
|
||||
- chainName: middle_metacarpal_l
|
||||
elementChain:
|
||||
- name: middle_metacarpal_l
|
||||
index: 22
|
||||
depth: -1
|
||||
- name: middle_01_l
|
||||
index: 23
|
||||
depth: -1
|
||||
- name: middle_02_l
|
||||
index: 24
|
||||
depth: -1
|
||||
- name: middle_03_l
|
||||
index: 25
|
||||
depth: -1
|
||||
- chainName: pinky_metacarpal_l
|
||||
elementChain:
|
||||
- name: pinky_metacarpal_l
|
||||
index: 26
|
||||
depth: -1
|
||||
- name: pinky_01_l
|
||||
index: 27
|
||||
depth: -1
|
||||
- name: pinky_02_l
|
||||
index: 28
|
||||
depth: -1
|
||||
- name: pinky_03_l
|
||||
index: 29
|
||||
depth: -1
|
||||
- chainName: ring_metacarpal_l
|
||||
elementChain:
|
||||
- name: ring_metacarpal_l
|
||||
index: 30
|
||||
depth: -1
|
||||
- name: ring_01_l
|
||||
index: 31
|
||||
depth: -1
|
||||
- name: ring_02_l
|
||||
index: 32
|
||||
depth: -1
|
||||
- name: ring_03_l
|
||||
index: 33
|
||||
depth: -1
|
||||
- chainName: thumb_01_l
|
||||
elementChain:
|
||||
- name: thumb_01_l
|
||||
index: 34
|
||||
depth: -1
|
||||
- name: thumb_02_l
|
||||
index: 35
|
||||
depth: -1
|
||||
- name: thumb_03_l
|
||||
index: 36
|
||||
depth: -1
|
||||
- chainName: clavicle_r
|
||||
elementChain:
|
||||
- name: clavicle_r
|
||||
index: 41
|
||||
depth: -1
|
||||
- name: upperarm_r
|
||||
index: 42
|
||||
depth: -1
|
||||
- name: lowerarm_r
|
||||
index: 43
|
||||
depth: -1
|
||||
- name: hand_r
|
||||
index: 44
|
||||
depth: -1
|
||||
- chainName: index_metacarpal_r
|
||||
elementChain:
|
||||
- name: index_metacarpal_r
|
||||
index: 45
|
||||
depth: -1
|
||||
- name: index_01_r
|
||||
index: 46
|
||||
depth: -1
|
||||
- name: index_02_r
|
||||
index: 47
|
||||
depth: -1
|
||||
- name: index_03_r
|
||||
index: 48
|
||||
depth: -1
|
||||
- chainName: middle_metacarpal_r
|
||||
elementChain:
|
||||
- name: middle_metacarpal_r
|
||||
index: 49
|
||||
depth: -1
|
||||
- name: middle_01_r
|
||||
index: 50
|
||||
depth: -1
|
||||
- name: middle_02_r
|
||||
index: 51
|
||||
depth: -1
|
||||
- name: middle_03_r
|
||||
index: 52
|
||||
depth: -1
|
||||
- chainName: pinky_metacarpal_r
|
||||
elementChain:
|
||||
- name: pinky_metacarpal_r
|
||||
index: 53
|
||||
depth: -1
|
||||
- name: pinky_01_r
|
||||
index: 54
|
||||
depth: -1
|
||||
- name: pinky_02_r
|
||||
index: 55
|
||||
depth: -1
|
||||
- name: pinky_03_r
|
||||
index: 56
|
||||
depth: -1
|
||||
- chainName: ring_metacarpal_r
|
||||
elementChain:
|
||||
- name: ring_metacarpal_r
|
||||
index: 57
|
||||
depth: -1
|
||||
- name: ring_01_r
|
||||
index: 58
|
||||
depth: -1
|
||||
- name: ring_02_r
|
||||
index: 59
|
||||
depth: -1
|
||||
- name: ring_03_r
|
||||
index: 60
|
||||
depth: -1
|
||||
- chainName: thumb_01_r
|
||||
elementChain:
|
||||
- name: thumb_01_r
|
||||
index: 61
|
||||
depth: -1
|
||||
- name: thumb_02_r
|
||||
index: 62
|
||||
depth: -1
|
||||
- name: thumb_03_r
|
||||
index: 63
|
||||
depth: -1
|
||||
- chainName: neck_01
|
||||
elementChain:
|
||||
- name: neck_01
|
||||
index: 68
|
||||
depth: -1
|
||||
- chainName: neck_01_wt
|
||||
elementChain:
|
||||
- name: neck_01_wt
|
||||
index: 69
|
||||
depth: -1
|
||||
- chainName: neck_02
|
||||
elementChain:
|
||||
- name: neck_02
|
||||
index: 70
|
||||
depth: -1
|
||||
- chainName: head
|
||||
elementChain:
|
||||
- name: head
|
||||
index: 71
|
||||
depth: -1
|
||||
- name: facial_root
|
||||
index: 72
|
||||
depth: -1
|
||||
- chainName: brow_center
|
||||
elementChain:
|
||||
- name: brow_center
|
||||
index: 73
|
||||
depth: -1
|
||||
- chainName: brow_inner_l
|
||||
elementChain:
|
||||
- name: brow_inner_l
|
||||
index: 74
|
||||
depth: -1
|
||||
- chainName: brow_inner_r
|
||||
elementChain:
|
||||
- name: brow_inner_r
|
||||
index: 75
|
||||
depth: -1
|
||||
- chainName: brow_outer_l
|
||||
elementChain:
|
||||
- name: brow_outer_l
|
||||
index: 76
|
||||
depth: -1
|
||||
- chainName: brow_outer_r
|
||||
elementChain:
|
||||
- name: brow_outer_r
|
||||
index: 77
|
||||
depth: -1
|
||||
- chainName: cheek_l
|
||||
elementChain:
|
||||
- name: cheek_l
|
||||
index: 78
|
||||
depth: -1
|
||||
- chainName: cheek_r
|
||||
elementChain:
|
||||
- name: cheek_r
|
||||
index: 79
|
||||
depth: -1
|
||||
- chainName: eye_l
|
||||
elementChain:
|
||||
- name: eye_l
|
||||
index: 80
|
||||
depth: -1
|
||||
- chainName: eye_l_inner
|
||||
elementChain:
|
||||
- name: eye_l_inner
|
||||
index: 81
|
||||
depth: -1
|
||||
- chainName: eye_l_lower
|
||||
elementChain:
|
||||
- name: eye_l_lower
|
||||
index: 82
|
||||
depth: -1
|
||||
- chainName: eye_l_outer
|
||||
elementChain:
|
||||
- name: eye_l_outer
|
||||
index: 83
|
||||
depth: -1
|
||||
- chainName: eye_l_upper
|
||||
elementChain:
|
||||
- name: eye_l_upper
|
||||
index: 84
|
||||
depth: -1
|
||||
- chainName: eye_r
|
||||
elementChain:
|
||||
- name: eye_r
|
||||
index: 85
|
||||
depth: -1
|
||||
- chainName: eye_r_inner
|
||||
elementChain:
|
||||
- name: eye_r_inner
|
||||
index: 86
|
||||
depth: -1
|
||||
- chainName: eye_r_lower
|
||||
elementChain:
|
||||
- name: eye_r_lower
|
||||
index: 87
|
||||
depth: -1
|
||||
- chainName: eye_r_outer
|
||||
elementChain:
|
||||
- name: eye_r_outer
|
||||
index: 88
|
||||
depth: -1
|
||||
- chainName: eye_r_upper
|
||||
elementChain:
|
||||
- name: eye_r_upper
|
||||
index: 89
|
||||
depth: -1
|
||||
- chainName: eyelid_lower_l
|
||||
elementChain:
|
||||
- name: eyelid_lower_l
|
||||
index: 90
|
||||
depth: -1
|
||||
- chainName: eyelid_lower_r
|
||||
elementChain:
|
||||
- name: eyelid_lower_r
|
||||
index: 91
|
||||
depth: -1
|
||||
- chainName: eyelid_upper_l
|
||||
elementChain:
|
||||
- name: eyelid_upper_l
|
||||
index: 92
|
||||
depth: -1
|
||||
- chainName: eyelid_upper_r
|
||||
elementChain:
|
||||
- name: eyelid_upper_r
|
||||
index: 93
|
||||
depth: -1
|
||||
- chainName: jaw
|
||||
elementChain:
|
||||
- name: jaw
|
||||
index: 94
|
||||
depth: -1
|
||||
- chainName: jaw_back
|
||||
elementChain:
|
||||
- name: jaw_back
|
||||
index: 95
|
||||
depth: -1
|
||||
- chainName: tongue_01
|
||||
elementChain:
|
||||
- name: tongue_01
|
||||
index: 96
|
||||
depth: -1
|
||||
- chainName: lip_lower_l
|
||||
elementChain:
|
||||
- name: lip_lower_l
|
||||
index: 97
|
||||
depth: -1
|
||||
- name: lip_lower_outside_l
|
||||
index: 98
|
||||
depth: -1
|
||||
- chainName: lip_lower_r
|
||||
elementChain:
|
||||
- name: lip_lower_r
|
||||
index: 99
|
||||
depth: -1
|
||||
- name: lip_lower_outside_r
|
||||
index: 100
|
||||
depth: -1
|
||||
- chainName: lip_upper_l
|
||||
elementChain:
|
||||
- name: lip_upper_l
|
||||
index: 101
|
||||
depth: -1
|
||||
- name: lip_upper_outside_l
|
||||
index: 102
|
||||
depth: -1
|
||||
- chainName: lip_upper_r
|
||||
elementChain:
|
||||
- name: lip_upper_r
|
||||
index: 103
|
||||
depth: -1
|
||||
- name: lip_upper_outside_r
|
||||
index: 104
|
||||
depth: -1
|
||||
- chainName: mouth_l
|
||||
elementChain:
|
||||
- name: mouth_l
|
||||
index: 105
|
||||
depth: -1
|
||||
- chainName: mouth_r
|
||||
elementChain:
|
||||
- name: mouth_r
|
||||
index: 106
|
||||
depth: -1
|
||||
- chainName: nose_l
|
||||
elementChain:
|
||||
- name: nose_l
|
||||
index: 107
|
||||
depth: -1
|
||||
- chainName: nose_r
|
||||
elementChain:
|
||||
- name: nose_r
|
||||
index: 108
|
||||
depth: -1
|
||||
- chainName: neck_02_wt
|
||||
elementChain:
|
||||
- name: neck_02_wt
|
||||
index: 109
|
||||
depth: -1
|
||||
- chainName: spine_05_wt
|
||||
elementChain:
|
||||
- name: spine_05_wt
|
||||
index: 110
|
||||
depth: -1
|
||||
- chainName: breast_l
|
||||
elementChain:
|
||||
- name: breast_l
|
||||
index: 111
|
||||
depth: -1
|
||||
- chainName: breast_r
|
||||
elementChain:
|
||||
- name: breast_r
|
||||
index: 112
|
||||
depth: -1
|
||||
- chainName: thigh_l
|
||||
elementChain:
|
||||
- name: thigh_l
|
||||
index: 113
|
||||
depth: -1
|
||||
- name: calf_l
|
||||
index: 114
|
||||
depth: -1
|
||||
- name: foot_l
|
||||
index: 117
|
||||
depth: -1
|
||||
- name: ball_l
|
||||
index: 118
|
||||
depth: -1
|
||||
- chainName: thigh_r
|
||||
elementChain:
|
||||
- name: thigh_r
|
||||
index: 121
|
||||
depth: -1
|
||||
- name: calf_r
|
||||
index: 122
|
||||
depth: -1
|
||||
- name: foot_r
|
||||
index: 125
|
||||
depth: -1
|
||||
- name: ball_r
|
||||
index: 126
|
||||
depth: -1
|
||||
inputConfig: {fileID: 0}
|
||||
rigCurves: []
|
||||
rigDepths: 00000000010000000200000003000000030000000200000003000000030000000400000004000000050000000500000006000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000a0000000a00000009000000090000000700000008000000090000000a0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000e0000000b0000000c0000000d0000000a0000000a0000000900000009000000070000000800000008000000090000000a0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000b0000000c0000000c0000000b0000000c0000000b0000000c0000000b0000000c0000000b0000000c0000000b0000000b0000000b0000000b0000000900000007000000080000000800000002000000030000000400000004000000040000000500000003000000030000000200000003000000040000000400000004000000050000000300000003000000
|
||||
8
Assets/KINEMATION/MagicBlend/Rig_Human_Male.asset.meta
Normal file
8
Assets/KINEMATION/MagicBlend/Rig_Human_Male.asset.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14f74f4e0df7b30439cf0f73a77ef074
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/KINEMATION/MagicBlend/Runtime.meta
Normal file
8
Assets/KINEMATION/MagicBlend/Runtime.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 623069bce9ef18e4aa3b67ccb5aa566b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendAsset.cs
Normal file
56
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendAsset.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
// Designed by KINEMATION, 2025.
|
||||
|
||||
using KINEMATION.KAnimationCore.Runtime.Attributes;
|
||||
using KINEMATION.KAnimationCore.Runtime.Rig;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.MagicBlend.Runtime
|
||||
{
|
||||
public enum MagicBlendOutType
|
||||
{
|
||||
DoNotBlendOut,
|
||||
AutoBlendOut,
|
||||
AutoBlendOutToPreviousAsset
|
||||
}
|
||||
|
||||
public class MagicBlendAsset : ScriptableObject, IRigProvider
|
||||
{
|
||||
[Header("Rig")]
|
||||
public KRig rigAsset;
|
||||
|
||||
[Header("Blending")]
|
||||
[Min(0f)] public float blendTime = 0.15f;
|
||||
public AnimationCurve blendCurve = AnimationCurve.EaseInOut(0f, 0f, 1f, 1f);
|
||||
|
||||
[Header("Poses")]
|
||||
public AnimationClip basePose;
|
||||
public AnimationClip overlayPose;
|
||||
public List<OverrideOverlay> overrideOverlays = new List<OverrideOverlay>();
|
||||
[Min(0f)] public float overlaySpeed = 1f;
|
||||
[Tooltip("If Overlay is static or not.")]
|
||||
public bool isAnimation = false;
|
||||
public MagicBlendOutType blendOutType = MagicBlendOutType.DoNotBlendOut;
|
||||
|
||||
[Unfold] public List<LayeredBlend> layeredBlends = new List<LayeredBlend>();
|
||||
[Range(0f, 1f)] public float globalWeight = 1f;
|
||||
|
||||
public KRig GetRigAsset()
|
||||
{
|
||||
return rigAsset;
|
||||
}
|
||||
|
||||
public bool HasOverrides()
|
||||
{
|
||||
if (overrideOverlays.Count == 0) return false;
|
||||
foreach (var overlay in overrideOverlays) if (overlay.overlay == null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public KRigElement[] GetHierarchy()
|
||||
{
|
||||
return rigAsset == null ? null : rigAsset.GetHierarchy();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendAsset.cs.meta
Normal file
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendAsset.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cea8c2a1237b4b5b8bbfd16a4f12cc26
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: a497183ade831dc4aa44bf44b5ce27b8, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
192
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendJobs.cs
Normal file
192
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendJobs.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
// Designed by KINEMATION, 2025.
|
||||
|
||||
using KINEMATION.KAnimationCore.Runtime.Core;
|
||||
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace KINEMATION.MagicBlend.Runtime
|
||||
{
|
||||
// Processes base locomotion pose.
|
||||
public struct PoseJob : IAnimationJob
|
||||
{
|
||||
[ReadOnly] public bool alwaysAnimate;
|
||||
[ReadOnly] public bool readPose;
|
||||
[ReadOnly] public TransformSceneHandle root;
|
||||
public NativeArray<BlendStreamAtom> atoms;
|
||||
|
||||
public void ProcessAnimation(AnimationStream stream)
|
||||
{
|
||||
if (!alwaysAnimate && !readPose)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KTransform rootTransform = new KTransform()
|
||||
{
|
||||
rotation = root.GetRotation(stream),
|
||||
position = root.GetPosition(stream)
|
||||
};
|
||||
|
||||
int num = atoms.Length;
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
var atom = atoms[i];
|
||||
KTransform atomTransform = new KTransform()
|
||||
{
|
||||
position = atom.handle.GetPosition(stream),
|
||||
rotation = atom.handle.GetRotation(stream)
|
||||
};
|
||||
|
||||
atomTransform = rootTransform.GetRelativeTransform(atomTransform, false);
|
||||
atom.activePose.basePose = atomTransform;
|
||||
atom.activePose.basePose.position = atom.handle.GetLocalPosition(stream);
|
||||
atoms[i] = atom;
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessRootMotion(AnimationStream stream)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// Processes active stream pose.
|
||||
public struct OverlayJob : IAnimationJob
|
||||
{
|
||||
[ReadOnly] public bool alwaysAnimate;
|
||||
[ReadOnly] public bool cachePose;
|
||||
[ReadOnly] public TransformSceneHandle root;
|
||||
public NativeArray<BlendStreamAtom> atoms;
|
||||
|
||||
public void ProcessAnimation(AnimationStream stream)
|
||||
{
|
||||
if (!alwaysAnimate && !cachePose)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
KTransform rootTransform = new KTransform()
|
||||
{
|
||||
rotation = root.GetRotation(stream),
|
||||
position = root.GetPosition(stream)
|
||||
};
|
||||
|
||||
int num = atoms.Length;
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
var atom = atoms[i];
|
||||
|
||||
KTransform atomTransform = new KTransform()
|
||||
{
|
||||
rotation = atom.handle.GetRotation(stream),
|
||||
position = atom.handle.GetPosition(stream)
|
||||
};
|
||||
|
||||
atomTransform = rootTransform.GetRelativeTransform(atomTransform, false);
|
||||
|
||||
atom.activePose.overlayPose = atomTransform;
|
||||
atom.activePose.overlayPose.position = atom.handle.GetLocalPosition(stream);
|
||||
atom.activePose.localOverlayRotation = atom.handle.GetLocalRotation(stream);
|
||||
|
||||
atoms[i] = atom;
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessRootMotion(AnimationStream stream)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// Processes final layering.
|
||||
public struct LayeringJob : IAnimationJob
|
||||
{
|
||||
[ReadOnly] public float blendWeight;
|
||||
[ReadOnly] public bool cachePose;
|
||||
[ReadOnly] public TransformSceneHandle root;
|
||||
public NativeArray<BlendStreamAtom> atoms;
|
||||
|
||||
public void ProcessAnimation(AnimationStream stream)
|
||||
{
|
||||
KTransform rootTransform = new KTransform()
|
||||
{
|
||||
rotation = root.GetRotation(stream),
|
||||
position = root.GetPosition(stream)
|
||||
};
|
||||
|
||||
int num = atoms.Length;
|
||||
|
||||
// Refresh the current pose.
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
var atom = atoms[i];
|
||||
|
||||
KTransform atomTransform = new KTransform()
|
||||
{
|
||||
rotation = atom.handle.GetRotation(stream),
|
||||
position = atom.handle.GetPosition(stream),
|
||||
scale = Vector3.one
|
||||
};
|
||||
|
||||
atom.meshStreamPose = rootTransform.GetRelativeTransform(atomTransform, false);
|
||||
atom.meshStreamPose.position = atom.handle.GetLocalPosition(stream);
|
||||
|
||||
atom.activePose.additiveWeight = atom.additiveWeight;
|
||||
atom.activePose.baseWeight = atom.baseWeight;
|
||||
atom.activePose.localWeight = atom.localWeight;
|
||||
|
||||
atoms[i] = atom;
|
||||
}
|
||||
|
||||
// Apply mesh-space additive.
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
var atom = atoms[i];
|
||||
AtomPose blendedPose = atom.GetBlendedAtomPose(blendWeight);
|
||||
|
||||
if (cachePose)
|
||||
{
|
||||
atom.cachedPose = blendedPose;
|
||||
atoms[i] = atom;
|
||||
}
|
||||
|
||||
KTransform meshBasePose = blendedPose.basePose;
|
||||
KTransform meshOverlayPose = blendedPose.overlayPose;
|
||||
Quaternion localOverlayRotation = blendedPose.localOverlayRotation;
|
||||
|
||||
float additiveWeight = blendedPose.additiveWeight;
|
||||
float baseWeight = blendedPose.baseWeight;
|
||||
float localWeight = blendedPose.localWeight;
|
||||
|
||||
KTransform additive = new KTransform()
|
||||
{
|
||||
rotation = atom.meshStreamPose.rotation * Quaternion.Inverse(meshBasePose.rotation),
|
||||
position = atom.meshStreamPose.position - meshBasePose.position
|
||||
};
|
||||
|
||||
Quaternion rotation = additive.rotation * meshOverlayPose.rotation;
|
||||
|
||||
// Blend additive.
|
||||
rotation = Quaternion.Slerp(meshOverlayPose.rotation, rotation, additiveWeight);
|
||||
// Blend locomotion pose.
|
||||
rotation = Quaternion.Slerp(atom.meshStreamPose.rotation, rotation, baseWeight);
|
||||
// Convert to world space.
|
||||
rotation = rootTransform.rotation * rotation;
|
||||
|
||||
Vector3 position = meshOverlayPose.position + additive.position * additiveWeight;
|
||||
position = Vector3.Lerp(atom.meshStreamPose.position, position, baseWeight);
|
||||
|
||||
atom.handle.SetRotation(stream, rotation);
|
||||
rotation = Quaternion.Slerp(atom.handle.GetLocalRotation(stream), localOverlayRotation, localWeight);
|
||||
atom.handle.SetLocalRotation(stream, rotation);
|
||||
|
||||
position = Vector3.Lerp(position, meshOverlayPose.position, localWeight);
|
||||
atom.handle.SetLocalPosition(stream, position);
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessRootMotion(AnimationStream stream)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendJobs.cs.meta
Normal file
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendJobs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d94da5f3f9dd1584d95bc242f712151a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
151
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendLibrary.cs
Normal file
151
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendLibrary.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea61816638094afd9e1b1b9bf47e15cc
|
||||
timeCreated: 1722703296
|
||||
31
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendState.cs
Normal file
31
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendState.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// Designed by KINEMATION, 2025.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.MagicBlend.Runtime
|
||||
{
|
||||
public class MagicBlendState : StateMachineBehaviour
|
||||
{
|
||||
[SerializeField] private MagicBlendAsset magicBlendAsset;
|
||||
private bool _isInitialized;
|
||||
private MagicBlending _magicBlending;
|
||||
|
||||
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
_magicBlending = animator.gameObject.GetComponent<MagicBlending>();
|
||||
if (_magicBlending == null) return;
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
float blendTime = animator.GetAnimatorTransitionInfo(layerIndex).duration;
|
||||
_magicBlending.UpdateMagicBlendAsset(magicBlendAsset, new MagicBlendingData()
|
||||
{
|
||||
blendTime = blendTime,
|
||||
useLinear = true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendState.cs.meta
Normal file
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlendState.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 004dd898c28047b78e17ce086af4bdd2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 6fd4d99d3a1edc7408fe599214be6059, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
553
Assets/KINEMATION/MagicBlend/Runtime/MagicBlending.cs
Normal file
553
Assets/KINEMATION/MagicBlend/Runtime/MagicBlending.cs
Normal file
@@ -0,0 +1,553 @@
|
||||
// Designed by KINEMATION, 2025.
|
||||
|
||||
using System;
|
||||
using KINEMATION.KAnimationCore.Runtime.Rig;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Experimental.Animations;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
namespace KINEMATION.MagicBlend.Runtime
|
||||
{
|
||||
public struct MagicBlendingData
|
||||
{
|
||||
public MagicBlendAsset blendAsset;
|
||||
public AnimationClip overlayPose;
|
||||
public float overlaySpeed;
|
||||
public float blendTime;
|
||||
public bool useLinear;
|
||||
|
||||
public static MagicBlendingData Empty = new MagicBlendingData()
|
||||
{
|
||||
overlayPose = null,
|
||||
blendTime = -1f,
|
||||
useLinear = false,
|
||||
};
|
||||
}
|
||||
|
||||
[HelpURL("https://kinemation.gitbook.io/magic-blend-documentation/")]
|
||||
public class MagicBlending : MonoBehaviour
|
||||
{
|
||||
public PlayableGraph playableGraph;
|
||||
public MagicBlendAsset BlendAsset => blendAsset;
|
||||
|
||||
[Tooltip("This asset controls the blending weights.")]
|
||||
[SerializeField] private MagicBlendAsset blendAsset;
|
||||
|
||||
[Tooltip("Will update weights every frame.")]
|
||||
[SerializeField] private bool forceUpdateWeights = true;
|
||||
[Tooltip("Will process the Overlay pose. Keep it on most of the time.")]
|
||||
[SerializeField] private bool alwaysAnimatePoses = true;
|
||||
|
||||
private const ushort PlayableSortingPriority = 900;
|
||||
|
||||
private Animator _animator;
|
||||
private KRigComponent _rigComponent;
|
||||
|
||||
private AnimationLayerMixerPlayable _playableMixer;
|
||||
private NativeArray<BlendStreamAtom> _atoms;
|
||||
|
||||
private PoseJob _poseJob;
|
||||
private OverlayJob _overlayJob;
|
||||
private LayeringJob _layeringJob;
|
||||
|
||||
private AnimationScriptPlayable _poseJobPlayable;
|
||||
private AnimationScriptPlayable _overlayJobPlayable;
|
||||
private AnimationScriptPlayable _layeringJobPlayable;
|
||||
|
||||
private bool _isInitialized;
|
||||
private float _blendPlayback = 1f;
|
||||
private float _blendTime = 0f;
|
||||
private AnimationCurve _blendCurve;
|
||||
|
||||
private MagicBlendingData _blendData;
|
||||
private MagicBlendingData _desiredBlendData;
|
||||
private MagicBlendAsset _previousBlendAsset;
|
||||
private List<int> _blendedIndexes = new List<int>();
|
||||
|
||||
private Dictionary<string, int> _hierarchyMap;
|
||||
private RuntimeAnimatorController _cachedController;
|
||||
private AnimationPlayableOutput _magicBlendOutput;
|
||||
|
||||
private bool _forceBlendOut;
|
||||
private bool _wasAnimatorActive;
|
||||
|
||||
public void UpdateMagicBlendAsset(MagicBlendAsset newAsset)
|
||||
{
|
||||
UpdateMagicBlendAsset(newAsset, MagicBlendingData.Empty);
|
||||
}
|
||||
|
||||
public void UpdateMagicBlendAsset(MagicBlendAsset newAsset, MagicBlendingData blendingData,
|
||||
bool ignoreBlending = false)
|
||||
{
|
||||
if (newAsset == null || !_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_desiredBlendData = blendingData;
|
||||
_desiredBlendData.blendAsset = newAsset;
|
||||
|
||||
bool useBlending = blendingData.blendTime > 0f || newAsset.blendTime > 0f;
|
||||
if (useBlending && !ignoreBlending)
|
||||
{
|
||||
_layeringJob.cachePose = true;
|
||||
_layeringJobPlayable.SetJobData(_layeringJob);
|
||||
return;
|
||||
}
|
||||
|
||||
_layeringJob.blendWeight = 1f;
|
||||
_layeringJobPlayable.SetJobData(_layeringJob);
|
||||
|
||||
SetNewAsset();
|
||||
|
||||
if (!alwaysAnimatePoses)
|
||||
{
|
||||
_poseJob.readPose = true;
|
||||
_overlayJob.cachePose = true;
|
||||
|
||||
_poseJobPlayable.SetJobData(_poseJob);
|
||||
_overlayJobPlayable.SetJobData(_overlayJob);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a new blending asset.
|
||||
/// </summary>
|
||||
/// <param name="newAsset">Blending asset.</param>
|
||||
/// <param name="overlayOverride">Override clip.</param>>
|
||||
/// <param name="useBlending">Whether we need blending.</param>
|
||||
/// <param name="blendTime">Blending time in seconds.</param>
|
||||
/// <param name="useCurve">Whether we need curve or linear transition.</param>
|
||||
[Obsolete("Use the alternative override!")]
|
||||
public void UpdateMagicBlendAsset(MagicBlendAsset newAsset, bool useBlending = true,
|
||||
float blendTime = -1f, bool useCurve = true, AnimationClip overlayOverride = null)
|
||||
{
|
||||
UpdateMagicBlendAsset(newAsset, new MagicBlendingData()
|
||||
{
|
||||
blendTime = blendTime,
|
||||
useLinear = !useCurve,
|
||||
overlayPose = overlayOverride
|
||||
});
|
||||
}
|
||||
|
||||
public void StopMagicBlending()
|
||||
{
|
||||
_forceBlendOut = true;
|
||||
_blendPlayback = 0f;
|
||||
}
|
||||
|
||||
public void SetOverlayTime(float newTime)
|
||||
{
|
||||
var overlayPlayable = _overlayJobPlayable.GetInput(0);
|
||||
if (!overlayPlayable.IsValid()) return;
|
||||
overlayPlayable.SetTime(newTime);
|
||||
}
|
||||
|
||||
public float GetOverlayTime(bool isNormalized = true)
|
||||
{
|
||||
var overlayPlayable = _overlayJobPlayable.GetInput(0);
|
||||
if (!overlayPlayable.IsValid() || !blendAsset.isAnimation)
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
float length = (float) overlayPlayable.GetDuration();
|
||||
if (Mathf.Approximately(length, 0f))
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
float time = (float) overlayPlayable.GetTime();
|
||||
return isNormalized ? Mathf.Clamp01(time / length) : time;
|
||||
}
|
||||
|
||||
protected virtual void SetProcessJobs(bool isActive)
|
||||
{
|
||||
_poseJobPlayable.SetProcessInputs(isActive);
|
||||
_overlayJobPlayable.SetProcessInputs(isActive);
|
||||
}
|
||||
|
||||
protected virtual void SetNewAsset()
|
||||
{
|
||||
_blendData = _desiredBlendData;
|
||||
|
||||
if (blendAsset != null && blendAsset.blendOutType == MagicBlendOutType.DoNotBlendOut)
|
||||
{
|
||||
_previousBlendAsset = blendAsset;
|
||||
}
|
||||
|
||||
blendAsset = _blendData.blendAsset;
|
||||
if (_previousBlendAsset == null && blendAsset.blendOutType == MagicBlendOutType.DoNotBlendOut)
|
||||
{
|
||||
_previousBlendAsset = blendAsset;
|
||||
}
|
||||
|
||||
if (_blendData.overlayPose == null) _blendData.overlayPose = blendAsset.overlayPose;
|
||||
_blendCurve = _blendData.useLinear ? null : blendAsset.blendCurve;
|
||||
_blendTime = _blendData.blendTime > 0f ? _blendData.blendTime : blendAsset.blendTime;
|
||||
|
||||
MagicBlendLibrary.ConnectPose(_poseJobPlayable, playableGraph, blendAsset.basePose);
|
||||
|
||||
float overlaySpeed = Mathf.Approximately(_blendData.overlaySpeed, 0f)
|
||||
? blendAsset.overlaySpeed
|
||||
: _blendData.overlaySpeed;
|
||||
|
||||
float speed = blendAsset.isAnimation ? overlaySpeed : 0f;
|
||||
if (blendAsset.HasOverrides())
|
||||
{
|
||||
MagicBlendLibrary.ConnectOverlays(_overlayJobPlayable, playableGraph, _blendData.overlayPose,
|
||||
blendAsset.overrideOverlays, speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
MagicBlendLibrary.ConnectPose(_overlayJobPlayable, playableGraph, _blendData.overlayPose, speed);
|
||||
}
|
||||
|
||||
// Reset all weights.
|
||||
for (int i = 0; i < _hierarchyMap.Count; i++)
|
||||
{
|
||||
var atom = _atoms[i];
|
||||
atom.baseWeight = atom.additiveWeight = atom.localWeight = 0f;
|
||||
_atoms[i] = atom;
|
||||
}
|
||||
|
||||
// Add indexes which will be blended.
|
||||
_blendedIndexes.Clear();
|
||||
foreach (var blend in blendAsset.layeredBlends)
|
||||
{
|
||||
foreach (var element in blend.layer.elementChain)
|
||||
{
|
||||
_hierarchyMap.TryGetValue(element.name, out int index);
|
||||
_blendedIndexes.Add(index);
|
||||
}
|
||||
}
|
||||
|
||||
// Active the jobs processing.
|
||||
SetProcessJobs(true);
|
||||
_forceBlendOut = false;
|
||||
|
||||
// Update weights.
|
||||
UpdateBlendWeights();
|
||||
}
|
||||
|
||||
protected virtual void BuildMagicMixer()
|
||||
{
|
||||
if (!_playableMixer.IsValid())
|
||||
{
|
||||
_playableMixer = AnimationLayerMixerPlayable.Create(playableGraph, 3);
|
||||
InitializeJobs();
|
||||
_playableMixer.ConnectInput(0, _poseJobPlayable, 0, 1f);
|
||||
_playableMixer.ConnectInput(1, _overlayJobPlayable, 0, 1f);
|
||||
_playableMixer.ConnectInput(2, _layeringJobPlayable, 0, 1f);
|
||||
}
|
||||
|
||||
_magicBlendOutput.SetSourcePlayable(_playableMixer);
|
||||
_magicBlendOutput.SetSortingOrder(PlayableSortingPriority);
|
||||
|
||||
int num = playableGraph.GetOutputCount();
|
||||
int animatorPlayableIndex = 0;
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
var sourcePlayable = playableGraph.GetOutput(i).GetSourcePlayable();
|
||||
if (sourcePlayable.GetPlayableType() != typeof(AnimatorControllerPlayable))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
animatorPlayableIndex = i;
|
||||
}
|
||||
|
||||
var animatorOutput = playableGraph.GetOutput(animatorPlayableIndex);
|
||||
var animatorPlayable = animatorOutput.GetSourcePlayable();
|
||||
|
||||
if (_layeringJobPlayable.IsValid())
|
||||
{
|
||||
_layeringJobPlayable.DisconnectInput(0);
|
||||
}
|
||||
|
||||
_layeringJobPlayable.ConnectInput(0, animatorPlayable, 0, 1f);
|
||||
|
||||
if (blendAsset != null)
|
||||
{
|
||||
UpdateMagicBlendAsset(blendAsset, new MagicBlendingData()
|
||||
{
|
||||
blendTime = -1f,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void InitializeMagicBlending()
|
||||
{
|
||||
playableGraph = _animator.playableGraph;
|
||||
_atoms = MagicBlendLibrary.SetupBlendAtoms(_animator, _rigComponent);
|
||||
|
||||
_magicBlendOutput = AnimationPlayableOutput.Create(playableGraph, "MagicBlendOutput", _animator);
|
||||
_isInitialized = true;
|
||||
BuildMagicMixer();
|
||||
|
||||
playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);
|
||||
playableGraph.Play();
|
||||
}
|
||||
|
||||
private void InitializeJobs()
|
||||
{
|
||||
var rootSceneHandle = _animator.BindSceneTransform(_animator.transform);
|
||||
|
||||
_poseJob = new PoseJob()
|
||||
{
|
||||
atoms = _atoms,
|
||||
root = rootSceneHandle,
|
||||
alwaysAnimate = alwaysAnimatePoses,
|
||||
readPose = false
|
||||
};
|
||||
_poseJobPlayable = AnimationScriptPlayable.Create(playableGraph, _poseJob, 1);
|
||||
|
||||
_overlayJob = new OverlayJob()
|
||||
{
|
||||
atoms = _atoms,
|
||||
root = rootSceneHandle,
|
||||
alwaysAnimate = alwaysAnimatePoses,
|
||||
cachePose = false
|
||||
};
|
||||
_overlayJobPlayable = AnimationScriptPlayable.Create(playableGraph, _overlayJob, 1);
|
||||
|
||||
_layeringJob = new LayeringJob()
|
||||
{
|
||||
atoms = _atoms,
|
||||
root = rootSceneHandle,
|
||||
blendWeight = 1f,
|
||||
cachePose = false,
|
||||
};
|
||||
_layeringJobPlayable = AnimationScriptPlayable.Create(playableGraph, _layeringJob, 1);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if(_isInitialized) BuildMagicMixer();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
_cachedController = _animator.runtimeAnimatorController;
|
||||
_wasAnimatorActive = _animator.isActiveAndEnabled;
|
||||
|
||||
_rigComponent = GetComponentInChildren<KRigComponent>();
|
||||
_hierarchyMap = new Dictionary<string, int>();
|
||||
|
||||
var hierarchy = _rigComponent.GetRigTransforms();
|
||||
for (int i = 0; i < hierarchy.Length; i++)
|
||||
{
|
||||
_hierarchyMap.Add(hierarchy[i].name, i);
|
||||
}
|
||||
|
||||
InitializeMagicBlending();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
_cachedBlendAsset = blendAsset;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected virtual void UpdateBlendWeights(float globalWeight = 1f)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
foreach (var blend in blendAsset.layeredBlends)
|
||||
{
|
||||
foreach (var unused in blend.layer.elementChain)
|
||||
{
|
||||
int realIndex = _blendedIndexes[index];
|
||||
|
||||
var atom = _atoms[realIndex];
|
||||
atom.baseWeight = blend.baseWeight * blendAsset.globalWeight * globalWeight;
|
||||
atom.additiveWeight = blend.additiveWeight * blendAsset.globalWeight * globalWeight;
|
||||
atom.localWeight = blend.localWeight * blendAsset.globalWeight * globalWeight;
|
||||
_atoms[realIndex] = atom;
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
var overlayPlayable = _overlayJobPlayable.GetInput(0);
|
||||
int count = overlayPlayable.GetInputCount();
|
||||
if (count == 0) return;
|
||||
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
overlayPlayable.SetInputWeight(i, blendAsset.overrideOverlays[i - 1].weight);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (_blendData.blendAsset == null || blendAsset == null) return;
|
||||
|
||||
var activeAnimator = _animator.runtimeAnimatorController;
|
||||
|
||||
if (_cachedController != activeAnimator || _wasAnimatorActive != _animator.isActiveAndEnabled)
|
||||
{
|
||||
BuildMagicMixer();
|
||||
}
|
||||
|
||||
_cachedController = activeAnimator;
|
||||
_wasAnimatorActive = _animator.isActiveAndEnabled;
|
||||
|
||||
if (blendAsset.isAnimation)
|
||||
{
|
||||
int count = _overlayJobPlayable.GetInput(0).GetInputCount();
|
||||
|
||||
var overlayPlayable = count == 0 ? _overlayJobPlayable.GetInput(0)
|
||||
: _overlayJobPlayable.GetInput(0).GetInput(0);
|
||||
|
||||
if (overlayPlayable.GetTime() >= _blendData.overlayPose.length)
|
||||
{
|
||||
if (blendAsset.blendOutType > MagicBlendOutType.DoNotBlendOut)
|
||||
{
|
||||
if ((blendAsset.blendOutType == MagicBlendOutType.AutoBlendOut
|
||||
|| _previousBlendAsset == null))
|
||||
{
|
||||
if(!_forceBlendOut) StopMagicBlending();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateMagicBlendAsset(_previousBlendAsset);
|
||||
}
|
||||
}
|
||||
else if(_blendData.overlayPose.isLooping)
|
||||
{
|
||||
overlayPlayable.SetTime(0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1)
|
||||
{
|
||||
for (int i = 1; i < count; i++)
|
||||
{
|
||||
var overrideOverlay = _overlayJobPlayable.GetInput(0).GetInput(i);
|
||||
var overrideClip = blendAsset.overrideOverlays[i - 1].overlay;
|
||||
|
||||
if (!overrideClip.isLooping || overrideOverlay.GetTime() < overrideClip.length
|
||||
|| blendAsset.blendOutType > MagicBlendOutType.DoNotBlendOut)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
overrideOverlay.SetTime(0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float globalWeight = 1f;
|
||||
if (_forceBlendOut)
|
||||
{
|
||||
_blendPlayback = Mathf.Clamp(_blendPlayback + Time.deltaTime, 0f, _blendTime);
|
||||
float blendOutWeight = _blendPlayback / _blendTime;
|
||||
globalWeight = 1f - (_blendCurve?.Evaluate(blendOutWeight) ?? blendOutWeight);
|
||||
}
|
||||
|
||||
if (forceUpdateWeights || _forceBlendOut)
|
||||
{
|
||||
UpdateBlendWeights(globalWeight);
|
||||
}
|
||||
|
||||
if (Mathf.Approximately(globalWeight, 0f))
|
||||
{
|
||||
SetProcessJobs(false);
|
||||
blendAsset = null;
|
||||
#if UNITY_EDITOR
|
||||
_cachedBlendAsset = null;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_forceBlendOut || Mathf.Approximately(_blendPlayback, _blendTime)) return;
|
||||
|
||||
_blendPlayback = Mathf.Clamp(_blendPlayback + Time.deltaTime, 0f, _blendTime);
|
||||
float normalizedWeight = _blendTime > 0f ? _blendPlayback / _blendTime : 1f;
|
||||
|
||||
_layeringJob.blendWeight = _blendCurve?.Evaluate(normalizedWeight) ?? normalizedWeight;
|
||||
_layeringJobPlayable.SetJobData(_layeringJob);
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (!alwaysAnimatePoses && _poseJob.readPose)
|
||||
{
|
||||
_poseJob.readPose = false;
|
||||
_overlayJob.cachePose = false;
|
||||
|
||||
_poseJobPlayable.SetJobData(_poseJob);
|
||||
_overlayJobPlayable.SetJobData(_overlayJob);
|
||||
}
|
||||
|
||||
if (_layeringJob.cachePose)
|
||||
{
|
||||
SetNewAsset();
|
||||
|
||||
_blendPlayback = 0f;
|
||||
|
||||
_layeringJob.cachePose = false;
|
||||
_layeringJob.blendWeight = 0f;
|
||||
_layeringJobPlayable.SetJobData(_layeringJob);
|
||||
|
||||
if (!alwaysAnimatePoses)
|
||||
{
|
||||
_poseJob.readPose = true;
|
||||
_overlayJob.cachePose = true;
|
||||
|
||||
_poseJobPlayable.SetJobData(_poseJob);
|
||||
_overlayJobPlayable.SetJobData(_overlayJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
if (playableGraph.IsValid() && playableGraph.IsPlaying())
|
||||
{
|
||||
playableGraph.Stop();
|
||||
}
|
||||
|
||||
if (_atoms.IsCreated)
|
||||
{
|
||||
_atoms.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMagicBlendAsset(MagicBlendAsset newAsset)
|
||||
{
|
||||
blendAsset = newAsset;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private MagicBlendAsset _cachedBlendAsset;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (!_isInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_poseJob.alwaysAnimate = alwaysAnimatePoses;
|
||||
_overlayJob.alwaysAnimate = alwaysAnimatePoses;
|
||||
|
||||
_poseJobPlayable.SetJobData(_poseJob);
|
||||
_overlayJobPlayable.SetJobData(_overlayJob);
|
||||
|
||||
if (_cachedBlendAsset == blendAsset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateMagicBlendAsset(blendAsset);
|
||||
(_cachedBlendAsset, blendAsset) = (blendAsset, _cachedBlendAsset);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlending.cs.meta
Normal file
11
Assets/KINEMATION/MagicBlend/Runtime/MagicBlending.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdf51b00bdc44c699c58a3ed985775d4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 50
|
||||
icon: {fileID: 2800000, guid: 6fd4d99d3a1edc7408fe599214be6059, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user