feat: improved merge armature implementation (#174)

This branch rewrites the merge armature logic to be both simpler and more reliable. In particular, all components in the merged armature will always be moved into the target armature, eliminating the need for complex and unreliable constraint adjustments. I also rewrite the path remapping logic to be more reliable by tracking actual GameObjects, rather than string paths.

This change fixes a number of constraint-heavy outfits, including:

* https://cloudz.booth.pm/items/3751948
* https://capettiya.booth.pm/items/4424678

It also fixes issues with some more advanced use cases, such as animating transforms on bones that are newly added using merge armature.
This commit is contained in:
bd_ 2023-01-05 21:10:22 +09:00 committed by GitHub
parent aba8d45bd8
commit 1635b988a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 3969 additions and 291 deletions

12
.gitignore vendored
View File

@ -70,4 +70,14 @@ crashlytics-build.properties
!/Assets/bd_/ModularAvatar.meta !/Assets/bd_/ModularAvatar.meta
!/Assets/bd_.meta !/Assets/bd_.meta
![Mm]odular[Aa]vatar.meta !/Assets/_ModularAvatar.meta
!/Assets/_ModularAvatar/
!/Assets/_ModularAvatar/*
!/Assets/_ModularAvatar/**/*
!/Assets/bd_/ModularAvatar/DevAssets/
!/Assets/bd_/ModularAvatar/DevAssets/**/*
![Mm]odular[Aa]vatar.meta
Thry

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c5a2bf598635bd4458c4e1ebb1ab1d79
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9d2706d17a5b8ff44b56c779d2bbc439
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,108 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using VRC.SDK3.Avatars.Components;
namespace modular_avatar_tests
{
public class PathMappingTest
{
private List<GameObject> objects;
[SetUp]
public void Setup()
{
objects = new List<GameObject>();
}
[TearDown]
public void Teardown()
{
foreach (var obj in objects)
{
Object.DestroyImmediate(obj);
}
}
GameObject CreateRoot(string name)
{
var go = new GameObject(name);
objects.Add(go);
// Needed for avatar path finding functions to work properly
go.AddComponent(typeof(VRCAvatarDescriptor));
return go;
}
GameObject CreateChild(GameObject parent, string name)
{
var go = new GameObject(name);
go.transform.parent = parent.transform;
objects.Add(go);
return go;
}
[Test]
public void TracksSimpleRenames()
{
var root = CreateRoot("root");
var a = CreateChild(root, "a");
PathMappings.Init(root);
Assert.AreEqual("a", PathMappings.MapPath("a"));
a.name = "b";
PathMappings.ClearCache();
Assert.AreEqual("b", PathMappings.MapPath("a"));
}
[Test]
public void TracksObjectMoves()
{
var root = CreateRoot("root");
var a = CreateChild(root, "a");
var b = CreateChild(root, "b");
PathMappings.Init(root);
Assert.AreEqual("a", PathMappings.MapPath("a"));
a.transform.parent = b.transform;
PathMappings.ClearCache();
Assert.AreEqual("b/a", PathMappings.MapPath("a"));
}
[Test]
public void TracksCollapses()
{
var root = CreateRoot("root");
var a = CreateChild(root, "a");
var b = CreateChild(a, "b");
var c = CreateChild(b, "c");
PathMappings.Init(root);
PathMappings.MarkRemoved(b);
c.transform.parent = a.transform;
Object.DestroyImmediate(b);
Assert.AreEqual("a/c", PathMappings.MapPath("a/b/c"));
}
[Test]
public void TransformLookthrough()
{
var root = CreateRoot("root");
var a = CreateChild(root, "a");
var b = CreateChild(a, "b");
var c = CreateChild(b, "c");
var d = CreateChild(c, "d");
PathMappings.Init(root);
PathMappings.MarkTransformLookthrough(b);
PathMappings.MarkTransformLookthrough(c);
Assert.AreEqual("a/b/c", PathMappings.MapPath("a/b/c"));
Assert.AreEqual("a", PathMappings.MapPath("a/b/c", true));
Assert.AreEqual("a/b/c/d", PathMappings.MapPath("a/b/c/d", true));
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc087947fd98b2b43a853f93161cfe13
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
{
"name": "Tests",
"references": [
"GUID:27619889b8ba8c24980f49ee34dbb44a",
"GUID:0acc523941302664db1f4e527237feb3",
"GUID:fc900867c0f47cd49b6e2ae4ef907300",
"GUID:5ce33783346c3124990afbe7b0390a06",
"GUID:5718fb738711cd34ea54e9553040911d",
"GUID:b906909fcc54f634db50f2cad0f988d9",
"GUID:3456780c4fb2d324ab9c633d6f1b0ddb"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e7fbc2b19fe484647838347cee75b556
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 870d80eb511c7774b8e41f7c788d8597
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,199 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: AAB_Animation
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1
value: {x: 360, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path: Armature/Hips/Cube
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 1930904748
attribute: 4
script: {fileID: 0}
typeID: 4
customType: 4
isPPtrCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 360
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.x
path: Armature/Hips/Cube
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.y
path: Armature/Hips/Cube
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.z
path: Armature/Hips/Cube
classID: 4
script: {fileID: 0}
m_EulerEditorCurves:
- curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.x
path: Armature/Hips/Cube
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.y
path: Armature/Hips/Cube
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.z
path: Armature/Hips/Cube
classID: 4
script: {fileID: 0}
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 13579d21560f40e439b36d4176b4b7cd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1107 &-9015797059024545987
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 2149298753904408782}
m_Position: {x: 185, y: 286, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 2149298753904408782}
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: AAB_Controller
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -9015797059024545987}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &2149298753904408782
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: AAB_Animation
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 13579d21560f40e439b36d4176b4b7cd, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 607d212fdab1a174aa89298354448c54
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,601 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &8406353226483579956
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353226483579959}
- component: {fileID: 8406353226483579958}
m_Layer: 0
m_Name: Armature
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353226483579959
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353226483579956}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 8406353228297050700}
m_Father: {fileID: 8406353227014151518}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8406353226483579958
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353226483579956}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2df373bf91cf30b4bbd495e11cb1a2ec, type: 3}
m_Name:
m_EditorClassIdentifier:
mergeTarget:
referencePath: Armature
prefix:
suffix:
locked: 0
--- !u!1 &8406353226514776489
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353226514776488}
m_Layer: 0
m_Name: Hips
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353226514776488
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353226514776489}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 8406353228177466097}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &8406353227014151519
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353227014151518}
- component: {fileID: 8406353227014151512}
- component: {fileID: 8406353227014151513}
m_Layer: 0
m_Name: Added
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353227014151518
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353227014151519}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 8406353226483579959}
m_Father: {fileID: 8406353227346201163}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8406353227014151512
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353227014151519}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
m_Name:
m_EditorClassIdentifier:
animator: {fileID: 9100000, guid: 607d212fdab1a174aa89298354448c54, type: 2}
layerType: 5
deleteAttachedAnimator: 1
pathMode: 0
matchAvatarWriteDefaults: 0
--- !u!95 &8406353227014151513
Animator:
serializedVersion: 3
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353227014151519}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: 607d212fdab1a174aa89298354448c54, type: 2}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorControllerStateOnDisable: 0
--- !u!1 &8406353227346201166
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353227346201163}
- component: {fileID: 8406353227346201160}
- component: {fileID: 8406353227346201161}
m_Layer: 0
m_Name: AnimateAddedBones
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353227346201163
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353227346201166}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.1275694, y: 1.0049627, z: 0.030396208}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 8406353228177466097}
- {fileID: 8406353227014151518}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8406353227346201160
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353227346201166}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 542108242, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3}
m_Name:
m_EditorClassIdentifier:
Name:
ViewPosition: {x: 0, y: 1.6, z: 0.2}
Animations: 0
ScaleIPD: 1
lipSync: 0
lipSyncJawBone: {fileID: 0}
lipSyncJawClosed: {x: 0, y: 0, z: 0, w: 1}
lipSyncJawOpen: {x: 0, y: 0, z: 0, w: 1}
VisemeSkinnedMesh: {fileID: 0}
MouthOpenBlendShapeName: Facial_Blends.Jaw_Down
VisemeBlendShapes: []
unityVersion:
portraitCameraPositionOffset: {x: 0, y: 0, z: 0}
portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139}
customExpressions: 1
expressionsMenu: {fileID: 0}
expressionParameters: {fileID: 0}
enableEyeLook: 0
customEyeLookSettings:
eyeMovement:
confidence: 0.5
excitement: 0.5
leftEye: {fileID: 0}
rightEye: {fileID: 0}
eyesLookingStraight:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingUp:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingDown:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingLeft:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingRight:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidType: 0
upperLeftEyelid: {fileID: 0}
upperRightEyelid: {fileID: 0}
lowerLeftEyelid: {fileID: 0}
lowerRightEyelid: {fileID: 0}
eyelidsDefault:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsClosed:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsLookingUp:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsLookingDown:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsSkinnedMesh: {fileID: 0}
eyelidsBlendshapes:
customizeAnimationLayers: 1
baseAnimationLayers:
- isEnabled: 0
type: 0
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 2
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 3
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 4
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 5
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
specialAnimationLayers:
- isEnabled: 0
type: 6
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 7
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 8
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
AnimationPreset: {fileID: 0}
animationHashSet: []
autoFootsteps: 1
autoLocomotion: 1
collider_head:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_torso:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_footR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_footL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_handR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_handL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerIndexL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerMiddleL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerRingL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerLittleL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerIndexR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerMiddleR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerRingR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerLittleR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
--- !u!114 &8406353227346201161
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353227346201166}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -1427037861, guid: 4ecd63eff847044b68db9453ce219299, type: 3}
m_Name:
m_EditorClassIdentifier:
launchedFromSDKPipeline: 0
completedSDKPipeline: 0
blueprintId:
contentType: 0
assetBundleUnityVersion:
fallbackStatus: 0
--- !u!1 &8406353228177466102
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353228177466097}
m_Layer: 0
m_Name: Armature
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353228177466097
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353228177466102}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 8406353226514776488}
m_Father: {fileID: 8406353227346201163}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &8406353228297050701
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353228297050700}
m_Layer: 0
m_Name: Hips
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353228297050700
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353228297050701}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 8406353228491165615}
m_Father: {fileID: 8406353226483579959}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &8406353228491165612
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8406353228491165615}
- component: {fileID: 8406353228491165609}
- component: {fileID: 8406353228491165614}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8406353228491165615
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353228491165612}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_Children: []
m_Father: {fileID: 8406353228297050700}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &8406353228491165609
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353228491165612}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &8406353228491165614
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8406353228491165612}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4534c39ff0a9c52498f7ccf1b88023c0
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,134 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: RootAnimation
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: RootAnimationTest
classID: 1
script: {fileID: 0}
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 1348953117
attribute: 2086281974
script: {fileID: 0}
typeID: 1
customType: 0
isPPtrCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: RootAnimationTest
classID: 1
script: {fileID: 0}
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8bc4d5b9506611c45a7d9215f59bb94f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-1125248755811767262
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: RootAnimation
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 8bc4d5b9506611c45a7d9215f59bb94f, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: RootAnimationTest
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: rootAnimTest
m_StateMachine: {fileID: 3050413205761934622}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1107 &3050413205761934622
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: rootAnimTest
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -1125248755811767262}
m_Position: {x: 315.1202, y: 53.004517, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -1125248755811767262}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0e369712684366046b73117734386e5b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,98 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4470255446025870319
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4470255446025870316}
- component: {fileID: 4470255446025870315}
- component: {fileID: 4470255446025870314}
- component: {fileID: 4470255446025870317}
m_Layer: 0
m_Name: RootAnimationTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4470255446025870316
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4470255446025870319}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.144, z: 0.612}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &4470255446025870315
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4470255446025870319}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &4470255446025870314
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4470255446025870319}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!114 &4470255446025870317
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4470255446025870319}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
m_Name:
m_EditorClassIdentifier:
animator: {fileID: 9100000, guid: 0e369712684366046b73117734386e5b, type: 2}
layerType: 5
deleteAttachedAnimator: 1
pathMode: 1

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9c01879223045064db024459ebe72513
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,134 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SelfAnim
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path:
classID: 1
script: {fileID: 0}
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 2086281974
script: {fileID: 0}
typeID: 1
customType: 0
isPPtrCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.5
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 1
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path:
classID: 1
script: {fileID: 0}
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8299508f042df3649b83f6443d4ed041
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-1125248755811767262
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: selfAnim
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 8299508f042df3649b83f6443d4ed041, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SelfAnimTest
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: selfAnimTest
m_StateMachine: {fileID: 3050413205761934622}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1107 &3050413205761934622
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: selfAnimTest
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -1125248755811767262}
m_Position: {x: 315.1202, y: 53.004517, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -1125248755811767262}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1880cdff996ddec488ba62db1359a277
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,98 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &3749365485163865256
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3749365485163865259}
- component: {fileID: 3749365485163865260}
- component: {fileID: 3749365485163865261}
- component: {fileID: 3749365485163865258}
m_Layer: 0
m_Name: SelfAnimationTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3749365485163865259
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3749365485163865256}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1.144, z: 0.612}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &3749365485163865260
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3749365485163865256}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &3749365485163865261
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3749365485163865256}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!114 &3749365485163865258
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3749365485163865256}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
m_Name:
m_EditorClassIdentifier:
animator: {fileID: 9100000, guid: 1880cdff996ddec488ba62db1359a277, type: 2}
layerType: 5
deleteAttachedAnimator: 1
pathMode: 0

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 85d821cb93b756544901b5c7368965ed
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1a037acb9296193418171fc2bdc4cef2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,101 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1107 &-2042627874815571600
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 6971386041819002268}
m_Position: {x: 172.10034, y: 224.15991, z: 0}
- serializedVersion: 1
m_State: {fileID: 1854403825162406043}
m_Position: {x: 170, y: 320, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 6971386041819002268}
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_BaseFX
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -2042627874815571600}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &1854403825162406043
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_Toggle
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: eec8cd2e6005bb544b048117daa751ac, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6971386041819002268
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_Empty
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 90b18dc284666b44c9854df52cd1fd79, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 85fd81885f9bf2845bcd91ac90d054f4
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1107 &-7544367895585285567
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: 4610933037596458320}
m_Position: {x: 262.86316, y: -391.82565, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 4610933037596458320}
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_ChildController
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: -7544367895585285567}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1102 &4610933037596458320
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_Rotate
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: e780594a122d0dc41af6048d1a95cc77, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 251b19641faa3ce4aac0bfd3c05cee12
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_Empty
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings: []
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90b18dc284666b44c9854df52cd1fd79
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,199 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_Rotate
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1
value: {x: 360, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path: Armature/Hips
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 3561920168
attribute: 4
script: {fileID: 0}
typeID: 4
customType: 4
isPPtrCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 360
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.x
path: Armature/Hips
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.y
path: Armature/Hips
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.z
path: Armature/Hips
classID: 4
script: {fileID: 0}
m_EulerEditorCurves:
- curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.x
path: Armature/Hips
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.y
path: Armature/Hips
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.z
path: Armature/Hips
classID: 4
script: {fileID: 0}
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e780594a122d0dc41af6048d1a95cc77
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,143 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TMTSO_Toggle
serializedVersion: 6
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Sw0
classID: 1
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Sw0/Added
classID: 1
script: {fileID: 0}
m_PPtrCurves: []
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 3608974950
attribute: 2086281974
script: {fileID: 0}
typeID: 1
customType: 0
isPPtrCurve: 0
- serializedVersion: 2
path: 2575739863
attribute: 2086281974
script: {fileID: 0}
typeID: 1
customType: 0
isPPtrCurve: 0
pptrCurveMapping: []
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 0
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 0
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Sw0
classID: 1
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Sw0/Added
classID: 1
script: {fileID: 0}
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eec8cd2e6005bb544b048117daa751ac
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,842 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &710753555040418776
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555040418759}
m_Layer: 0
m_Name: Sw0
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555040418759
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555040418776}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753555508593347}
m_Father: {fileID: 710753555419318260}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &710753555155880976
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555155880991}
- component: {fileID: 710753555155880989}
- component: {fileID: 710753555155880990}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555155880991
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555155880976}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_Children: []
m_Father: {fileID: 710753555840947454}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &710753555155880989
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555155880976}
m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &710753555155880990
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555155880976}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!1 &710753555202494833
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555202494832}
m_Layer: 0
m_Name: Armature
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555202494832
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555202494833}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753555840947454}
m_Father: {fileID: 710753555419318260}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &710753555419318024
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555419318260}
- component: {fileID: 710753555419318261}
- component: {fileID: 710753555419318262}
- component: {fileID: 710753555419318263}
m_Layer: 0
m_Name: TransformMappingThroughSwitchedObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555419318260
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555419318024}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.1275694, y: 1.0049627, z: 0.030396208}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753555202494832}
- {fileID: 710753555040418759}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &710753555419318261
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555419318024}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 542108242, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3}
m_Name:
m_EditorClassIdentifier:
Name:
ViewPosition: {x: 0, y: 1.6, z: 0.2}
Animations: 0
ScaleIPD: 1
lipSync: 0
lipSyncJawBone: {fileID: 0}
lipSyncJawClosed: {x: 0, y: 0, z: 0, w: 1}
lipSyncJawOpen: {x: 0, y: 0, z: 0, w: 1}
VisemeSkinnedMesh: {fileID: 0}
MouthOpenBlendShapeName: Facial_Blends.Jaw_Down
VisemeBlendShapes: []
unityVersion:
portraitCameraPositionOffset: {x: 0, y: 0, z: 0}
portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139}
customExpressions: 1
expressionsMenu: {fileID: 0}
expressionParameters: {fileID: 0}
enableEyeLook: 0
customEyeLookSettings:
eyeMovement:
confidence: 0.5
excitement: 0.5
leftEye: {fileID: 0}
rightEye: {fileID: 0}
eyesLookingStraight:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingUp:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingDown:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingLeft:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyesLookingRight:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidType: 0
upperLeftEyelid: {fileID: 0}
upperRightEyelid: {fileID: 0}
lowerLeftEyelid: {fileID: 0}
lowerRightEyelid: {fileID: 0}
eyelidsDefault:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsClosed:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsLookingUp:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsLookingDown:
upper:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
lower:
linked: 1
left: {x: 0, y: 0, z: 0, w: 0}
right: {x: 0, y: 0, z: 0, w: 0}
eyelidsSkinnedMesh: {fileID: 0}
eyelidsBlendshapes:
customizeAnimationLayers: 1
baseAnimationLayers:
- isEnabled: 0
type: 0
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 4
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 5
animatorController: {fileID: 9100000, guid: 85fd81885f9bf2845bcd91ac90d054f4,
type: 2}
mask: {fileID: 0}
isDefault: 0
specialAnimationLayers:
- isEnabled: 0
type: 6
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 7
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
- isEnabled: 0
type: 8
animatorController: {fileID: 0}
mask: {fileID: 0}
isDefault: 1
AnimationPreset: {fileID: 0}
animationHashSet: []
autoFootsteps: 1
autoLocomotion: 1
collider_head:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_torso:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_footR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_footL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_handR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_handL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerIndexL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerMiddleL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerRingL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerLittleL:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerIndexR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerMiddleR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerRingR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
collider_fingerLittleR:
isMirrored: 1
state: 0
transform: {fileID: 0}
radius: 0
height: 0
position: {x: 0, y: 0, z: 0}
rotation: {x: 0, y: 0, z: 0, w: 1}
--- !u!114 &710753555419318262
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555419318024}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -1427037861, guid: 4ecd63eff847044b68db9453ce219299, type: 3}
m_Name:
m_EditorClassIdentifier:
launchedFromSDKPipeline: 0
completedSDKPipeline: 0
blueprintId:
contentType: 0
assetBundleUnityVersion:
fallbackStatus: 0
--- !u!95 &710753555419318263
Animator:
serializedVersion: 3
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555419318024}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: 85fd81885f9bf2845bcd91ac90d054f4, type: 2}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorControllerStateOnDisable: 0
--- !u!1 &710753555508593348
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555508593347}
- component: {fileID: 710753555508593345}
- component: {fileID: 710753555508593346}
m_Layer: 0
m_Name: Added
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555508593347
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555508593348}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753555948097965}
m_Father: {fileID: 710753555040418759}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &710753555508593345
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555508593348}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
m_Name:
m_EditorClassIdentifier:
animator: {fileID: 9100000, guid: 251b19641faa3ce4aac0bfd3c05cee12, type: 2}
layerType: 5
deleteAttachedAnimator: 1
pathMode: 0
matchAvatarWriteDefaults: 0
--- !u!95 &710753555508593346
Animator:
serializedVersion: 3
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555508593348}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: 251b19641faa3ce4aac0bfd3c05cee12, type: 2}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorControllerStateOnDisable: 0
--- !u!1 &710753555840947455
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555840947454}
m_Layer: 0
m_Name: Hips
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555840947454
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555840947455}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753555155880991}
m_Father: {fileID: 710753555202494832}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &710753555941978658
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555941978657}
- component: {fileID: 710753555941978656}
m_Layer: 0
m_Name: Hips
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555941978657
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555941978658}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753556207084964}
m_Father: {fileID: 710753555948097965}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &710753555941978656
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555941978658}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 1661641543, guid: 2a2c05204084d904aa4945ccff20d8e5, type: 3}
m_Name:
m_EditorClassIdentifier:
integrationType: 0
rootTransform: {fileID: 0}
ignoreTransforms: []
endpointPosition: {x: 0, y: 0, z: 0}
multiChildType: 0
pull: 0.2
pullCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
spring: 0.2
springCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
stiffness: 0.2
stiffnessCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
gravity: 0
gravityCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
gravityFalloff: 0
gravityFalloffCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
immobileType: 0
immobile: 0
immobileCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
allowCollision: 1
radius: 0
radiusCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
colliders: []
limitType: 0
maxAngleX: 45
maxAngleXCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
maxAngleZ: 45
maxAngleZCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
limitRotation: {x: 0, y: 0, z: 0}
limitRotationXCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
limitRotationYCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
limitRotationZCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
allowGrabbing: 1
allowPosing: 1
grabMovement: 0.5
maxStretch: 0
maxStretchCurve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
isAnimated: 0
parameter:
showGizmos: 1
boneOpacity: 0.5
limitOpacity: 0.5
--- !u!1 &710753555948097966
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753555948097965}
- component: {fileID: 710753555948097964}
m_Layer: 0
m_Name: Armature
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753555948097965
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555948097966}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 710753555941978657}
m_Father: {fileID: 710753555508593347}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &710753555948097964
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753555948097966}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2df373bf91cf30b4bbd495e11cb1a2ec, type: 3}
m_Name:
m_EditorClassIdentifier:
mergeTarget:
referencePath: Armature
prefix:
suffix:
locked: 0
--- !u!1 &710753556207084965
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 710753556207084964}
- component: {fileID: 710753556207084962}
- component: {fileID: 710753556207084963}
m_Layer: 0
m_Name: Sphere
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &710753556207084964
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753556207084965}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.173, z: 0}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_Children: []
m_Father: {fileID: 710753555941978657}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!33 &710753556207084962
MeshFilter:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753556207084965}
m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
--- !u!23 &710753556207084963
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 710753556207084965}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2f45295a1cf574e40b19e78cadbcd7f1
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

1
Packages/.gitignore vendored
View File

@ -2,3 +2,4 @@
!com.vrchat.core.*/ !com.vrchat.core.*/
com.vrchat.*/ com.vrchat.*/
!nadena.dev.*/ !nadena.dev.*/
*.zip

View File

@ -0,0 +1,251 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor
{
internal class AnimationDatabase
{
internal class ClipHolder
{
internal Motion CurrentClip;
internal Motion OriginalClip { get; }
internal readonly bool IsProxyAnimation;
internal ClipHolder(Motion clip)
{
CurrentClip = OriginalClip = clip;
IsProxyAnimation = Util.IsProxyAnimation(clip);
}
}
private List<Action> _clipCommitActions = new List<Action>();
private List<ClipHolder> _clips = new List<ClipHolder>();
private Dictionary<string, HashSet<ClipHolder>> _pathToClip =
new Dictionary<string, HashSet<ClipHolder>>();
private HashSet<BlendTree> _processedBlendTrees = new HashSet<BlendTree>();
internal void Commit()
{
foreach (var clip in _clips)
{
if (clip.IsProxyAnimation) clip.CurrentClip = clip.OriginalClip;
}
foreach (var action in _clipCommitActions)
{
action();
}
}
internal void Bootstrap(VRCAvatarDescriptor avatarDescriptor)
{
foreach (var layer in avatarDescriptor.baseAnimationLayers)
{
BootstrapLayer(layer);
}
foreach (var layer in avatarDescriptor.specialAnimationLayers)
{
BootstrapLayer(layer);
}
void BootstrapLayer(VRCAvatarDescriptor.CustomAnimLayer layer)
{
if (!layer.isDefault && layer.animatorController is AnimatorController ac && Util.IsTemporaryAsset(ac))
{
foreach (var state in Util.States(ac))
{
RegisterState(state);
}
}
}
}
/// <summary>
/// Registers a motion and all its reachable submotions with the animation database. The processClip callback,
/// if provided, will be invoked for each newly discovered clip.
/// </summary>
/// <param name="state"></param>
/// <param name="processClip"></param>
/// <exception cref="Exception"></exception>
internal void RegisterState(AnimatorState state, Action<ClipHolder> processClip = null)
{
Dictionary<Motion, ClipHolder> _originalToHolder = new Dictionary<Motion, ClipHolder>();
if (processClip == null) processClip = (_) => { };
var isProxyAnim = Util.IsProxyAnimation(state.motion);
if (state.motion == null) return;
var clipHolder = RegisterMotion(state.motion, state, processClip, _originalToHolder);
if (!Util.IsTemporaryAsset(state.motion))
{
// Protect the original animations from mutations by creating temporary clones; in the case of a proxy
// animation, we'll restore the original in a later pass
var placeholder = Object.Instantiate(state.motion);
AssetDatabase.AddObjectToAsset(placeholder, state);
clipHolder.CurrentClip = placeholder;
if (isProxyAnim)
{
_clipCommitActions.Add(() => { Object.DestroyImmediate(placeholder, true); });
}
}
_clipCommitActions.Add(() => { state.motion = clipHolder.CurrentClip; });
}
internal void ForeachClip(Action<ClipHolder> processClip)
{
foreach (var clipHolder in _clips)
{
processClip(clipHolder);
}
}
/// <summary>
/// Returns a list of clips which touched the given _original_ path. This path is subject to basepath remapping,
/// but not object movement remapping.
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
internal ImmutableArray<ClipHolder> ClipsForPath(string path)
{
if (_pathToClip.TryGetValue(path, out var clips))
{
return clips.ToImmutableArray();
}
else
{
return ImmutableArray<ClipHolder>.Empty;
}
}
private ClipHolder RegisterMotion(
Motion motion,
AnimatorState state,
Action<ClipHolder> processClip,
Dictionary<Motion, ClipHolder> originalToHolder
)
{
if (originalToHolder.TryGetValue(motion, out var holder))
{
return holder;
}
switch (motion)
{
case AnimationClip clip:
{
holder = new ClipHolder(clip);
processClip(holder);
recordPaths(holder);
_clips.Add(holder);
_clipCommitActions.Add(() =>
{
if (holder.CurrentClip != holder.OriginalClip)
{
if (!AssetDatabase.IsSubAsset(holder.CurrentClip))
{
AssetDatabase.AddObjectToAsset(holder.CurrentClip, AssetDatabase.GetAssetPath(state));
}
}
});
break;
}
case BlendTree tree:
{
holder = RegisterBlendtree(tree, state, processClip, originalToHolder);
break;
}
}
originalToHolder[motion] = holder;
return holder;
}
private void recordPaths(ClipHolder holder)
{
var clip = holder.CurrentClip as AnimationClip;
foreach (var binding in AnimationUtility.GetCurveBindings(clip))
{
var path = binding.path;
AddPath(path);
}
foreach (var binding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
{
var path = binding.path;
AddPath(path);
}
void AddPath(string p0)
{
if (!_pathToClip.TryGetValue(p0, out var clips))
{
clips = new HashSet<ClipHolder>();
_pathToClip[p0] = clips;
}
clips.Add(holder);
}
}
private ClipHolder RegisterBlendtree(
BlendTree tree,
AnimatorState state,
Action<ClipHolder> processClip,
Dictionary<Motion, ClipHolder> originalToHolder
)
{
if (!Util.IsTemporaryAsset(tree))
{
throw new Exception("Blendtree must be a temporary asset");
}
var treeHolder = new ClipHolder(tree);
var children = tree.children;
var holders = new ClipHolder[children.Length];
for (int i = 0; i < children.Length; i++)
{
holders[i] = RegisterMotion(children[i].motion, state, processClip, originalToHolder);
}
_clipCommitActions.Add(() =>
{
var dirty = false;
for (int i = 0; i < children.Length; i++)
{
var curClip = holders[i].CurrentClip;
if (children[i].motion != curClip)
{
children[i].motion = curClip;
dirty = true;
if (string.IsNullOrWhiteSpace(AssetDatabase.GetAssetPath(curClip)))
{
AssetDatabase.AddObjectToAsset(curClip, AssetDatabase.GetAssetPath(state));
}
}
}
if (dirty)
{
tree.children = children;
EditorUtility.SetDirty(tree);
}
});
return treeHolder;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 11130986120e452b8dc8db0d19aa71fc
timeCreated: 1671624207

View File

@ -36,7 +36,7 @@ namespace nadena.dev.modular_avatar.core.editor
internal class AnimatorCombiner internal class AnimatorCombiner
{ {
private readonly AnimatorController _combined; private readonly AnimatorController _combined;
private AnimatorOverrideController _overrideController; private AnimatorOverrideController _overrideController;
private List<AnimatorControllerLayer> _layers = new List<AnimatorControllerLayer>(); private List<AnimatorControllerLayer> _layers = new List<AnimatorControllerLayer>();
@ -92,15 +92,17 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
public void AddOverrideController(string basePath, AnimatorOverrideController overrideController, bool? writeDefaults) public void AddOverrideController(string basePath, AnimatorOverrideController overrideController,
bool? writeDefaults)
{ {
AnimatorController controller = overrideController.runtimeAnimatorController as AnimatorController; AnimatorController controller = overrideController.runtimeAnimatorController as AnimatorController;
if (controller == null) return; if (controller == null) return;
_overrideController = overrideController; _overrideController = overrideController;
try try
{ {
this.AddController(basePath, controller, writeDefaults); this.AddController(basePath, controller, writeDefaults);
} finally }
finally
{ {
_overrideController = null; _overrideController = null;
} }
@ -192,16 +194,16 @@ namespace nadena.dev.modular_avatar.core.editor
newPath = newPath.Substring(0, newPath.Length - 1); newPath = newPath.Substring(0, newPath.Length - 1);
} }
return PathMappings.MapPath(newPath, binding.type == typeof(Transform)); return newPath;
} }
} }
private Object customClone(Object o, string basePath) private Object customClone(Object o, string basePath)
{ {
if (basePath == "") return null;
if (o is AnimationClip clip) if (o is AnimationClip clip)
{ {
if (basePath == "" || Util.IsProxyAnimation(clip)) return clip;
AnimationClip newClip = new AnimationClip(); AnimationClip newClip = new AnimationClip();
newClip.name = "rebased " + clip.name; newClip.name = "rebased " + clip.name;
AssetDatabase.AddObjectToAsset(newClip, _combined); AssetDatabase.AddObjectToAsset(newClip, _combined);
@ -277,10 +279,10 @@ namespace nadena.dev.modular_avatar.core.editor
} }
// When using AnimatorOverrideController, replace the original AnimationClip based on AnimatorOverrideController. // When using AnimatorOverrideController, replace the original AnimationClip based on AnimatorOverrideController.
if (_overrideController != null && original is AnimationClip srcClip) if (_overrideController != null && original is AnimationClip srcClip)
{ {
T overrideClip = _overrideController[srcClip] as T; T overrideClip = _overrideController[srcClip] as T;
if (overrideClip != null) if (overrideClip != null)
{ {
original = overrideClip; original = overrideClip;
} }

View File

@ -26,12 +26,15 @@ using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using VRC.SDK3.Avatars.Components; using VRC.SDK3.Avatars.Components;
using VRC.SDKBase.Editor.BuildPipeline; using VRC.SDKBase.Editor.BuildPipeline;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
[assembly: InternalsVisibleTo("Tests")]
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
{ {
[InitializeOnLoad] [InitializeOnLoad]
@ -129,8 +132,10 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
nowProcessing = true; nowProcessing = true;
var vrcAvatarDescriptor = avatarGameObject.GetComponent<VRCAvatarDescriptor>();
BoneDatabase.ResetBones(); BoneDatabase.ResetBones();
PathMappings.Clear(); PathMappings.Init(vrcAvatarDescriptor.gameObject);
ClonedMenuMappings.Clear(); ClonedMenuMappings.Clear();
// Sometimes people like to nest one avatar in another, when transplanting clothing. To avoid issues // Sometimes people like to nest one avatar in another, when transplanting clothing. To avoid issues
@ -149,16 +154,22 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
var context = new BuildContext(vrcAvatarDescriptor);
new RenameParametersHook().OnPreprocessAvatar(avatarGameObject); new RenameParametersHook().OnPreprocessAvatar(avatarGameObject);
new MenuInstallHook().OnPreprocessAvatar(avatarGameObject);
new MergeArmatureHook().OnPreprocessAvatar(avatarGameObject);
new RetargetMeshes().OnPreprocessAvatar(avatarGameObject);
new BoneProxyProcessor().OnPreprocessAvatar(avatarGameObject);
new VisibleHeadAccessoryProcessor(avatarGameObject.GetComponent<VRCAvatarDescriptor>()).Process();
new MergeAnimatorProcessor().OnPreprocessAvatar(avatarGameObject); new MergeAnimatorProcessor().OnPreprocessAvatar(avatarGameObject);
new BlendshapeSyncAnimationProcessor().OnPreprocessAvatar(avatarGameObject); context.AnimationDatabase.Bootstrap(vrcAvatarDescriptor);
new MenuInstallHook().OnPreprocessAvatar(avatarGameObject);
new MergeArmatureHook().OnPreprocessAvatar(context, avatarGameObject);
new BoneProxyProcessor().OnPreprocessAvatar(avatarGameObject);
new VisibleHeadAccessoryProcessor(vrcAvatarDescriptor).Process();
new RemapAnimationPass(vrcAvatarDescriptor).Process(context.AnimationDatabase);
new BlendshapeSyncAnimationProcessor().OnPreprocessAvatar(avatarGameObject, context.AnimationDatabase);
PhysboneBlockerPass.Process(avatarGameObject); PhysboneBlockerPass.Process(avatarGameObject);
context.AnimationDatabase.Commit();
AfterProcessing?.Invoke(avatarGameObject); AfterProcessing?.Invoke(avatarGameObject);
FixupAnimatorDebugData(avatarGameObject); FixupAnimatorDebugData(avatarGameObject);
@ -173,16 +184,15 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
UnityEngine.Object.DestroyImmediate(component); UnityEngine.Object.DestroyImmediate(component);
} }
var activator = avatarGameObject.GetComponent<AvatarActivator>(); var activator = avatarGameObject.GetComponent<AvatarActivator>();
if (activator != null) if (activator != null)
{ {
UnityEngine.Object.DestroyImmediate(activator); UnityEngine.Object.DestroyImmediate(activator);
} }
ClonedMenuMappings.Clear(); ClonedMenuMappings.Clear();
} }
} }
[SuppressMessage("ReSharper", "PossibleNullReferenceException")] [SuppressMessage("ReSharper", "PossibleNullReferenceException")]

View File

@ -43,7 +43,7 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
public void OnPreprocessAvatar(GameObject avatar) public void OnPreprocessAvatar(GameObject avatar, AnimationDatabase animDb)
{ {
var avatarDescriptor = avatar.GetComponent<VRCAvatarDescriptor>(); var avatarDescriptor = avatar.GetComponent<VRCAvatarDescriptor>();
_bindingMappings = new Dictionary<SummaryBinding, List<SummaryBinding>>(); _bindingMappings = new Dictionary<SummaryBinding, List<SummaryBinding>>();
@ -102,21 +102,14 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
// Ensure we have a unique copy of the controller.
if (!Util.IsTemporaryAsset(controller))
{
controller = Util.DeepCloneAnimator(controller);
layers[fxIndex].animatorController = controller;
avatarDescriptor.baseAnimationLayers = layers;
}
_container = controller;
// Walk and transform all clips // Walk and transform all clips
foreach (var state in AllStates(controller)) animDb.ForeachClip(clip =>
{ {
state.motion = TransformMotion(state.motion); if (clip.CurrentClip is AnimationClip anim)
} {
clip.CurrentClip = TransformMotion(anim);
}
});
} }
Motion TransformMotion(Motion motion) Motion TransformMotion(Motion motion)
@ -152,7 +145,16 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
var newTree = new BlendTree(); var newTree = new BlendTree();
EditorUtility.CopySerialized(tree, newTree); EditorUtility.CopySerialized(tree, newTree);
AssetDatabase.AddObjectToAsset(newTree, _container); if (_container == null)
{
_container = newTree;
AssetDatabase.CreateAsset(_container, Util.GenerateAssetPath());
}
else
{
AssetDatabase.AddObjectToAsset(newTree, _container);
}
newTree.children = children; newTree.children = children;
motion = newTree; motion = newTree;
} }
@ -183,7 +185,6 @@ namespace nadena.dev.modular_avatar.core.editor
if (clip == origClip) if (clip == origClip)
{ {
clip = Object.Instantiate(clip); clip = Object.Instantiate(clip);
AssetDatabase.AddObjectToAsset(clip, _container);
} }
foreach (var dst in dstBindings) foreach (var dst in dstBindings)

View File

@ -51,12 +51,6 @@ namespace nadena.dev.modular_avatar.core.editor
transform.localPosition = Vector3.zero; transform.localPosition = Vector3.zero;
transform.localRotation = Quaternion.identity; transform.localRotation = Quaternion.identity;
} }
PathMappings.Remap(oldPath, new PathMappings.MappingEntry()
{
path = RuntimeUtil.AvatarRootPath(proxy.gameObject),
transformPath = RuntimeUtil.AvatarRootPath(proxy.gameObject)
});
} }
Object.DestroyImmediate(proxy); Object.DestroyImmediate(proxy);

View File

@ -0,0 +1,15 @@
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core.editor
{
internal class BuildContext
{
internal readonly VRCAvatarDescriptor AvatarDescriptor;
internal readonly AnimationDatabase AnimationDatabase = new AnimationDatabase();
public BuildContext(VRCAvatarDescriptor avatarDescriptor)
{
AvatarDescriptor = avatarDescriptor;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 41bbb1832c9d409a999605fae058dd19
timeCreated: 1671624226

View File

@ -127,6 +127,13 @@ namespace nadena.dev.modular_avatar.core.editor
defaultControllers_[layer.type] = controller; defaultControllers_[layer.type] = controller;
writeDefaults_[layer.type] = ProbeWriteDefaults(controller); writeDefaults_[layer.type] = ProbeWriteDefaults(controller);
if (!layer.isDefault)
{
// For non-default layers, ensure we always clone the controller for the benefit of subsequent
// processing phases
mergeSessions[layer.type] = new AnimatorCombiner();
mergeSessions[layer.type].AddController("", controller, null);
}
} }
} }

View File

@ -24,10 +24,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.Animations; using UnityEngine.Animations;
using VRC.Dynamics; using VRC.Dynamics;
using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Dynamics.PhysBone.Components; using VRC.SDK3.Dynamics.PhysBone.Components;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
@ -35,21 +37,14 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
internal class MergeArmatureHook internal class MergeArmatureHook
{ {
private Dictionary<Transform, Transform> BoneRemappings = new Dictionary<Transform, Transform>(); private BuildContext context;
private HashSet<GameObject> ToDelete = new HashSet<GameObject>();
private HashSet<IConstraint> AddedConstraints = new HashSet<IConstraint>();
internal bool OnPreprocessAvatar(GameObject avatarGameObject) internal void OnPreprocessAvatar(BuildContext context, GameObject avatarGameObject)
{ {
BoneRemappings.Clear(); this.context = context;
ToDelete.Clear();
AddedConstraints.Clear();
var mergeArmatures = avatarGameObject.transform.GetComponentsInChildren<ModularAvatarMergeArmature>(true); var mergeArmatures = avatarGameObject.transform.GetComponentsInChildren<ModularAvatarMergeArmature>(true);
BoneRemappings.Clear();
ToDelete.Clear();
foreach (var mergeArmature in mergeArmatures) foreach (var mergeArmature in mergeArmatures)
{ {
MergeArmature(mergeArmature); MergeArmature(mergeArmature);
@ -59,74 +54,39 @@ namespace nadena.dev.modular_avatar.core.editor
foreach (var renderer in avatarGameObject.transform.GetComponentsInChildren<SkinnedMeshRenderer>(true)) foreach (var renderer in avatarGameObject.transform.GetComponentsInChildren<SkinnedMeshRenderer>(true))
{ {
var bones = renderer.bones; var bones = renderer.bones;
for (int i = 0; i < bones.Length; i++) bones[i] = MapBoneReference(bones[i], Retargetable.Ignore);
renderer.bones = bones; renderer.bones = bones;
renderer.rootBone = MapBoneReference(renderer.rootBone, Retargetable.Ignore);
renderer.probeAnchor = MapBoneReference(renderer.probeAnchor);
} }
foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRCPhysBone>(true)) foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRCPhysBone>(true))
{ {
if (c.rootTransform == null) c.rootTransform = c.transform; if (c.rootTransform == null) c.rootTransform = c.transform;
UpdateBoneReferences(c); RetainBoneReferences(c);
} }
foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRCPhysBoneCollider>(true)) foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRCPhysBoneCollider>(true))
{ {
if (c.rootTransform == null) c.rootTransform = c.transform; if (c.rootTransform == null) c.rootTransform = c.transform;
UpdateBoneReferences(c); RetainBoneReferences(c);
} }
foreach (var c in avatarGameObject.transform.GetComponentsInChildren<ContactBase>(true)) foreach (var c in avatarGameObject.transform.GetComponentsInChildren<ContactBase>(true))
{ {
if (c.rootTransform == null) c.rootTransform = c.transform; if (c.rootTransform == null) c.rootTransform = c.transform;
UpdateBoneReferences(c); RetainBoneReferences(c);
} }
foreach (var c in avatarGameObject.transform.GetComponentsInChildren<IConstraint>(true)) foreach (var c in avatarGameObject.transform.GetComponentsInChildren<IConstraint>(true))
{ {
if (!AddedConstraints.Contains(c)) RetainBoneReferences(c as Component);
{
FixupConstraint(c);
}
} }
foreach (var bone in ToDelete) UnityEngine.Object.DestroyImmediate(bone); new RetargetMeshes().OnPreprocessAvatar(avatarGameObject);
return true;
} }
private void FixupConstraint(IConstraint constraint) private void RetainBoneReferences(Component c)
{ {
int nSources = constraint.sourceCount; if (c == null) return;
for (int i = 0; i < nSources; i++)
{
var source = constraint.GetSource(i);
source.sourceTransform = MapConstraintSource(source.sourceTransform);
constraint.SetSource(i, source);
}
if (constraint is AimConstraint aimConstraint)
{
aimConstraint.worldUpObject = MapConstraintSource(aimConstraint.worldUpObject);
}
if (constraint is LookAtConstraint lookAtConstraint)
{
lookAtConstraint.worldUpObject = MapConstraintSource(lookAtConstraint.worldUpObject);
}
}
private Transform MapConstraintSource(Transform transform)
{
if (transform == null) return null;
if (!BoneRemappings.TryGetValue(transform, out var remap)) return transform;
var retarget = BoneDatabase.GetRetargetedBone(remap);
return retarget != null ? retarget : remap;
}
private void UpdateBoneReferences(Component c, Retargetable retargetable = Retargetable.Disable)
{
SerializedObject so = new SerializedObject(c); SerializedObject so = new SerializedObject(c);
SerializedProperty iter = so.GetIterator(); SerializedProperty iter = so.GetIterator();
@ -144,17 +104,11 @@ namespace nadena.dev.modular_avatar.core.editor
if (iter.objectReferenceValue is Transform t) if (iter.objectReferenceValue is Transform t)
{ {
var mapped = MapBoneReference(t, retargetable); BoneDatabase.RetainMergedBone(t);
iter.objectReferenceValue = mapped;
ClearToDeleteFlag(mapped);
} }
else if (iter.objectReferenceValue is GameObject go) else if (iter.objectReferenceValue is GameObject go)
{ {
var mapped = MapBoneReference(go.transform, retargetable); BoneDatabase.RetainMergedBone(go.transform);
iter.objectReferenceValue = mapped?.gameObject;
ClearToDeleteFlag(mapped);
} }
break; break;
@ -164,40 +118,7 @@ namespace nadena.dev.modular_avatar.core.editor
so.ApplyModifiedPropertiesWithoutUndo(); so.ApplyModifiedPropertiesWithoutUndo();
} }
private void ClearToDeleteFlag(Transform t) private bool HasAdditionalComponents(GameObject go)
{
while (t != null && ToDelete.Contains(t.gameObject))
{
ToDelete.Remove(t.gameObject);
t = t.parent;
}
}
enum Retargetable
{
Disable,
Ignore,
Use
}
private Transform MapBoneReference(Transform bone, Retargetable retargetable = Retargetable.Disable)
{
if (bone != null && BoneRemappings.TryGetValue(bone, out var newBone))
{
if (retargetable == Retargetable.Disable) BoneDatabase.MarkNonRetargetable(newBone);
bone = newBone;
}
if (bone != null && retargetable == Retargetable.Use)
{
var retargeted = BoneDatabase.GetRetargetedBone(bone);
if (retargeted != null) bone = retargeted;
}
return bone;
}
private bool HasAdditionalComponents(GameObject go, out Type constraintType)
{ {
bool hasComponents = false; bool hasComponents = false;
bool needsConstraint = false; bool needsConstraint = false;
@ -210,165 +131,235 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
case Transform _: break; case Transform _: break;
case ModularAvatarMergeArmature _: break; case ModularAvatarMergeArmature _: break;
case VRCPhysBone _:
case VRCPhysBoneCollider _:
hasComponents = true;
break;
case AimConstraint _:
case LookAtConstraint _:
case RotationConstraint _:
hasRotationConstraint = true;
needsConstraint = true;
hasComponents = true;
break;
case PositionConstraint _:
hasPositionConstraint = true;
needsConstraint = true;
hasComponents = true;
break;
case ParentConstraint _:
needsConstraint = false;
hasPositionConstraint = hasRotationConstraint = true;
hasComponents = true;
break;
default: default:
hasComponents = true; hasComponents = true;
needsConstraint = true;
break; break;
} }
} }
if (!needsConstraint || (hasPositionConstraint && hasRotationConstraint))
{
constraintType = null;
}
else if (hasPositionConstraint)
{
constraintType = typeof(RotationConstraint);
}
else if (hasRotationConstraint)
{
constraintType = typeof(PositionConstraint);
}
else
{
constraintType = typeof(ParentConstraint);
}
return hasComponents; return hasComponents;
} }
/// <summary>
/// Tracks an object whose Active state is animated, and which leads up to this Merge Animator component.
/// We use this tracking data to create proxy objects within the main armature, which track the same active
/// state.
/// </summary>
struct IntermediateObj
{
/// <summary>
/// Name of the intermediate object. Used to name proxy objects.
/// </summary>
public string name;
/// <summary>
/// The original path of this intermediate object.
/// </summary>
public string originPath;
/// <summary>
/// Whether this object is initially active.
/// </summary>
public bool active;
}
private List<IntermediateObj> intermediateObjects = new List<IntermediateObj>();
private Dictionary<string, List<string>> activationPathMappings = new Dictionary<string, List<string>>();
private void MergeArmature(ModularAvatarMergeArmature mergeArmature) private void MergeArmature(ModularAvatarMergeArmature mergeArmature)
{ {
// TODO: error reporting framework? // TODO: error reporting framework?
if (mergeArmature.mergeTargetObject == null) return; if (mergeArmature.mergeTargetObject == null) return;
GatherActiveStatePaths(mergeArmature.transform);
RecursiveMerge(mergeArmature, mergeArmature.gameObject, mergeArmature.mergeTargetObject.gameObject, true); RecursiveMerge(mergeArmature, mergeArmature.gameObject, mergeArmature.mergeTargetObject.gameObject, true);
FixupAnimations();
}
private AnimationCurve GetActiveBinding(AnimationClip clip, string path)
{
return AnimationUtility.GetEditorCurve(clip,
EditorCurveBinding.FloatCurve(path, typeof(GameObject), "m_IsActive"));
}
private void FixupAnimations()
{
foreach (var kvp in activationPathMappings)
{
var path = kvp.Key;
var mappings = kvp.Value;
foreach (var holder in context.AnimationDatabase.ClipsForPath(path))
{
if (!Util.IsTemporaryAsset(holder.CurrentClip))
{
holder.CurrentClip = Object.Instantiate(holder.CurrentClip);
}
var clip = holder.CurrentClip as AnimationClip;
if (clip == null) continue;
var curve = GetActiveBinding(clip, path);
if (curve != null)
{
foreach (var mapping in mappings)
{
clip.SetCurve(mapping, typeof(GameObject), "m_IsActive", curve);
}
}
}
}
}
private void GatherActiveStatePaths(Transform root)
{
intermediateObjects.Clear();
activationPathMappings.Clear();
List<IntermediateObj> rootPath = new List<IntermediateObj>();
while (root != null && root.GetComponent<VRCAvatarDescriptor>() == null)
{
rootPath.Insert(0, new IntermediateObj()
{
name = root.name,
originPath = RuntimeUtil.AvatarRootPath(root.gameObject),
active = root.gameObject.activeSelf
});
root = root.parent;
}
var prefix = "";
for (int i = 1; i <= rootPath.Count; i++)
{
var srcPrefix = string.Join("/", rootPath.Take(i).Select(p => p.name));
if (context.AnimationDatabase.ClipsForPath(srcPrefix).Any(clip =>
GetActiveBinding(clip.CurrentClip as AnimationClip, srcPrefix) != null
))
{
var intermediate = rootPath[i - 1].name + "$" + Guid.NewGuid().ToString();
var originPath = rootPath[i - 1].originPath;
intermediateObjects.Add(new IntermediateObj()
{
name = intermediate,
originPath = originPath,
active = rootPath[i - 1].active
});
if (prefix.Length > 0) prefix += "/";
prefix += intermediate;
activationPathMappings[originPath] = new List<string>();
}
}
} }
/** /**
* (Attempts to) merge the source gameobject into the target gameobject. Returns true if the merged source * (Attempts to) merge the source gameobject into the target gameobject. Returns true if the merged source
* object must be retained. * object must be retained.
*/ */
private bool RecursiveMerge( private void RecursiveMerge(ModularAvatarMergeArmature config,
ModularAvatarMergeArmature config,
GameObject src, GameObject src,
GameObject newParent, GameObject newParent,
bool zipMerge bool zipMerge)
)
{ {
if (src == newParent) if (src == newParent)
{ {
throw new Exception("[ModularAvatar] Attempted to merge an armature into itself! Aborting build..."); throw new Exception("[ModularAvatar] Attempted to merge an armature into itself! Aborting build...");
} }
GameObject mergedSrcBone = new GameObject(src.name + "@" + GUID.Generate());
mergedSrcBone.transform.SetParent(src.transform.parent);
mergedSrcBone.transform.localPosition = src.transform.localPosition;
mergedSrcBone.transform.localRotation = src.transform.localRotation;
mergedSrcBone.transform.localScale = src.transform.localScale;
mergedSrcBone.transform.SetParent(newParent.transform, true);
if (zipMerge) PruneDuplicatePhysBones(newParent, src); if (zipMerge) PruneDuplicatePhysBones(newParent, src);
bool retain = HasAdditionalComponents(src, out var constraintType); bool retain = HasAdditionalComponents(src) || !zipMerge;
if (constraintType != null) zipMerge = zipMerge && src.GetComponent<IConstraint>() == null;
GameObject mergedSrcBone = newParent;
if (retain)
{ {
IConstraint constraint = (IConstraint) src.AddComponent(constraintType); mergedSrcBone = newParent;
AddedConstraints.Add(constraint); var switchPath = "";
constraint.AddSource(new ConstraintSource() foreach (var intermediate in intermediateObjects)
{ {
weight = 1, var preexisting = mergedSrcBone.transform.Find(intermediate.name);
sourceTransform = mergedSrcBone.transform if (preexisting != null)
}); {
Matrix4x4 targetToSrc = src.transform.worldToLocalMatrix * newParent.transform.localToWorldMatrix; mergedSrcBone = preexisting.gameObject;
if (constraint is ParentConstraint pc) continue;
{ }
pc.translationOffsets = new Vector3[] {targetToSrc.MultiplyPoint(Vector3.zero)};
pc.rotationOffsets = new Vector3[] {targetToSrc.rotation.eulerAngles}; var switchObj = new GameObject(intermediate.name);
switchObj.transform.SetParent(mergedSrcBone.transform, false);
switchObj.transform.localPosition = Vector3.zero;
switchObj.transform.localRotation = Quaternion.identity;
switchObj.transform.localScale = Vector3.one;
switchObj.SetActive(intermediate.active);
if (switchPath.Length > 0)
{
switchPath += "/";
}
else
{
// This new leaf can break parent bone physbones. Add a PB Blocker
// to prevent this becoming an issue.
switchObj.GetOrAddComponent<ModularAvatarPBBlocker>();
}
switchPath += intermediate.name;
activationPathMappings[intermediate.originPath].Add(RuntimeUtil.AvatarRootPath(switchObj));
mergedSrcBone = switchObj;
// Ensure mesh retargeting looks through this
BoneDatabase.AddMergedBone(mergedSrcBone.transform);
BoneDatabase.RetainMergedBone(mergedSrcBone.transform);
PathMappings.MarkTransformLookthrough(mergedSrcBone);
} }
constraint.locked = true;
constraint.constraintActive = true;
} }
if ((constraintType != null && constraintType != typeof(ParentConstraint)) src.transform.SetParent(mergedSrcBone.transform, true);
|| (constraintType == null && src.GetComponent<IConstraint>() != null)) src.name = src.name + "$" + Guid.NewGuid();
{ src.GetOrAddComponent<ModularAvatarPBBlocker>();
return true; mergedSrcBone = src;
}
if (zipMerge) if (zipMerge)
{ {
BoneDatabase.AddMergedBone(mergedSrcBone.transform); PathMappings.MarkTransformLookthrough(src);
var srcPath = RuntimeUtil.AvatarRootPath(src); BoneDatabase.AddMergedBone(src.transform);
PathMappings.Remap(srcPath, new PathMappings.MappingEntry()
{
transformPath = RuntimeUtil.AvatarRootPath(newParent),
path = srcPath
});
// The new merged leaf (if it's retained below) can break parent bone physbones. Add a PB Blocker
// to prevent this becoming an issue.
mergedSrcBone.GetOrAddComponent<ModularAvatarPBBlocker>();
} }
BoneRemappings[src.transform] = mergedSrcBone.transform;
List<Transform> children = new List<Transform>(); List<Transform> children = new List<Transform>();
foreach (Transform child in src.transform) foreach (Transform child in src.transform)
{ {
children.Add(child); children.Add(child);
} }
foreach (Transform child in children) if (zipMerge)
{ {
var childGameObject = child.gameObject; foreach (Transform child in children)
var childName = childGameObject.name;
GameObject childNewParent = mergedSrcBone;
bool shouldZip = zipMerge;
if (shouldZip && childName.StartsWith(config.prefix) && childName.EndsWith(config.suffix))
{ {
var targetObjectName = childName.Substring(config.prefix.Length, var childGameObject = child.gameObject;
childName.Length - config.prefix.Length - config.suffix.Length); var childName = childGameObject.name;
var targetObject = newParent.transform.Find(targetObjectName); GameObject childNewParent = mergedSrcBone;
if (targetObject != null) bool shouldZip = false;
if (childName.StartsWith(config.prefix) && childName.EndsWith(config.suffix))
{ {
childNewParent = targetObject.gameObject; var targetObjectName = childName.Substring(config.prefix.Length,
} childName.Length - config.prefix.Length - config.suffix.Length);
else var targetObject = newParent.transform.Find(targetObjectName);
{ if (targetObject != null)
shouldZip = false; {
childNewParent = targetObject.gameObject;
shouldZip = true;
}
} }
RecursiveMerge(config, childGameObject, childNewParent, shouldZip);
} }
var retainChild = RecursiveMerge(config, childGameObject, childNewParent, shouldZip);
retain = retain || retainChild;
} }
if (!retain) ToDelete.Add(src);
return retain;
} }
/** /**
@ -406,4 +397,4 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
} }
} }

View File

@ -44,8 +44,9 @@ namespace nadena.dev.modular_avatar.core.editor
IsRetargetable[bone] = true; IsRetargetable[bone] = true;
} }
internal static void MarkNonRetargetable(Transform bone) internal static void RetainMergedBone(Transform bone)
{ {
if (bone == null) return;
if (IsRetargetable.ContainsKey(bone)) IsRetargetable[bone] = false; if (IsRetargetable.ContainsKey(bone)) IsRetargetable[bone] = false;
} }
@ -117,6 +118,7 @@ namespace nadena.dev.modular_avatar.core.editor
child.SetParent(destBone, true); child.SetParent(destBone, true);
} }
PathMappings.MarkRemoved(sourceBone.gameObject);
UnityEngine.Object.DestroyImmediate(sourceBone.gameObject); UnityEngine.Object.DestroyImmediate(sourceBone.gameObject);
} }
} }
@ -132,13 +134,6 @@ namespace nadena.dev.modular_avatar.core.editor
private readonly SkinnedMeshRenderer renderer; private readonly SkinnedMeshRenderer renderer;
private Mesh src, dst; private Mesh src, dst;
struct BindInfo
{
public Matrix4x4 priorLocalToBone;
public Matrix4x4 localToBone;
public Matrix4x4 priorToNew;
}
public MeshRetargeter(SkinnedMeshRenderer renderer) public MeshRetargeter(SkinnedMeshRenderer renderer)
{ {
this.renderer = renderer; this.renderer = renderer;

View File

@ -23,50 +23,128 @@
*/ */
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using NUnit.Framework;
using UnityEngine; using UnityEngine;
using VRC.SDKBase.Editor.BuildPipeline; using VRC.SDKBase.Editor.BuildPipeline;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
{ {
// TODO - needs optimization pass maybe?
internal static class PathMappings internal static class PathMappings
{ {
private static List<(string, MappingEntry)> Mappings = new List<(string, MappingEntry)>(); private static Dictionary<GameObject, List<string>> _objectToOriginalPaths =
new Dictionary<GameObject, List<string>>();
internal struct MappingEntry private static ImmutableDictionary<string, string> _originalPathToMappedPath = null;
private static ImmutableDictionary<string, string> _transformOriginalPathToMappedPath = null;
private static HashSet<GameObject> _transformLookthroughObjects = new HashSet<GameObject>();
internal static void Init(GameObject root)
{ {
public string path; _objectToOriginalPaths.Clear();
public string transformPath; _originalPathToMappedPath = null;
_transformLookthroughObjects.Clear();
public string Get(bool isTransformMapping) foreach (var xform in root.GetComponentsInChildren<Transform>(true))
{ {
return isTransformMapping ? transformPath : path; var path = RuntimeUtil.RelativePath(root, xform.gameObject);
_objectToOriginalPaths.Add(xform.gameObject, new List<string> {path});
}
ClearCache();
}
internal static void ClearCache()
{
_originalPathToMappedPath = _transformOriginalPathToMappedPath = null;
}
/// <summary>
/// When animating a transform component on a merged bone, we want to make sure we manipulate the original
/// avatar's bone, not a stub bone attached underneath. By making an object as transform lookthrough, any
/// queries for mapped paths on the transform component will walk up the tree to the next parent.
/// </summary>
/// <param name="obj">The object to mark transform lookthrough</param>
internal static void MarkTransformLookthrough(GameObject obj)
{
ClearCache();
_transformLookthroughObjects.Add(obj);
}
/// <summary>
/// Marks an object as having been removed. Its paths will be remapped to its parent.
/// </summary>
/// <param name="obj"></param>
internal static void MarkRemoved(GameObject obj)
{
ClearCache();
if (_objectToOriginalPaths.TryGetValue(obj, out var paths))
{
var parent = obj.transform.parent.gameObject;
if (_objectToOriginalPaths.TryGetValue(parent, out var parentPaths))
{
parentPaths.AddRange(paths);
}
_objectToOriginalPaths.Remove(obj);
_transformLookthroughObjects.Remove(obj);
} }
} }
internal static void Clear() private static ImmutableDictionary<string, string> BuildMapping(ref ImmutableDictionary<string, string> cache,
bool transformLookup)
{ {
Mappings.Clear(); if (cache != null) return cache;
}
internal static void Remap(string from, MappingEntry to) ImmutableDictionary<string, string>.Builder builder = ImmutableDictionary.CreateBuilder<string, string>();
{
Mappings.Add((from, to)); foreach (var kvp in _objectToOriginalPaths)
{
var obj = kvp.Key;
var paths = kvp.Value;
if (transformLookup)
{
while (_transformLookthroughObjects.Contains(obj))
{
obj = obj.transform.parent.gameObject;
}
}
var newPath = RuntimeUtil.AvatarRootPath(obj);
foreach (var origPath in paths)
{
builder.Add(origPath, newPath);
}
}
cache = builder.ToImmutableDictionary();
return cache;
} }
internal static string MapPath(string path, bool isTransformMapping = false) internal static string MapPath(string path, bool isTransformMapping = false)
{ {
foreach (var (src, mapping) in Mappings) ImmutableDictionary<string, string> mappings;
{
if (path == src || path.StartsWith(src + "/"))
{
var suffix = path.Substring(src.Length);
path = mapping.Get(isTransformMapping) + suffix;
// Continue processing subsequent remappings if (isTransformMapping)
} {
mappings = BuildMapping(ref _originalPathToMappedPath, true);
}
else
{
mappings = BuildMapping(ref _transformOriginalPathToMappedPath, false);
} }
return path; if (mappings.TryGetValue(path, out var mappedPath))
{
return mappedPath;
}
else
{
return path;
}
} }
} }
} }

View File

@ -0,0 +1,79 @@
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core.editor
{
/// <summary>
/// Remaps all animation path references based on PathMappings data.
/// </summary>
internal class RemapAnimationPass
{
private readonly VRCAvatarDescriptor _avatarDescriptor;
public RemapAnimationPass(VRCAvatarDescriptor avatarDescriptor)
{
_avatarDescriptor = avatarDescriptor;
}
public void Process(AnimationDatabase animDb)
{
PathMappings.ClearCache();
animDb.ForeachClip(clip =>
{
if (clip.CurrentClip is AnimationClip anim && !clip.IsProxyAnimation)
{
clip.CurrentClip = MapMotion(anim);
}
});
}
private static string MapPath(EditorCurveBinding binding)
{
if (binding.type == typeof(Animator) && binding.path == "")
{
return "";
}
else
{
return PathMappings.MapPath(binding.path, binding.type == typeof(Transform));
}
}
private AnimationClip MapMotion(AnimationClip clip)
{
if (clip.name.StartsWith("proxy_"))
{
Debug.Log("");
}
AnimationClip newClip = new AnimationClip();
newClip.name = "remapped " + clip.name;
foreach (var binding in AnimationUtility.GetCurveBindings(clip))
{
var newBinding = binding;
newBinding.path = MapPath(binding);
newClip.SetCurve(newBinding.path, newBinding.type, newBinding.propertyName,
AnimationUtility.GetEditorCurve(clip, binding));
}
foreach (var objBinding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
{
var newBinding = objBinding;
newBinding.path = MapPath(objBinding);
AnimationUtility.SetObjectReferenceCurve(newClip, newBinding,
AnimationUtility.GetObjectReferenceCurve(clip, objBinding));
}
newClip.wrapMode = clip.wrapMode;
newClip.legacy = clip.legacy;
newClip.frameRate = clip.frameRate;
newClip.localBounds = clip.localBounds;
AnimationUtility.SetAnimationClipSettings(newClip, AnimationUtility.GetAnimationClipSettings(clip));
return newClip;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 13e4085d9ace44a680228680e5e1172e
timeCreated: 1671618477

View File

@ -23,6 +23,8 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection; using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
using UnityEditor; using UnityEditor;
@ -111,14 +113,25 @@ namespace nadena.dev.modular_avatar.core.editor
}; };
} }
public static AnimatorController DeepCloneAnimator(AnimatorController controller) public static AnimatorController DeepCloneAnimator(RuntimeAnimatorController controller)
{ {
var merger = new AnimatorCombiner(); var merger = new AnimatorCombiner();
merger.AddController("", controller, null); switch (controller)
{
case AnimatorController ac:
merger.AddController("", ac, null);
break;
case AnimatorOverrideController oac:
merger.AddOverrideController("", oac, null);
break;
default:
throw new Exception("Unknown RuntimeAnimatorContoller type " + controller.GetType());
}
return merger.Finish(); return merger.Finish();
} }
public static AnimatorController ConvertAnimatorController(AnimatorOverrideController overrideController) public static AnimatorController ConvertAnimatorController(AnimatorOverrideController overrideController)
{ {
var merger = new AnimatorCombiner(); var merger = new AnimatorCombiner();
merger.AddOverrideController("", overrideController, null); merger.AddOverrideController("", overrideController, null);
@ -149,30 +162,68 @@ namespace nadena.dev.modular_avatar.core.editor
private const int MAX_EXPRESSION_TEXTURE_SIZE = 256; private const int MAX_EXPRESSION_TEXTURE_SIZE = 256;
public enum ValidateExpressionMenuIconResult public enum ValidateExpressionMenuIconResult
{ {
Success, Success,
TooLarge, TooLarge,
Uncompressed Uncompressed
} }
public static ValidateExpressionMenuIconResult ValidateExpressionMenuIcon(Texture2D icon) public static ValidateExpressionMenuIconResult ValidateExpressionMenuIcon(Texture2D icon)
{ {
string path = AssetDatabase.GetAssetPath(icon); string path = AssetDatabase.GetAssetPath(icon);
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter; TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer == null) return ValidateExpressionMenuIconResult.Success; if (importer == null) return ValidateExpressionMenuIconResult.Success;
TextureImporterPlatformSettings settings = importer.GetDefaultPlatformTextureSettings(); TextureImporterPlatformSettings settings = importer.GetDefaultPlatformTextureSettings();
// Max texture size; // Max texture size;
if ((icon.width > MAX_EXPRESSION_TEXTURE_SIZE || icon.height > MAX_EXPRESSION_TEXTURE_SIZE) && if ((icon.width > MAX_EXPRESSION_TEXTURE_SIZE || icon.height > MAX_EXPRESSION_TEXTURE_SIZE) &&
settings.maxTextureSize > MAX_EXPRESSION_TEXTURE_SIZE) return ValidateExpressionMenuIconResult.TooLarge; settings.maxTextureSize > MAX_EXPRESSION_TEXTURE_SIZE) return ValidateExpressionMenuIconResult.TooLarge;
// Compression // Compression
if (settings.textureCompression == TextureImporterCompression.Uncompressed) return ValidateExpressionMenuIconResult.Uncompressed; if (settings.textureCompression == TextureImporterCompression.Uncompressed)
return ValidateExpressionMenuIconResult.Uncompressed;
return ValidateExpressionMenuIconResult.Success; return ValidateExpressionMenuIconResult.Success;
} }
internal static IEnumerable<AnimatorState> States(AnimatorController ac)
{
HashSet<AnimatorStateMachine> visitedStateMachines = new HashSet<AnimatorStateMachine>();
Queue<AnimatorStateMachine> pending = new Queue<AnimatorStateMachine>();
foreach (var layer in ac.layers)
{
if (layer.stateMachine != null) pending.Enqueue(layer.stateMachine);
}
while (pending.Count > 0)
{
var next = pending.Dequeue();
if (visitedStateMachines.Contains(next)) continue;
visitedStateMachines.Add(next);
foreach (var child in next.stateMachines)
{
if (child.stateMachine != null) pending.Enqueue(child.stateMachine);
}
foreach (var state in next.states)
{
yield return state.state;
}
}
}
internal static bool IsProxyAnimation(Motion m)
{
var path = AssetDatabase.GetAssetPath(m);
// This is a fairly wide condition in order to deal with:
// 1. Future additions of proxy animations (so GUIDs are out)
// 2. Unitypackage based installations of the VRCSDK
// 3. VCC based installations of the VRCSDK
// 4. Very old VCC based installations of the VRCSDK where proxy animations were copied into Assets
return path.Contains("/AV3 Demo Assets/Animation/ProxyAnim/proxy");
}
} }
} }

View File

@ -89,14 +89,7 @@ namespace nadena.dev.modular_avatar.core.editor
var oscale = xform.lossyScale; var oscale = xform.lossyScale;
xform.localScale = new Vector3(oscale.x / pscale.x, oscale.y / pscale.y, oscale.z / pscale.z); xform.localScale = new Vector3(oscale.x / pscale.x, oscale.y / pscale.y, oscale.z / pscale.z);
var oldPath = RuntimeUtil.AvatarRootPath(target.gameObject);
target.transform.SetParent(proxy, true); target.transform.SetParent(proxy, true);
var newPath = RuntimeUtil.AvatarRootPath(target.gameObject);
PathMappings.Remap(oldPath, new PathMappings.MappingEntry()
{
path = newPath,
transformPath = newPath
});
didWork = true; didWork = true;
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "nadena.dev.modular-avatar", "name": "nadena.dev.modular-avatar",
"displayName": "Modular Avatar", "displayName": "Modular Avatar",
"version": "1.3.0", "version": "1.4.0-aaa-mergerefactor-0",
"unity": "2019.4", "unity": "2019.4",
"description": "A suite of tools for assembling your avatar out of reusable components", "description": "A suite of tools for assembling your avatar out of reusable components",
"author": { "author": {