Merge branch 'main' into basis-compatibility

This commit is contained in:
bd_ 2024-10-19 17:48:37 -07:00 committed by GitHub
commit 8a93053dcd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
70 changed files with 4567 additions and 318 deletions

View File

@ -19,7 +19,7 @@
"dependencies": {}
},
"nadena.dev.ndmf": {
"version": "1.5.0"
"version": "1.5.3"
}
}
}

View File

@ -122,7 +122,7 @@ jobs:
workingDirectory: docs-site~
- name: Purge cache
uses: nathanvaughn/actions-cloudflare-purge@cd4afdf666c2e6a6720048f27ac9cbdd664a673a
uses: nathanvaughn/actions-cloudflare-purge@992cc4e96422fb8ddf077281678373fe41e7736c
continue-on-error: true
with:
cf_zone: ${{ secrets.CF_ZONE_ID }}

View File

@ -116,6 +116,7 @@ jobs:
with:
repos: |
https://vpm.nadena.dev/vpm-prerelease.json
https://vrchat.github.io/packages/index.json?download
- if: ${{ steps.setup.outputs.should_test == 'true' }}
name: "Debug: List project contents"

View File

@ -53,7 +53,21 @@ namespace nadena.dev.modular_avatar.animation
set
{
_originalClip = value;
IsProxyAnimation = value != null && Util.IsProxyAnimation(value);
var baseClip = ObjectRegistry.GetReference(value)?.Object as AnimationClip;
IsProxyAnimation = false;
if (value != null && Util.IsProxyAnimation(value))
{
IsProxyAnimation = true;
}
else if (baseClip != null && Util.IsProxyAnimation(baseClip))
{
// RenameParametersPass replaces proxy clips outside of the purview of the animation database,
// so trace this using ObjectRegistry and correct the reference.
IsProxyAnimation = true;
_originalClip = baseClip;
}
}
}

View File

@ -573,6 +573,8 @@ namespace nadena.dev.modular_avatar.animation
private AnimatorStateMachine mapStateMachine(string basePath, AnimatorStateMachine layerStateMachine)
{
if (layerStateMachine == null) return null;
var cacheKey = new KeyValuePair<string, AnimatorStateMachine>(basePath, layerStateMachine);
if (_stateMachines.TryGetValue(cacheKey, out var asm))

View File

@ -1,10 +1,12 @@
#if MA_VRCSDK3_AVATARS
using System.Linq;
using nadena.dev.modular_avatar.core.editor;
using nadena.dev.ndmf;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using BuildContext = nadena.dev.ndmf.BuildContext;
namespace nadena.dev.modular_avatar.animation
{
@ -24,11 +26,16 @@ namespace nadena.dev.modular_avatar.animation
if (fx == null) return;
var nullMotion = new AnimationClip();
nullMotion.name = "NullMotion";
var blendTree = new BlendTree();
blendTree.blendType = BlendTreeType.Direct;
blendTree.useAutomaticThresholds = false;
blendTree.children = asc.BoundReadableProperties.Select(GenerateDelayChild).ToArray();
blendTree.children = asc.BoundReadableProperties
.Select(prop => GenerateDelayChild(nullMotion, prop))
.ToArray();
var asm = new AnimatorStateMachine();
var state = new AnimatorState();
@ -53,9 +60,24 @@ namespace nadena.dev.modular_avatar.animation
defaultWeight = 1,
blendingMode = AnimatorLayerBlendingMode.Override
}).ToArray();
// Ensure the initial state of readable props matches the actual state of the gameobject
var parameters = fx.parameters;
var paramToIndex = parameters.Select((p, i) => (p, i)).ToDictionary(x => x.p.name, x => x.i);
foreach (var (binding, prop) in asc.BoundReadableProperties)
{
var obj = asc.PathMappings.PathToObject(binding.path);
if (obj != null && paramToIndex.TryGetValue(prop, out var index))
{
parameters[index].defaultFloat = obj.activeSelf ? 1 : 0;
}
}
fx.parameters = parameters;
}
private ChildMotion GenerateDelayChild((EditorCurveBinding, string) binding)
private ChildMotion GenerateDelayChild(Motion nullMotion, (EditorCurveBinding, string) binding)
{
var ecb = binding.Item1;
var prop = binding.Item2;
@ -65,10 +87,40 @@ namespace nadena.dev.modular_avatar.animation
curve.AddKey(0, 1);
AnimationUtility.SetEditorCurve(motion, ecb, curve);
// Occasionally, we'll have a very small value pop up, probably due to FP errors.
// To correct for this, instead of directly using the property in the direct blend tree,
// we'll use a 1D blend tree to give ourselves a buffer.
var bufferBlendTree = new BlendTree();
bufferBlendTree.blendType = BlendTreeType.Simple1D;
bufferBlendTree.useAutomaticThresholds = false;
bufferBlendTree.blendParameter = prop;
bufferBlendTree.children = new[]
{
new ChildMotion
{
motion = nullMotion,
timeScale = 1,
threshold = 0
},
new ChildMotion
{
motion = nullMotion,
timeScale = 1,
threshold = 0.01f
},
new ChildMotion
{
motion = motion,
timeScale = 1,
threshold = 1
}
};
return new ChildMotion
{
motion = motion,
directBlendParameter = prop,
motion = bufferBlendTree,
directBlendParameter = MergeBlendTreePass.ALWAYS_ONE,
timeScale = 1
};
}

View File

@ -11,6 +11,8 @@ namespace nadena.dev.modular_avatar.core.editor.HarmonyPatches
{
internal class PatchLoader
{
private const string HarmonyId = "nadena.dev.modular_avatar";
private static readonly Action<Harmony>[] patches = new Action<Harmony>[]
{
//HierarchyViewPatches.Patch,
@ -19,7 +21,7 @@ namespace nadena.dev.modular_avatar.core.editor.HarmonyPatches
[InitializeOnLoadMethod]
static void ApplyPatches()
{
var harmony = new Harmony("nadena.dev.modular_avatar");
var harmony = new Harmony(HarmonyId);
foreach (var patch in patches)
{
@ -33,7 +35,7 @@ namespace nadena.dev.modular_avatar.core.editor.HarmonyPatches
}
}
AssemblyReloadEvents.beforeAssemblyReload += () => { harmony.UnpatchAll(); };
AssemblyReloadEvents.beforeAssemblyReload += () => { harmony.UnpatchAll(HarmonyId); };
}
}
}

View File

@ -0,0 +1,106 @@
using System;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
namespace nadena.dev.modular_avatar.core.editor
{
internal abstract class DragAndDropManipulator<T> : PointerManipulator where T : Component, IHaveObjReferences
{
private const string DragActiveClassName = "drop-area--drag-active";
public T TargetComponent { get; set; }
protected virtual bool AllowKnownObjects => true;
private Transform _avatarRoot;
private GameObject[] _draggingObjects = Array.Empty<GameObject>();
public DragAndDropManipulator(VisualElement targetElement, T targetComponent)
{
target = targetElement;
TargetComponent = targetComponent;
}
protected sealed override void RegisterCallbacksOnTarget()
{
target.RegisterCallback<DragEnterEvent>(OnDragEnter);
target.RegisterCallback<DragLeaveEvent>(OnDragLeave);
target.RegisterCallback<DragExitedEvent>(OnDragExited);
target.RegisterCallback<DragUpdatedEvent>(OnDragUpdated);
target.RegisterCallback<DragPerformEvent>(OnDragPerform);
}
protected sealed override void UnregisterCallbacksFromTarget()
{
target.UnregisterCallback<DragEnterEvent>(OnDragEnter);
target.UnregisterCallback<DragLeaveEvent>(OnDragLeave);
target.UnregisterCallback<DragExitedEvent>(OnDragExited);
target.UnregisterCallback<DragUpdatedEvent>(OnDragUpdated);
target.UnregisterCallback<DragPerformEvent>(OnDragPerform);
}
private void OnDragEnter(DragEnterEvent _)
{
if (TargetComponent == null) return;
_avatarRoot = RuntimeUtil.FindAvatarTransformInParents(TargetComponent.transform);
if (_avatarRoot == null) return;
var knownObjects = TargetComponent.GetObjectReferences().Select(x => x.Get(TargetComponent)).ToHashSet();
_draggingObjects = DragAndDrop.objectReferences.OfType<GameObject>()
.Where(x => AllowKnownObjects || !knownObjects.Contains(x))
.Where(x => RuntimeUtil.FindAvatarTransformInParents(x.transform) == _avatarRoot)
.Where(FilterGameObject)
.ToArray();
if (_draggingObjects.Length == 0) return;
target.AddToClassList(DragActiveClassName);
}
private void OnDragLeave(DragLeaveEvent _)
{
_draggingObjects = Array.Empty<GameObject>();
target.RemoveFromClassList(DragActiveClassName);
}
private void OnDragExited(DragExitedEvent _)
{
_draggingObjects = Array.Empty<GameObject>();
target.RemoveFromClassList(DragActiveClassName);
}
private void OnDragUpdated(DragUpdatedEvent _)
{
if (TargetComponent == null) return;
if (_avatarRoot == null) return;
if (_draggingObjects.Length == 0) return;
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
}
private void OnDragPerform(DragPerformEvent _)
{
if (TargetComponent == null) return;
if (_avatarRoot == null) return;
if (_draggingObjects.Length == 0) return;
AddObjectReferences(_draggingObjects
.Select(x =>
{
var reference = new AvatarObjectReference();
reference.Set(x);
return reference;
})
.ToArray());
}
protected virtual bool FilterGameObject(GameObject obj)
{
return true;
}
protected abstract void AddObjectReferences(AvatarObjectReference[] references);
}
}

View File

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

View File

@ -16,6 +16,7 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
[SerializeField] private StyleSheet uss;
[SerializeField] private VisualTreeAsset uxml;
private DragAndDropManipulator _dragAndDropManipulator;
protected override void OnInnerInspectorGUI()
{
@ -37,7 +38,44 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
listView.showBoundCollectionSize = false;
listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight;
_dragAndDropManipulator = new DragAndDropManipulator(root.Q("group-box"), target as ModularAvatarMaterialSetter);
return root;
}
private void OnEnable()
{
if (_dragAndDropManipulator != null)
_dragAndDropManipulator.TargetComponent = target as ModularAvatarMaterialSetter;
}
private class DragAndDropManipulator : DragAndDropManipulator<ModularAvatarMaterialSetter>
{
public DragAndDropManipulator(VisualElement targetElement, ModularAvatarMaterialSetter targetComponent)
: base(targetElement, targetComponent) { }
protected override bool FilterGameObject(GameObject obj)
{
if (obj.TryGetComponent<Renderer>(out var renderer))
{
return renderer.sharedMaterials.Length > 0;
}
return false;
}
protected override void AddObjectReferences(AvatarObjectReference[] references)
{
Undo.RecordObject(TargetComponent, "Add Material Switch Objects");
foreach (var reference in references)
{
var materialSwitchObject = new MaterialSwitchObject { Object = reference, MaterialIndex = 0 };
TargetComponent.Objects.Add(materialSwitchObject);
}
EditorUtility.SetDirty(TargetComponent);
PrefabUtility.RecordPrefabInstancePropertyModifications(TargetComponent);
}
}
}
}

View File

@ -62,3 +62,13 @@
#f-material {
flex-grow: 1;
}
.drop-area--drag-active {
background-color: rgba(0, 127, 255, 0.2);
}
.drop-area--drag-active .unity-scroll-view,
.drop-area--drag-active .unity-list-view__footer,
.drop-area--drag-active .unity-list-view__reorderable-item {
background-color: rgba(0, 0, 0, 0.0);
}

View File

@ -368,7 +368,7 @@ namespace nadena.dev.modular_avatar.core.editor
serializedObject.ApplyModifiedProperties();
Localization.ShowLanguageUI();
ShowLanguageUI();
}
private string ObjectHierarchyOrder(Component arg)
@ -415,6 +415,9 @@ namespace nadena.dev.modular_avatar.core.editor
var group = installer.gameObject.AddComponent<ModularAvatarMenuGroup>();
var menuRoot = new GameObject();
menuRoot.name = "Menu";
group.targetObject = menuRoot;
Undo.RegisterCreatedObjectUndo(menuRoot, "Extract menu");
menuRoot.transform.SetParent(group.transform, false);
foreach (var control in menu.controls)

View File

@ -301,10 +301,9 @@ namespace nadena.dev.modular_avatar.core.editor
EditorGUILayout.BeginVertical();
if (_type.hasMultipleDifferentValues) return;
VRCExpressionsMenu.Control.ControlType type =
(VRCExpressionsMenu.Control.ControlType) Enum
.GetValues(typeof(VRCExpressionsMenu.Control.ControlType))
.GetValue(_type.enumValueIndex);
var controlTypeArray = Enum.GetValues(typeof(VRCExpressionsMenu.Control.ControlType));
var index = Math.Clamp(_type.enumValueIndex, 0, controlTypeArray.Length - 1);
var type = (VRCExpressionsMenu.Control.ControlType)controlTypeArray.GetValue(index);
switch (type)
{
@ -646,6 +645,9 @@ namespace nadena.dev.modular_avatar.core.editor
var myMenuItem = serializedObject.targetObject as ModularAvatarMenuItem;
if (myMenuItem == null) return null;
var avatarRoot = RuntimeUtil.FindAvatarInParents(myMenuItem.gameObject.transform);
if (avatarRoot == null) return null;
var myParameterName = myMenuItem.Control.parameter.name;
if (string.IsNullOrEmpty(myParameterName)) return new List<ModularAvatarMenuItem>();
@ -653,7 +655,6 @@ namespace nadena.dev.modular_avatar.core.editor
if (myMappings.TryGetValue((ParameterNamespace.Animator, myParameterName), out var myReplacement))
myParameterName = myReplacement.ParameterName;
var avatarRoot = RuntimeUtil.FindAvatarInParents(myMenuItem.gameObject.transform);
var siblings = new List<ModularAvatarMenuItem>();
foreach (var otherMenuItem in avatarRoot.GetComponentsInChildren<ModularAvatarMenuItem>(true))

View File

@ -84,6 +84,7 @@ namespace nadena.dev.modular_avatar.core.editor
}
private bool posResetOptionFoldout = false;
private bool posReset_convertATPose = true;
private bool posReset_adjustRotation = false;
private bool posReset_adjustScale = false;
private bool posReset_heuristicRootScale = true;
@ -134,14 +135,17 @@ namespace nadena.dev.modular_avatar.core.editor
MessageType.Info
);
posReset_heuristicRootScale = EditorGUILayout.ToggleLeft(
G("merge_armature.reset_pos.heuristic_scale"),
posReset_heuristicRootScale);
posReset_convertATPose = EditorGUILayout.ToggleLeft(
G("merge_armature.reset_pos.convert_atpose"),
posReset_convertATPose);
posReset_adjustRotation = EditorGUILayout.ToggleLeft(
G("merge_armature.reset_pos.adjust_rotation"),
posReset_adjustRotation);
posReset_adjustScale = EditorGUILayout.ToggleLeft(G("merge_armature.reset_pos.adjust_scale"),
posReset_adjustScale);
posReset_heuristicRootScale = EditorGUILayout.ToggleLeft(
G("merge_armature.reset_pos.heuristic_scale"),
posReset_heuristicRootScale);
if (GUILayout.Button(G("merge_armature.reset_pos.execute")))
{
@ -188,6 +192,11 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
if (posReset_convertATPose)
{
SetupOutfit.FixAPose(RuntimeUtil.FindAvatarTransformInParents(mergeTarget.transform).gameObject, mama.transform, false);
}
if (posReset_heuristicRootScale && !suppressRootScale)
{
AdjustRootScale();
@ -279,4 +288,4 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
}
}
}

View File

@ -35,14 +35,12 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
ROSimulatorButton.BindRefObject(root, target);
var listView = root.Q<ListView>("Shapes");
_dragAndDropManipulator = new DragAndDropManipulator(listView)
{
TargetComponent = target as ModularAvatarObjectToggle
};
listView.showBoundCollectionSize = false;
listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight;
_dragAndDropManipulator = new DragAndDropManipulator(root.Q("group-box"), target as ModularAvatarObjectToggle);
return root;
}
@ -52,91 +50,25 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
_dragAndDropManipulator.TargetComponent = target as ModularAvatarObjectToggle;
}
private class DragAndDropManipulator : PointerManipulator
private class DragAndDropManipulator : DragAndDropManipulator<ModularAvatarObjectToggle>
{
public ModularAvatarObjectToggle TargetComponent;
private GameObject[] _nowDragging = Array.Empty<GameObject>();
private Transform _avatarRoot;
public DragAndDropManipulator(VisualElement targetElement, ModularAvatarObjectToggle targetComponent)
: base(targetElement, targetComponent) { }
private readonly VisualElement _parentElem;
protected override bool AllowKnownObjects => false;
public DragAndDropManipulator(VisualElement target)
protected override void AddObjectReferences(AvatarObjectReference[] references)
{
this.target = target;
_parentElem = target.parent;
}
Undo.RecordObject(TargetComponent, "Add Toggled Objects");
protected override void RegisterCallbacksOnTarget()
{
target.RegisterCallback<DragEnterEvent>(OnDragEnter);
target.RegisterCallback<DragLeaveEvent>(OnDragLeave);
target.RegisterCallback<DragPerformEvent>(OnDragPerform);
target.RegisterCallback<DragUpdatedEvent>(OnDragUpdate);
}
protected override void UnregisterCallbacksFromTarget()
{
target.UnregisterCallback<DragEnterEvent>(OnDragEnter);
target.UnregisterCallback<DragLeaveEvent>(OnDragLeave);
target.UnregisterCallback<DragPerformEvent>(OnDragPerform);
target.RegisterCallback<DragUpdatedEvent>(OnDragUpdate);
}
private void OnDragEnter(DragEnterEvent evt)
{
if (TargetComponent == null) return;
_avatarRoot = RuntimeUtil.FindAvatarTransformInParents(TargetComponent.transform);
if (_avatarRoot == null) return;
_nowDragging = DragAndDrop.objectReferences.OfType<GameObject>()
.Where(o => RuntimeUtil.FindAvatarTransformInParents(o.transform) == _avatarRoot)
.ToArray();
if (_nowDragging.Length > 0)
foreach (var reference in references)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Link;
_parentElem.AddToClassList("drop-area--drag-active");
}
}
private void OnDragUpdate(DragUpdatedEvent _)
{
if (_nowDragging.Length > 0) DragAndDrop.visualMode = DragAndDropVisualMode.Link;
}
private void OnDragLeave(DragLeaveEvent evt)
{
_nowDragging = Array.Empty<GameObject>();
_parentElem.RemoveFromClassList("drop-area--drag-active");
}
private void OnDragPerform(DragPerformEvent evt)
{
if (_nowDragging.Length > 0 && TargetComponent != null && _avatarRoot != null)
{
var knownObjs = TargetComponent.Objects.Select(o => o.Object.Get(TargetComponent)).ToHashSet();
Undo.RecordObject(TargetComponent, "Add Toggled Objects");
foreach (var obj in _nowDragging)
{
if (knownObjs.Contains(obj)) continue;
var aor = new AvatarObjectReference();
aor.Set(obj);
var toggledObject = new ToggledObject { Object = aor, Active = !obj.activeSelf };
TargetComponent.Objects.Add(toggledObject);
}
EditorUtility.SetDirty(TargetComponent);
PrefabUtility.RecordPrefabInstancePropertyModifications(TargetComponent);
var toggledObject = new ToggledObject { Object = reference, Active = !reference.Get(TargetComponent).activeSelf };
TargetComponent.Objects.Add(toggledObject);
}
_nowDragging = Array.Empty<GameObject>();
_parentElem.RemoveFromClassList("drop-area--drag-active");
EditorUtility.SetDirty(TargetComponent);
PrefabUtility.RecordPrefabInstancePropertyModifications(TargetComponent);
}
}
}

View File

@ -51,6 +51,12 @@
width: 60px;
}
.drop-area--drag-active > ListView ScrollView {
background-color: rgba(0, 255, 255, 0.1);
.drop-area--drag-active {
background-color: rgba(0, 127, 255, 0.2);
}
.drop-area--drag-active .unity-scroll-view,
.drop-area--drag-active .unity-list-view__footer,
.drop-area--drag-active .unity-list-view__reorderable-item {
background-color: rgba(0, 0, 0, 0.0);
}

View File

@ -20,7 +20,8 @@ namespace nadena.dev.modular_avatar.core.editor
private readonly DropdownField _boolField;
private ParameterSyncType _syncType;
private bool _hasInitialBinding;
public DefaultValueField()
{
// Hidden binding elements
@ -57,28 +58,39 @@ namespace nadena.dev.modular_avatar.core.editor
{
_numberField.style.display = DisplayStyle.Flex;
_boolField.style.display = DisplayStyle.None;
OnUpdateNumberValue(_numberField.value);
OnUpdateNumberValue(_numberField.value, true);
}
else
{
_numberField.style.display = DisplayStyle.None;
_boolField.style.display = DisplayStyle.Flex;
OnUpdateBoolValue(_boolField.value);
OnUpdateBoolValue(_boolField.value, true);
}
}
private void OnUpdateNumberValue(string value)
private void OnUpdateNumberValue(string value, bool implicitUpdate = false)
{
// Upon initial creation, sometimes the OnUpdateSyncType fires before we receive the initial value event.
// In this case, suppress the update to avoid losing data.
if (implicitUpdate && !_hasInitialBinding) return;
var theValue = _defaultValueField.value;
if (string.IsNullOrWhiteSpace(value))
{
_defaultValueField.value = 0;
if (!implicitUpdate)
{
_defaultValueField.value = 0;
}
theValue = _defaultValueField.value;
_hasExplicitDefaultValueField.value = false;
}
else if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsed)
&& !float.IsNaN(parsed)
&& !float.IsInfinity(parsed))
{
_defaultValueField.value = _syncType switch
theValue = _defaultValueField.value = _syncType switch
{
ParameterSyncType.Int => Mathf.FloorToInt(Mathf.Clamp(parsed, 0, 255)),
ParameterSyncType.Float => Mathf.Clamp(parsed, -1, 1),
@ -88,11 +100,15 @@ namespace nadena.dev.modular_avatar.core.editor
_hasExplicitDefaultValueField.value = true;
}
UpdateVisibleField(_defaultValueField.value, _hasExplicitDefaultValueField.value);
UpdateVisibleField(theValue, _hasExplicitDefaultValueField.value);
}
private void OnUpdateBoolValue(string value)
private void OnUpdateBoolValue(string value, bool implicitUpdate = false)
{
// Upon initial creation, sometimes the OnUpdateSyncType fires before we receive the initial value event.
// In this case, suppress the update to avoid losing data.
if (implicitUpdate && !_hasInitialBinding) return;
_defaultValueField.value = value == V_True ? 1 : 0;
_hasExplicitDefaultValueField.value = value != V_None;
@ -101,6 +117,8 @@ namespace nadena.dev.modular_avatar.core.editor
private void UpdateVisibleField(float value, bool hasExplicitValue)
{
_hasInitialBinding = true;
if (hasExplicitValue || Mathf.Abs(value) > 0.0000001)
{
_numberField.SetValueWithoutNotify(value.ToString(CultureInfo.InvariantCulture));

View File

@ -19,6 +19,7 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
[SerializeField] private StyleSheet uss;
[SerializeField] private VisualTreeAsset uxml;
private DragAndDropManipulator _dragAndDropManipulator;
private BlendshapeSelectWindow _window;
protected override void OnInnerInspectorGUI()
@ -41,6 +42,8 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
listView.showBoundCollectionSize = false;
listView.virtualizationMethod = CollectionVirtualizationMethod.DynamicHeight;
_dragAndDropManipulator = new DragAndDropManipulator(root.Q("group-box"), target as ModularAvatarShapeChanger);
// The Add button callback isn't exposed publicly for some reason...
var field_addButton = typeof(BaseListView).GetField("m_AddButton", NonPublic | Instance);
var addButton = (Button)field_addButton.GetValue(listView);
@ -50,6 +53,41 @@ namespace nadena.dev.modular_avatar.core.editor.ShapeChanger
return root;
}
private void OnEnable()
{
if (_dragAndDropManipulator != null)
_dragAndDropManipulator.TargetComponent = target as ModularAvatarShapeChanger;
}
private class DragAndDropManipulator : DragAndDropManipulator<ModularAvatarShapeChanger>
{
public DragAndDropManipulator(VisualElement targetElement, ModularAvatarShapeChanger targetComponent)
: base(targetElement, targetComponent) { }
protected override bool FilterGameObject(GameObject obj)
{
if (obj.TryGetComponent<SkinnedMeshRenderer>(out var smr))
{
return smr.sharedMesh != null && smr.sharedMesh.blendShapeCount > 0;
}
return false;
}
protected override void AddObjectReferences(AvatarObjectReference[] references)
{
Undo.RecordObject(TargetComponent, "Add Changed Shapes");
foreach (var reference in references)
{
var changedShape = new ChangedShape { Object = reference, ShapeName = string.Empty };
TargetComponent.Shapes.Add(changedShape);
}
EditorUtility.SetDirty(TargetComponent);
PrefabUtility.RecordPrefabInstancePropertyModifications(TargetComponent);
}
}
private void OnDisable()
{
if (_window != null) DestroyImmediate(_window);

View File

@ -68,3 +68,13 @@
.change-type-delete #f-value-delete {
display: flex;
}
.drop-area--drag-active {
background-color: rgba(0, 127, 255, 0.2);
}
.drop-area--drag-active .unity-scroll-view,
.drop-area--drag-active .unity-list-view__footer,
.drop-area--drag-active .unity-list-view__reorderable-item {
background-color: rgba(0, 0, 0, 0.0);
}

View File

@ -86,6 +86,7 @@
"merge_armature.lockmode.bidirectional.body": "The base armature and the merged armature will always have the same position. This is useful when creating animations that are meant to target the base armature. In order to activate this, your armatures must already be in the exact same position.",
"merge_armature.reset_pos": "Reset position to base avatar",
"merge_armature.reset_pos.info": "This command will force the position of all bones in the outfit to match that of the base avatar. This can be helpful as a starting point for installing outfits not set up for your current avatar.",
"merge_armature.reset_pos.convert_atpose": "Convert A-Pose/T-Pose to match base avatar",
"merge_armature.reset_pos.adjust_rotation": "Also set rotation to base avatar",
"merge_armature.reset_pos.adjust_scale": "Also set local scale to base avatar",
"merge_armature.reset_pos.execute": "Do it!",
@ -149,6 +150,8 @@
"error.rename_params.default_value_conflict:hint": "To avoid unpredictable behavior, leave the default value field blank in all but on MA Parameters component. If multiple values are present, Modular Avatar will select the first default value specified in the hierarchy order.",
"error.replace_object.null_target": "[MA-0008] No target specified",
"error.replace_object.null_target:hint": "Replace object needs a target object to replace. Try setting one.",
"error.replace_object.replacing_replacement": "[MA-0009] The same target object cannot be specified in multiple Replace Object components",
"error.replace_object.parent_of_target": "[MA-0010] The target object cannot be a parent of this object",
"validation.blendshape_sync.no_local_renderer": "[MA-1000] No renderer found on this object",
"validation.blendshape_sync.no_local_renderer:hint": "Blendshape Sync acts on a Skinned Mesh Renderer on the same GameObject. Did you attach it to the right object?",
"validation.blendshape_sync.no_local_mesh": "[MA-1001] No mesh found on the renderer on this object",

View File

@ -82,6 +82,7 @@
"merge_armature.lockmode.bidirectional.body": "アバターと統合されるアーマチュアは常に同じ位置になります。元のアバターを操作するアニメーションを作る時に便利かもしれません。有効にするためには、統合されるアーマチュアの位置を統合先と同じにしておく必要があります。",
"merge_armature.reset_pos": "位置を元アバターに合わせてリセット",
"merge_armature.reset_pos.info": "衣装のボーンの位置をアバターのボーンの位置に合わせます。非対応衣装を導入する際、アバウトに位置を合わせるのに便利です。",
"merge_armature.reset_pos.convert_atpose": "Aポーズ/Tポーズを合わせる",
"merge_armature.reset_pos.adjust_rotation": "回転も合わせる",
"merge_armature.reset_pos.adjust_scale": "スケールも合わせる",
"merge_armature.reset_pos.execute": "実行",
@ -145,6 +146,8 @@
"error.rename_params.default_value_conflict:hint": "予測不可能な動作を避けるため、MA Parametersコンポーネントの初期値フィールドはパラメーター名毎に1つだけしか指定しないようにし、他のコンポーネントでは空白のままにしてください。複数の値が存在する場合、Modular Avatarは階層順で最初に指定された初期値を採用します。",
"error.replace_object.null_target": "[MA-0008] 置き換え先が指定されていません",
"error.replace_object.null_target:hint": "Replace Objectは置き換え先のオブジェクトを指定する必要があります。",
"error.replace_object.replacing_replacement": "[MA-0009] 複数のReplace Objectコンポーネントで、同じ置き換え先を指定できません",
"error.replace_object.parent_of_target": "[MA-0010] このオブジェクトの親を置き換え先に指定できません",
"validation.blendshape_sync.no_local_renderer": "[MA-1000] このオブジェクトにはSkinned Mesh Rendererがありません。",
"validation.blendshape_sync.no_local_renderer:hint": "Blendshape Syncは同じGameObject上のSkinned Mesh Rendererに作用します。コンポーネントが正しいオブジェクトに追加されているか確認してください。",
"validation.blendshape_sync.no_local_mesh": "[MA-1001] このオブジェクトにはSkinned Mesh Rendererがありますが、メッシュがありません。",

View File

@ -251,7 +251,7 @@
"reactive_object.inverse": "反轉條件",
"reactive_object.material-setter.set-to": "將材質設定為:",
"menuitem.misc.add_toggle": "新增開關",
"ro_sim.open_debugger_button": "開啟響應除錯工具",
"ro_sim.open_debugger_button": "開啟 Reaction 除錯工具",
"ro_sim.window.title": "MA 響應除錯工具",
"ro_sim.header.inspecting": "檢視物件",
"ro_sim.header.clear_overrides": "清除所有覆寫",

View File

@ -119,9 +119,11 @@ namespace nadena.dev.modular_avatar.core.editor
internal static VRCExpressionsMenu.Control CloneControl(VRCExpressionsMenu.Control c)
{
var type = c.type != 0 ? c.type : VRCExpressionsMenu.Control.ControlType.Button;
return new VRCExpressionsMenu.Control()
{
type = c.type,
type = type,
name = c.name,
icon = c.icon,
parameter = new VRCExpressionsMenu.Control.Parameter() { name = c.parameter?.name },

View File

@ -246,6 +246,18 @@ namespace nadena.dev.modular_avatar.core.editor
var stateMachineQueue = new Queue<AnimatorStateMachine>();
foreach (var layer in controller.layers)
{
// Special case: A layer with a single state, which contains a blend tree, is ignored for WD analysis.
// This is because WD ON blend trees have different behavior from most WD ON states, and can be safely
// used in a WD OFF animator.
if (layer.stateMachine.states.Length == 1
&& layer.stateMachine.states[0].state.motion is BlendTree
&& layer.stateMachine.stateMachines.Length == 0
)
{
continue;
}
stateMachineQueue.Enqueue(layer.stateMachine);
}

View File

@ -60,7 +60,13 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
#if MA_VRCSDK3_AVATARS
seq.Run("Shape Changer", ctx => new ReactiveObjectPass(ctx).Execute())
.PreviewingWith(new ShapeChangerPreview(), new ObjectSwitcherPreview(), new MaterialSetterPreview());
// TODO: We currently run this above MergeArmaturePlugin, because Merge Armature might destroy
// game objects which contain Menu Installers. It'd probably be better however to teach Merge Armature
// to retain those objects? maybe?
seq.Run(MenuInstallPluginPass.Instance);
#endif
seq.Run(MergeArmaturePluginPass.Instance);
seq.Run(BoneProxyPluginPass.Instance);
#if MA_VRCSDK3_AVATARS
@ -77,7 +83,6 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
seq.Run(ConstraintConverterPass.Instance);
});
#if MA_VRCSDK3_AVATARS
seq.Run(MenuInstallPluginPass.Instance);
seq.Run(PhysbonesBlockerPluginPass.Instance);
seq.Run("Fixup Expressions Menu", ctx =>
{

View File

@ -1,14 +1,14 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor
{
internal class AnimatedProperty
{
public TargetProp TargetProp { get; }
public string ControlParam { get; set; }
public bool alwaysDeleted;
public object currentState;
// Objects which trigger deletion of this shape key.
@ -25,5 +25,30 @@ namespace nadena.dev.modular_avatar.core.editor
TargetProp = key;
this.currentState = currentState;
}
protected bool Equals(AnimatedProperty other)
{
return Equals(currentState, other.currentState) && actionGroups.SequenceEqual(other.actionGroups) &&
TargetProp.Equals(other.TargetProp);
}
public override bool Equals(object obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((AnimatedProperty)obj);
}
public override int GetHashCode()
{
var actionGroupHash = 0;
foreach (var ag in actionGroups)
{
actionGroupHash = HashCode.Combine(actionGroupHash, ag);
}
return HashCode.Combine(currentState, actionGroupHash, TargetProp);
}
}
}

View File

@ -1,11 +1,13 @@
using UnityEngine;
using System;
using UnityEngine;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor
{
internal class ControlCondition
{
public string Parameter;
public UnityEngine.Object DebugReference;
public Object DebugReference;
public string DebugName;
public bool IsConstant;
@ -14,5 +16,31 @@ namespace nadena.dev.modular_avatar.core.editor
public bool IsConstantActive => InitiallyActive && IsConstant;
public GameObject ReferenceObject;
protected bool Equals(ControlCondition other)
{
return Parameter == other.Parameter
&& Equals(DebugReference, other.DebugReference)
&& DebugName == other.DebugName
&& IsConstant == other.IsConstant
&& ParameterValueLo.Equals(other.ParameterValueLo)
&& ParameterValueHi.Equals(other.ParameterValueHi)
&& InitialValue.Equals(other.InitialValue)
&& Equals(ReferenceObject, other.ReferenceObject);
}
public override bool Equals(object obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((ControlCondition)obj);
}
public override int GetHashCode()
{
return HashCode.Combine(Parameter, DebugReference, DebugName, IsConstant, ParameterValueLo,
ParameterValueHi, InitialValue, ReferenceObject);
}
}
}

View File

@ -1,7 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using nadena.dev.modular_avatar.animation;
using UnityEngine;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor
{
@ -9,8 +10,8 @@ namespace nadena.dev.modular_avatar.core.editor
{
public ReactionRule(TargetProp key, float value)
: this(key, (object)value) { }
public ReactionRule(TargetProp key, UnityEngine.Object value)
public ReactionRule(TargetProp key, Object value)
: this(key, (object)value) { }
private ReactionRule(TargetProp key, object value)
@ -31,13 +32,15 @@ namespace nadena.dev.modular_avatar.core.editor
public bool InitiallyActive =>
((ControllingConditions.Count == 0) || ControllingConditions.All(c => c.InitiallyActive)) ^ Inverted;
public bool IsDelete;
public bool Inverted;
public bool IsConstant => ControllingConditions.Count == 0 || ControllingConditions.All(c => c.IsConstant);
public bool IsConstantOn => IsConstant && InitiallyActive;
public bool IsConstant => ControllingConditions.Count == 0
|| ControllingConditions.All(c => c.IsConstant)
|| ControllingConditions.Any(c => c.IsConstant && !c.InitiallyActive);
public bool IsConstantActive => IsConstant && InitiallyActive ^ Inverted;
public override string ToString()
{
return $"AGK: {TargetProp}={Value}";
@ -55,9 +58,36 @@ namespace nadena.dev.modular_avatar.core.editor
}
else return false;
if (!ControllingConditions.SequenceEqual(other.ControllingConditions)) return false;
if (IsDelete || other.IsDelete) return false;
return true;
}
protected bool Equals(ReactionRule other)
{
return TargetProp.Equals(other.TargetProp)
&& Equals(Value, other.Value)
&& Equals(ControllingObject, other.ControllingObject)
&& ControllingConditions.SequenceEqual(other.ControllingConditions)
&& Inverted == other.Inverted;
}
public override bool Equals(object obj)
{
if (obj is null) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((ReactionRule)obj);
}
public override int GetHashCode()
{
var ccHash = 0;
foreach (var cc in ControllingConditions)
{
ccHash = HashCode.Combine(ccHash, cc);
}
return HashCode.Combine(TargetProp, Value, ControllingObject, ccHash, Inverted);
}
}
}

View File

@ -1,5 +1,6 @@
#if MA_VRCSDK3_AVATARS
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf.preview;
using UnityEngine;
@ -39,6 +40,77 @@ namespace nadena.dev.modular_avatar.core.editor
return param;
}
}
private readonly Dictionary<(SkinnedMeshRenderer, string), HashSet<(SkinnedMeshRenderer, string)>>
_blendshapeSyncMappings = new();
private void LocateBlendshapeSyncs(GameObject root)
{
var components = _computeContext.GetComponentsInChildren<ModularAvatarBlendshapeSync>(root, true);
foreach (var bss in components)
{
var localMesh = _computeContext.GetComponent<SkinnedMeshRenderer>(bss.gameObject);
if (localMesh == null) continue;
foreach (var entry in _computeContext.Observe(bss, bss_ => bss_.Bindings.ToImmutableList(),
Enumerable.SequenceEqual))
{
var src = entry.ReferenceMesh.Get(bss);
if (src == null) continue;
var srcMesh = _computeContext.GetComponent<SkinnedMeshRenderer>(src);
var localBlendshape = entry.LocalBlendshape;
if (string.IsNullOrWhiteSpace(localBlendshape))
{
localBlendshape = entry.Blendshape;
}
var srcBinding = (srcMesh, entry.Blendshape);
var dstBinding = (localMesh, localBlendshape);
if (!_blendshapeSyncMappings.TryGetValue(srcBinding, out var dstSet))
{
dstSet = new HashSet<(SkinnedMeshRenderer, string)>();
_blendshapeSyncMappings[srcBinding] = dstSet;
}
dstSet.Add(dstBinding);
}
}
// For recursive blendshape syncs, we need to precompute the full set of affected blendshapes.
foreach (var (src, dsts) in _blendshapeSyncMappings)
{
var visited = new HashSet<(SkinnedMeshRenderer, string)>();
foreach (var item in Visit(src, visited).ToList())
{
dsts.Add(item);
}
}
IEnumerable<(SkinnedMeshRenderer, string)> Visit(
(SkinnedMeshRenderer, string) key,
HashSet<(SkinnedMeshRenderer, string)> visited
)
{
if (!visited.Add(key)) yield break;
if (_blendshapeSyncMappings.TryGetValue(key, out var children))
{
foreach (var child in children)
{
foreach (var item in Visit(child, visited))
{
yield return item;
}
}
}
yield return key;
}
}
private void BuildConditions(Component controllingComponent, ReactionRule rule)
{
@ -125,50 +197,80 @@ namespace nadena.dev.modular_avatar.core.editor
var key = new TargetProp
{
TargetObject = renderer,
PropertyName = "blendShape." + shape.ShapeName,
PropertyName = BlendshapePrefix + shape.ShapeName
};
var currentValue = renderer.GetBlendShapeWeight(shapeId);
var value = shape.ChangeType == ShapeChangeType.Delete ? 100 : shape.Value;
if (!shapeKeys.TryGetValue(key, out var info))
RegisterAction(key, currentValue, value, changer);
if (_blendshapeSyncMappings.TryGetValue((renderer, shape.ShapeName), out var bindings))
{
info = new AnimatedProperty(key, renderer.GetBlendShapeWeight(shapeId));
shapeKeys[key] = info;
// Propagate the new value through any Blendshape Syncs we might have.
// Note that we don't propagate deletes; it's common to e.g. want to delete breasts from the
// base model while retaining outerwear that matches the breast size.
foreach (var binding in bindings)
{
var bindingKey = new TargetProp
{
TargetObject = binding.Item1,
PropertyName = BlendshapePrefix + binding.Item2
};
var bindingRenderer = binding.Item1;
// Add initial state
var agk = new ReactionRule(key, value);
agk.Value = renderer.GetBlendShapeWeight(shapeId);
info.actionGroups.Add(agk);
var bindingMesh = bindingRenderer.sharedMesh;
if (bindingMesh == null) continue;
var bindingShapeIndex = bindingMesh.GetBlendShapeIndex(binding.Item2);
if (bindingShapeIndex < 0) continue;
var bindingInitialState = bindingRenderer.GetBlendShapeWeight(bindingShapeIndex);
RegisterAction(bindingKey, bindingInitialState, value, changer);
}
}
var action = ObjectRule(key, changer, value);
action.Inverted = _computeContext.Observe(changer, c => c.Inverted);
var isCurrentlyActive = changer.gameObject.activeInHierarchy;
if (shape.ChangeType == ShapeChangeType.Delete)
key = new TargetProp
{
action.IsDelete = true;
if (isCurrentlyActive) info.currentState = 100;
TargetObject = renderer,
PropertyName = DeletedShapePrefix + shape.ShapeName
};
info.actionGroups.Add(action); // Never merge
continue;
}
if (changer.gameObject.activeInHierarchy) info.currentState = action.Value;
if (info.actionGroups.Count == 0)
{
info.actionGroups.Add(action);
}
else if (!info.actionGroups[^1].TryMerge(action))
{
info.actionGroups.Add(action);
}
value = shape.ChangeType == ShapeChangeType.Delete ? 1 : 0;
RegisterAction(key, 0, value, changer);
}
}
return shapeKeys;
void RegisterAction(TargetProp key, float currentValue, float value, ModularAvatarShapeChanger changer)
{
if (!shapeKeys.TryGetValue(key, out var info))
{
info = new AnimatedProperty(key, currentValue);
shapeKeys[key] = info;
// Add initial state
var agk = new ReactionRule(key, value);
agk.Value = currentValue;
info.actionGroups.Add(agk);
}
var action = ObjectRule(key, changer, value);
action.Inverted = _computeContext.Observe(changer, c => c.Inverted);
if (changer.gameObject.activeInHierarchy) info.currentState = action.Value;
if (info.actionGroups.Count == 0)
{
info.actionGroups.Add(action);
}
else if (!info.actionGroups[^1].TryMerge(action))
{
info.actionGroups.Add(action);
}
}
}
private void FindMaterialSetters(Dictionary<TargetProp, AnimatedProperty> objectGroups, GameObject root)

View File

@ -19,6 +19,11 @@ namespace nadena.dev.modular_avatar.core.editor
private readonly ndmf.BuildContext _context;
private readonly AnimationServicesContext _asc;
private Dictionary<string, float> _simulationInitialStates;
public const string BlendshapePrefix = "blendShape.";
public const string DeletedShapePrefix = "deletedShape.";
public bool OptimizeShapes = true;
public ImmutableDictionary<string, float> ForcePropertyOverrides { get; set; } = ImmutableDictionary<string, float>.Empty;
@ -59,7 +64,6 @@ namespace nadena.dev.modular_avatar.core.editor
{
public Dictionary<TargetProp, AnimatedProperty> Shapes;
public Dictionary<TargetProp, object> InitialStates;
public HashSet<TargetProp> DeletedShapes;
}
private static PropCache<GameObject, AnalysisResult> _analysisCache;
@ -87,7 +91,6 @@ namespace nadena.dev.modular_avatar.core.editor
/// </summary>
/// <param name="root">The avatar root</param>
/// <param name="initialStates">A dictionary of target property to initial state (float or UnityEngine.Object)</param>
/// <param name="deletedShapes">A hashset of blendshape properties which are always deleted</param>
/// <returns></returns>
public AnalysisResult Analyze(
GameObject root
@ -99,9 +102,10 @@ namespace nadena.dev.modular_avatar.core.editor
{
result.Shapes = new();
result.InitialStates = new();
result.DeletedShapes = new();
return result;
}
LocateBlendshapeSyncs(root);
Dictionary<TargetProp, AnimatedProperty> shapes = FindShapes(root);
FindObjectToggles(shapes, root);
@ -110,7 +114,7 @@ namespace nadena.dev.modular_avatar.core.editor
ApplyInitialStateOverrides(shapes);
AnalyzeConstants(shapes);
ResolveToggleInitialStates(shapes);
PreprocessShapes(shapes, out result.InitialStates, out result.DeletedShapes);
PreprocessShapes(shapes, out result.InitialStates);
result.Shapes = shapes;
return result;
@ -125,7 +129,7 @@ namespace nadena.dev.modular_avatar.core.editor
foreach (var cond in rule.ControllingConditions)
{
var paramName = cond.Parameter;
if (ForcePropertyOverrides.TryGetValue(paramName, out var value))
if (ForcePropertyOverrides?.TryGetValue(paramName, out var value) == true)
{
cond.InitialValue = value;
}
@ -145,7 +149,7 @@ namespace nadena.dev.modular_avatar.core.editor
HashSet<GameObject> toggledObjects = new();
if (asc == null) return;
foreach (var targetProp in shapes.Keys)
if (targetProp is { TargetObject: GameObject go, PropertyName: "m_IsActive" })
toggledObjects.Add(go);
@ -166,7 +170,7 @@ namespace nadena.dev.modular_avatar.core.editor
group.actionGroups.RemoveAll(agk => agk.IsConstant && !agk.InitiallyActive);
// Remove all action groups up until the last one where we're always on
var lastAlwaysOnGroup = group.actionGroups.FindLastIndex(ag => ag.IsConstantOn);
var lastAlwaysOnGroup = group.actionGroups.FindLastIndex(ag => ag.IsConstantActive);
if (lastAlwaysOnGroup > 0)
group.actionGroups.RemoveRange(0, lastAlwaysOnGroup - 1);
}
@ -265,39 +269,26 @@ namespace nadena.dev.modular_avatar.core.editor
}
/// <summary>
/// Determine initial state and deleted shapes for all properties
/// Determine initial state for all properties
/// </summary>
/// <param name="shapes"></param>
/// <param name="initialStates"></param>
/// <param name="deletedShapes"></param>
private void PreprocessShapes(Dictionary<TargetProp, AnimatedProperty> shapes, out Dictionary<TargetProp, object> initialStates, out HashSet<TargetProp> deletedShapes)
private void PreprocessShapes(Dictionary<TargetProp, AnimatedProperty> shapes,
out Dictionary<TargetProp, object> initialStates)
{
// For each shapekey, determine 1) if we can just set an initial state and skip and 2) if we can delete the
// corresponding mesh. If we can't, delete ops are merged into the main list of operations.
initialStates = new Dictionary<TargetProp, object>();
deletedShapes = new HashSet<TargetProp>();
foreach (var (key, info) in shapes.ToList())
{
if (info.actionGroups.Count == 0)
{
// never active control; ignore it entirely
shapes.Remove(key);
if (OptimizeShapes) shapes.Remove(key);
continue;
}
var deletions = info.actionGroups.Where(agk => agk.IsDelete).ToList();
if (deletions.Any(d => d.ControllingConditions.All(c => c.IsConstantActive)))
{
// always deleted
shapes.Remove(key);
deletedShapes.Add(key);
continue;
}
// Move deleted shapes to the end of the list, so they override all Set actions
info.actionGroups = info.actionGroups.Where(agk => !agk.IsDelete).Concat(deletions).ToList();
var initialState = info.actionGroups.Where(agk => agk.InitiallyActive)
.Select(agk => agk.Value)
@ -309,7 +300,7 @@ namespace nadena.dev.modular_avatar.core.editor
// If we're now constant-on, we can skip animation generation
if (info.actionGroups[^1].IsConstant)
{
shapes.Remove(key);
if (OptimizeShapes) shapes.Remove(key);
}
}
}

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.modular_avatar.animation;
using UnityEditor;
@ -43,10 +42,11 @@ namespace nadena.dev.modular_avatar.core.editor
var shapes = analysis.Shapes;
var initialStates = analysis.InitialStates;
var deletedShapes = analysis.DeletedShapes;
GenerateActiveSelfProxies(shapes);
ProcessMeshDeletion(initialStates, shapes);
ProcessInitialStates(initialStates, shapes);
ProcessInitialAnimatorVariables(shapes);
@ -54,8 +54,6 @@ namespace nadena.dev.modular_avatar.core.editor
{
ProcessShapeKey(groups);
}
ProcessMeshDeletion(deletedShapes);
}
private void GenerateActiveSelfProxies(Dictionary<TargetProp, AnimatedProperty> shapes)
@ -86,7 +84,7 @@ namespace nadena.dev.modular_avatar.core.editor
initialValues[condition.Parameter] = condition.InitialValue;
}
}
}
}
private void ProcessInitialStates(Dictionary<TargetProp, object> initialStates,
Dictionary<TargetProp, AnimatedProperty> shapes)
@ -226,30 +224,65 @@ namespace nadena.dev.modular_avatar.core.editor
#region Mesh processing
private void ProcessMeshDeletion(HashSet<TargetProp> deletedKeys)
private void ProcessMeshDeletion(Dictionary<TargetProp, object> initialStates,
Dictionary<TargetProp, AnimatedProperty> shapes)
{
ImmutableDictionary<SkinnedMeshRenderer, List<TargetProp>> renderers = deletedKeys
.GroupBy(
v => (SkinnedMeshRenderer) v.TargetObject
).ToImmutableDictionary(
g => (SkinnedMeshRenderer) g.Key,
g => g.ToList()
);
var renderers = initialStates
.Where(kvp => kvp.Key.PropertyName.StartsWith(ReactiveObjectAnalyzer.DeletedShapePrefix))
.Where(kvp => kvp.Key.TargetObject is SkinnedMeshRenderer)
.Where(kvp => kvp.Value is float f && f > 0.5f)
// Filter any non-constant keys
.Where(kvp =>
{
if (!shapes.ContainsKey(kvp.Key))
{
// Constant value
return true;
}
foreach (var (renderer, infos) in renderers)
var lastGroup = shapes[kvp.Key].actionGroups.LastOrDefault();
return lastGroup?.IsConstantActive == true && lastGroup.Value is float f && f > 0.5f;
})
.GroupBy(kvp => kvp.Key.TargetObject as SkinnedMeshRenderer)
.Select(grouping => (grouping.Key, grouping.Select(
kvp => kvp.Key.PropertyName.Substring(ReactiveObjectAnalyzer.DeletedShapePrefix.Length)
).ToList()))
.ToList();
foreach (var (renderer, shapeNamesToDelete) in renderers)
{
if (renderer == null) continue;
var mesh = renderer.sharedMesh;
if (mesh == null) continue;
renderer.sharedMesh = RemoveBlendShapeFromMesh.RemoveBlendshapes(
mesh,
infos
.Select(i => mesh.GetBlendShapeIndex(i.PropertyName.Substring("blendShape.".Length)))
.Where(k => k >= 0)
.ToList()
);
var shapesToDelete = shapeNamesToDelete
.Select(shape => mesh.GetBlendShapeIndex(shape))
.Where(k => k >= 0)
.ToList();
renderer.sharedMesh = RemoveBlendShapeFromMesh.RemoveBlendshapes(mesh, shapesToDelete);
foreach (var name in shapeNamesToDelete)
{
// Don't need to animate this anymore...!
shapes.Remove(new TargetProp
{
TargetObject = renderer,
PropertyName = ReactiveObjectAnalyzer.BlendshapePrefix + name
});
shapes.Remove(new TargetProp
{
TargetObject = renderer,
PropertyName = ReactiveObjectAnalyzer.DeletedShapePrefix + name
});
initialStates.Remove(new TargetProp
{
TargetObject = renderer,
PropertyName = ReactiveObjectAnalyzer.BlendshapePrefix + name
});
}
}
}
@ -258,10 +291,6 @@ namespace nadena.dev.modular_avatar.core.editor
private void ProcessShapeKey(AnimatedProperty info)
{
// TODO: prune non-animated keys
// Check if this is non-animated and skip most processing if so
if (info.alwaysDeleted || info.actionGroups[^1].IsConstant) return;
var asm = GenerateStateMachine(info);
ApplyController(asm, "MA Responsive: " + info.TargetProp.TargetObject.name);
}
@ -301,8 +330,7 @@ namespace nadena.dev.modular_avatar.core.editor
var transitionBuffer = new List<(AnimatorState, List<AnimatorStateTransition>)>();
var entryTransitions = new List<AnimatorTransition>();
var initialStateTransitionList = new List<AnimatorStateTransition>();
transitionBuffer.Add((initialState, initialStateTransitionList));
transitionBuffer.Add((initialState, new List<AnimatorStateTransition>()));
foreach (var group in info.actionGroups.Skip(lastConstant))
{
@ -322,30 +350,33 @@ namespace nadena.dev.modular_avatar.core.editor
var conditions = GetTransitionConditions(asc, group);
if (!group.Inverted)
foreach (var (st, transitions) in transitionBuffer)
{
var transition = new AnimatorStateTransition
if (!group.Inverted)
{
isExit = true,
hasExitTime = false,
duration = 0,
hasFixedDuration = true,
conditions = (AnimatorCondition[])conditions.Clone()
};
initialStateTransitionList.Add(transition);
}
else
{
foreach (var cond in conditions)
{
initialStateTransitionList.Add(new AnimatorStateTransition
var transition = new AnimatorStateTransition
{
isExit = true,
hasExitTime = false,
duration = 0,
hasFixedDuration = true,
conditions = new[] { InvertCondition(cond) }
});
conditions = (AnimatorCondition[])conditions.Clone()
};
transitions.Add(transition);
}
else
{
foreach (var cond in conditions)
{
transitions.Add(new AnimatorStateTransition
{
isExit = true,
hasExitTime = false,
duration = 0,
hasFixedDuration = true,
conditions = new[] { InvertCondition(cond) }
});
}
}
}

View File

@ -15,11 +15,11 @@ namespace nadena.dev.modular_avatar.core.editor
protected override void Execute(ndmf.BuildContext context)
{
var hasShapeChanger = context.AvatarRootObject.GetComponentInChildren<ModularAvatarShapeChanger>() != null;
var hasShapeChanger = context.AvatarRootObject.GetComponentInChildren<ModularAvatarShapeChanger>(true) != null;
var hasObjectSwitcher =
context.AvatarRootObject.GetComponentInChildren<ModularAvatarObjectToggle>() != null;
context.AvatarRootObject.GetComponentInChildren<ModularAvatarObjectToggle>(true) != null;
var hasMaterialSetter =
context.AvatarRootObject.GetComponentInChildren<ModularAvatarMaterialSetter>() != null;
context.AvatarRootObject.GetComponentInChildren<ModularAvatarMaterialSetter>(true) != null;
if (hasShapeChanger || hasObjectSwitcher || hasMaterialSetter)
{
var clip = new AnimationClip();

View File

@ -73,8 +73,8 @@ namespace nadena.dev.modular_avatar.core.editor
var analysis = ReactiveObjectAnalyzer.CachedAnalyze(context, avatarRoot);
var shapes = analysis.Shapes;
ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>>.Builder rendererStates =
ImmutableDictionary.CreateBuilder<SkinnedMeshRenderer, ImmutableList<(int, float)>>(
var rendererStates =
ImmutableDictionary.CreateBuilder<SkinnedMeshRenderer, ImmutableDictionary<int, float>>(
);
var avatarRootTransform = avatarRoot.transform;
@ -84,16 +84,29 @@ namespace nadena.dev.modular_avatar.core.editor
var target = prop.TargetProp;
if (target.TargetObject == null || target.TargetObject is not SkinnedMeshRenderer r) continue;
if (!r.transform.IsChildOf(avatarRootTransform)) continue;
if (!target.PropertyName.StartsWith("blendShape.")) continue;
var isDelete = false;
string shapeName = null;
if (target.PropertyName.StartsWith(ReactiveObjectAnalyzer.DeletedShapePrefix))
{
isDelete = true;
shapeName = target.PropertyName.Substring(ReactiveObjectAnalyzer.DeletedShapePrefix.Length);
}
else if (target.PropertyName.StartsWith(ReactiveObjectAnalyzer.BlendshapePrefix))
{
shapeName = target.PropertyName.Substring(ReactiveObjectAnalyzer.BlendshapePrefix.Length);
}
else
{
continue;
}
var mesh = r.sharedMesh;
if (mesh == null) continue;
var shapeName = target.PropertyName.Substring("blendShape.".Length);
if (!rendererStates.TryGetValue(r, out var states))
{
states = ImmutableList<(int, float)>.Empty;
states = ImmutableDictionary<int, float>.Empty;
rendererStates[r] = states;
}
@ -102,16 +115,32 @@ namespace nadena.dev.modular_avatar.core.editor
var activeRule = prop.actionGroups.LastOrDefault(rule => rule.InitiallyActive);
if (activeRule == null || activeRule.Value is not float value) continue;
if (activeRule.ControllingObject == null) continue; // default value is being inherited
value = Math.Clamp(value, 0, 100);
if (activeRule.IsDelete) value = -1;
states = states.Add((index, value));
if (isDelete)
{
if (value < 0.5f) continue;
value = -1;
}
else
{
if (states.ContainsKey(index))
{
// Delete takes precedence over set in preview
continue;
}
value = Math.Clamp(value, 0, 100);
}
states = states.SetItem(index, value);
rendererStates[r] = states;
}
return rendererStates.ToImmutableDictionary();
return rendererStates.ToImmutableDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Select(shapePair => (shapePair.Key, shapePair.Value)
).ToImmutableList());
}
private IEnumerable<RenderGroup> ShapesToGroups(GameObject avatarRoot, ImmutableDictionary<SkinnedMeshRenderer, ImmutableList<(int, float)>> shapes)

View File

@ -257,7 +257,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
return;
}
_btn_clear.SetEnabled(!PropertyOverrides.Value.IsEmpty || !MenuItemOverrides.Value.IsEmpty);
_btn_clear.SetEnabled(PropertyOverrides.Value?.IsEmpty == false || MenuItemOverrides.Value?.IsEmpty == false);
e_debugInfo.style.display = DisplayStyle.Flex;
@ -265,6 +265,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
_lastComputeContext.InvokeOnInvalidate(this, MaybeRefreshUI);
var analysis = new ReactiveObjectAnalyzer(_lastComputeContext);
analysis.OptimizeShapes = false;
analysis.ForcePropertyOverrides = PropertyOverrides.Value;
analysis.ForceMenuItems = MenuItemOverrides.Value;
var result = analysis.Analyze(avatar.gameObject);
@ -472,7 +473,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
var f_set_inactive = effectGroup.Q<VisualElement>("effect__set-inactive");
var f_value = effectGroup.Q<FloatField>("effect__value");
var f_material = effectGroup.Q<ObjectField>("effect__material");
var f_delete = effectGroup.Q("effect__deleted");
var f_delete = effectGroup.Q<TextField>("effect__deleted");
f_target_component.style.display = DisplayStyle.None;
f_target_component.SetEnabled(false);
@ -505,9 +506,10 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
f_property.value = targetProp.PropertyName;
f_property.style.display = DisplayStyle.Flex;
if (reactionRule.IsDelete)
if (reactionRule.TargetProp.PropertyName.StartsWith(ReactiveObjectAnalyzer.DeletedShapePrefix))
{
f_delete.style.display = DisplayStyle.Flex;
f_delete.value = reactionRule.Value is > 0.5f ? "DELETE" : "RETAIN";
} else if (reactionRule.Value is float f)
{
f_value.SetValueWithoutNotify(f);

View File

@ -344,7 +344,7 @@ namespace nadena.dev.modular_avatar.core.editor
if (proxy == null) return;
var curParent = proxy.transform.parent ?? original.transform.parent;
if (_finalBonesMap.TryGetValue(curParent, out var newRoot))
if (curParent != null && _finalBonesMap.TryGetValue(curParent, out var newRoot))
{
// We need to remember this proxy so we can avoid destroying it when we destroy VirtualAvatarRoot
// in Dispose

View File

@ -229,7 +229,7 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
private static void FixAPose(GameObject avatarRoot, Transform outfitArmature)
internal static void FixAPose(GameObject avatarRoot, Transform outfitArmature, bool strictMode = true)
{
var mergeArmature = outfitArmature.GetComponent<ModularAvatarMergeArmature>();
if (mergeArmature == null) return;
@ -249,7 +249,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
var lowerArm = (HumanBodyBones)((int)arm + 2);
// check if the rotation of the arm differs, but distances and origin point are the same
// check if the rotation of the arm differs(, but distances and origin point are the same when strictMode)
var avatarArm = rootAnimator.GetBoneTransform(arm);
var outfitArm = avatarToOutfit(avatarArm);
@ -259,22 +259,27 @@ namespace nadena.dev.modular_avatar.core.editor
if (outfitArm == null) return;
if (outfitLowerArm == null) return;
if ((avatarArm.position - outfitArm.position).magnitude > 0.001f) return;
if (strictMode)
{
if ((avatarArm.position - outfitArm.position).magnitude > 0.001f) return;
// check relative distance to lower arm as well
var avatarArmLength = (avatarLowerArm.position - avatarArm.position).magnitude;
var outfitArmLength = (outfitLowerArm.position - outfitArm.position).magnitude;
// check relative distance to lower arm as well
var avatarArmLength = (avatarLowerArm.position - avatarArm.position).magnitude;
var outfitArmLength = (outfitLowerArm.position - outfitArm.position).magnitude;
if (Mathf.Abs(avatarArmLength - outfitArmLength) > 0.001f) return;
if (Mathf.Abs(avatarArmLength - outfitArmLength) > 0.001f) return;
} else {
if (Vector3.Dot((outfitLowerArm.position - outfitArm.position).normalized, (avatarLowerArm.position - avatarArm.position).normalized) > 0.999f) return;
}
// Rotate the outfit arm to ensure these two points match.
// Rotate the outfit arm to ensure these two bone orientations match.
Undo.RecordObject(outfitArm, "Convert A/T Pose");
var relRot = Quaternion.FromToRotation(
outfitLowerArm.position - outfitArm.position,
avatarLowerArm.position - avatarArm.position
);
outfitArm.rotation = relRot * outfitArm.rotation;
PrefabUtility.RecordPrefabInstancePropertyModifications(outfitArm);
EditorUtility.SetDirty(outfitArm);
}
Transform avatarToOutfit(Transform avBone)

View File

@ -33,4 +33,4 @@ For more information, check out the [documentation](https://m-a.nadena.dev).
* 部分的なアニメーターを親に統合することで、様々のギミックの実装を簡単にします。
* 他にもいろいろ!
詳しくは[ドキュメンテーションページにご参照ください](https://modular-avatar.nadena.dev/ja/).
詳しくは[ドキュメンテーションページをご覧ください](https://modular-avatar.nadena.dev/ja/).

View File

@ -38,7 +38,7 @@ namespace nadena.dev.modular_avatar.core
}
[AddComponentMenu("Modular Avatar/MA Material Setter")]
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/material-setter?lang=auto")]
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/reaction/material-setter?lang=auto")]
public class ModularAvatarMaterialSetter : ReactiveComponent, IHaveObjReferences
{
[SerializeField] private List<MaterialSwitchObject> m_objects = new();

View File

@ -21,7 +21,7 @@ namespace nadena.dev.modular_avatar.core
}
[AddComponentMenu("Modular Avatar/MA Object Toggle")]
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/object-toggle?lang=auto")]
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/reaction/object-toggle?lang=auto")]
public class ModularAvatarObjectToggle : ReactiveComponent, IHaveObjReferences
{
[SerializeField] private List<ToggledObject> m_objects = new();

View File

@ -57,14 +57,9 @@ namespace nadena.dev.modular_avatar.core
}
[AddComponentMenu("Modular Avatar/MA Shape Changer")]
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/shape-changer?lang=auto")]
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/reaction/shape-changer?lang=auto")]
public class ModularAvatarShapeChanger : ReactiveComponent, IHaveObjReferences
{
// Migration field to help with 1.10-beta series avatar data. Since this was never in a released version of MA,
// this migration support will be removed in 1.10.0.
[SerializeField] [FormerlySerializedAs("targetRenderer")] [HideInInspector]
private AvatarObjectReference m_targetRenderer = new();
[SerializeField] [FormerlySerializedAs("Shapes")]
private List<ChangedShape> m_shapes = new();
@ -82,40 +77,6 @@ namespace nadena.dev.modular_avatar.core
}
}
private void OnEnable()
{
MigrateTargetRenderer();
}
protected override void OnValidate()
{
base.OnValidate();
MigrateTargetRenderer();
}
// Migrate early versions of MASC (from Modular Avatar 1.10.0-beta.4 or earlier) to the new format, where the
// target renderer is stored separately for each shape.
// This logic will be removed in 1.10.0.
private void MigrateTargetRenderer()
{
// Note: This method runs in the context of OnValidate, and therefore cannot touch any other unity objects.
if (!string.IsNullOrEmpty(m_targetRenderer.referencePath) || m_targetRenderer.targetObject != null)
{
foreach (var shape in m_shapes)
{
if (shape.Object == null) shape.Object = new AvatarObjectReference();
if (string.IsNullOrEmpty(shape.Object.referencePath) && shape.Object.targetObject == null)
{
shape.Object.referencePath = m_targetRenderer.referencePath;
shape.Object.targetObject = m_targetRenderer.targetObject;
}
}
m_targetRenderer.referencePath = null;
m_targetRenderer.targetObject = null;
}
}
public IEnumerable<AvatarObjectReference> GetObjectReferences()
{
foreach (var shape in m_shapes)

View File

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

View File

@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-9046052599989551153
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: proxy_tpose
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: 645a7092829eff9478fb3a29f959a6fa, 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: New Animator Controller
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: proxy
m_StateMachine: {fileID: 1953483892909110087}
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 &1953483892909110087
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: proxy
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -9046052599989551153}
m_Position: {x: 360, y: 110, 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: -9046052599989551153}

View File

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

View File

@ -0,0 +1,28 @@
using modular_avatar_tests;
using nadena.dev.modular_avatar.core;
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using UnityEditor.Animations;
using UnityEngine;
namespace UnitTests.MergeAnimatorTests.ProxyAnim
{
public class ProxyAnimTest : TestBase
{
[Test]
public void whenProxyAnimIsMerged_itIsNotReplaced()
{
var root = CreatePrefab("ProxyAnimTest.prefab");
var originalAnimator = (AnimatorController) root.GetComponentInChildren<ModularAvatarMergeAnimator>().animator;
var originalClip = originalAnimator.layers[0].stateMachine.states[0].state.motion as AnimationClip;
AvatarProcessor.ProcessAvatar(root);
var resultLayer = findFxLayer(root, "proxy");
var resultClip = resultLayer.stateMachine.states[0].state.motion as AnimationClip;
Assert.AreEqual(originalClip, resultClip);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2cfba229fa1e4c718f5cb5dd579d3319
timeCreated: 1728166108

View File

@ -0,0 +1,378 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &603567390109878184
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2557688482630581002}
- component: {fileID: 2868037606074871127}
- component: {fileID: 1028276594299388724}
- component: {fileID: 223023489903813839}
m_Layer: 0
m_Name: ProxyAnimTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2557688482630581002
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 603567390109878184}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1.1618705, y: 1.0265146, z: 1.8807894}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 2189711873526373063}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!95 &2868037606074871127
Animator:
serializedVersion: 5
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 603567390109878184}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 0}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!114 &1028276594299388724
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 603567390109878184}
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}
networkIDs: []
customExpressions: 0
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: 0
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: 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 &223023489903813839
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 603567390109878184}
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 &1425973809379277617
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2189711873526373063}
- component: {fileID: 3380859768730913427}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2189711873526373063
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1425973809379277617}
serializedVersion: 2
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_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 2557688482630581002}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &3380859768730913427
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1425973809379277617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3}
m_Name:
m_EditorClassIdentifier:
animator: {fileID: 9100000, guid: 60603c8e68ac87447b02be4e3af6a7bd, type: 2}
layerType: 5
deleteAttachedAnimator: 1
pathMode: 0
matchAvatarWriteDefaults: 0
relativePathRoot:
referencePath:
targetObject: {fileID: 0}
layerPriority: 0

View File

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

View File

@ -0,0 +1,61 @@
using System.Linq;
using modular_avatar_tests;
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using UnityEngine;
namespace UnitTests.ReactiveComponent
{
public class BlendshapeSyncTest : TestBase
{
[Test]
public void blendshapeSync_propagatesThroughMeshes()
{
var root = CreatePrefab("BlendshapeSyncTest.prefab");
var analysis = new ReactiveObjectAnalyzer().Analyze(root);
var m1 = analysis.Shapes[new TargetProp()
{
TargetObject = root.transform.Find("m1").GetComponent<SkinnedMeshRenderer>(),
PropertyName = "blendShape.bottom"
}];
var m2 = analysis.Shapes[new TargetProp()
{
TargetObject = root.transform.Find("m2").GetComponent<SkinnedMeshRenderer>(),
PropertyName = "blendShape.bottom"
}];
var m3 = analysis.Shapes[new TargetProp()
{
TargetObject = root.transform.Find("m3").GetComponent<SkinnedMeshRenderer>(),
PropertyName = "blendShape.top"
}];
Assert.IsTrue(analysis.Shapes.ContainsKey(new TargetProp()
{
TargetObject = root.transform.Find("m1").GetComponent<SkinnedMeshRenderer>(),
PropertyName = "deletedShape.bottom"
}));
Assert.AreEqual(4, analysis.Shapes.Count);
foreach (var ag in m1.actionGroups)
{
ag.TargetProp = new TargetProp();
}
foreach (var ag in m2.actionGroups)
{
ag.TargetProp = new TargetProp();
}
foreach (var ag in m3.actionGroups)
{
ag.TargetProp = new TargetProp();
}
Assert.AreEqual(m2.actionGroups, m1.actionGroups);
Assert.AreEqual(m3.actionGroups, m1.actionGroups);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f74d4e816d0247159d977e21ebc57458
timeCreated: 1728168066

View File

@ -0,0 +1,799 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &4750389987621451750
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3724328547737935111}
- component: {fileID: 6141552197888553193}
- component: {fileID: 866105862211182099}
- component: {fileID: 5955186656294850035}
m_Layer: 0
m_Name: New Toggle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3724328547737935111
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4750389987621451750}
serializedVersion: 2
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_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 295226914695240947}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &6141552197888553193
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4750389987621451750}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3}
m_Name:
m_EditorClassIdentifier:
Control:
name: New Toggle
icon: {fileID: 0}
type: 102
parameter:
name:
value: 1
style: 0
subMenu: {fileID: 0}
subParameters: []
labels: []
MenuSource: 1
menuSource_otherObjectChildren: {fileID: 0}
isSynced: 1
isSaved: 1
isDefault: 1
automaticValue: 1
--- !u!114 &866105862211182099
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4750389987621451750}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3}
m_Name:
m_EditorClassIdentifier:
menuToAppend: {fileID: 0}
installTargetMenu: {fileID: 0}
--- !u!114 &5955186656294850035
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4750389987621451750}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 0
m_shapes:
- Object:
referencePath: m1
targetObject: {fileID: 7767603723203631002}
ShapeName: bottom
ChangeType: 1
Value: 100
--- !u!1 &7303978391080220300
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 295226914695240947}
- component: {fileID: 1177795503533185300}
- component: {fileID: 7792711537747161192}
- component: {fileID: 8538029171187693289}
m_Layer: 0
m_Name: BlendshapeSyncTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &295226914695240947
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7303978391080220300}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1.1618705, y: 1.0265146, z: 1.8807894}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 6955742288500591904}
- {fileID: 2035853062413530075}
- {fileID: 2118711245520540949}
- {fileID: 3724328547737935111}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!95 &1177795503533185300
Animator:
serializedVersion: 5
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7303978391080220300}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 0}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!114 &7792711537747161192
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7303978391080220300}
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}
networkIDs: []
customExpressions: 0
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: 0
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: 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 &8538029171187693289
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7303978391080220300}
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!1001 &1940371780088492798
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 295226914695240947}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.x
value: 5.33
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071067
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_ConstrainProportionsScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_DirtyAABB
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.z
value: 2
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_BlendShapeWeights.Array.data[0]
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_Name
value: m3
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
insertIndex: -1
addedObject: {fileID: 4462016549056391230}
m_SourcePrefab: {fileID: 100100000, guid: fe5b76dae94c07345b74d51e9a9a8440, type: 3}
--- !u!1 &1597929094539956143 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 1940371780088492798}
m_PrefabAsset: {fileID: 0}
--- !u!114 &4462016549056391230
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1597929094539956143}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6fd7cab7d93b403280f2f9da978d8a4f, type: 3}
m_Name:
m_EditorClassIdentifier:
Bindings:
- ReferenceMesh:
referencePath: m2
targetObject: {fileID: 1660453041666320737}
Blendshape: bottom
LocalBlendshape: top
--- !u!4 &2118711245520540949 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 1940371780088492798}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &2002541556693849136
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 295226914695240947}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.x
value: 2.75
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071067
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_ConstrainProportionsScale
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_DirtyAABB
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.z
value: 2
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_BlendShapeWeights.Array.data[0]
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_Name
value: m2
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
insertIndex: -1
addedObject: {fileID: 1532028097981150578}
m_SourcePrefab: {fileID: 100100000, guid: fe5b76dae94c07345b74d51e9a9a8440, type: 3}
--- !u!1 &1660453041666320737 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 2002541556693849136}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1532028097981150578
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1660453041666320737}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 6fd7cab7d93b403280f2f9da978d8a4f, type: 3}
m_Name:
m_EditorClassIdentifier:
Bindings:
- ReferenceMesh:
referencePath: m1
targetObject: {fileID: 7767603723203631002}
Blendshape: bottom
LocalBlendshape:
--- !u!4 &2035853062413530075 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 2002541556693849136}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &7425727422508624587
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 295226914695240947}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071067
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_DirtyAABB
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.z
value: 2
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_Materials.Array.data[0]
value:
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_BlendShapeWeights.Array.data[0]
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_Name
value: m1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: fe5b76dae94c07345b74d51e9a9a8440, type: 3}
--- !u!4 &6955742288500591904 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 7425727422508624587}
m_PrefabAsset: {fileID: 0}
--- !u!1 &7767603723203631002 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 7425727422508624587}
m_PrefabAsset: {fileID: 0}

View File

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

View File

@ -0,0 +1,666 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2464504760772767737
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3251791125987375227}
- component: {fileID: 6611954401356246169}
- component: {fileID: 4257580493320060063}
- component: {fileID: 7095484051158404692}
m_Layer: 0
m_Name: DeletionTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3251791125987375227
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2464504760772767737}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0.06867766, y: 0.7869835, z: -0.57959247}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children:
- {fileID: 8671858138418525756}
- {fileID: 3787319563290092876}
- {fileID: 2780879708549973278}
- {fileID: 6867583134219554799}
- {fileID: 3617623734196600728}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!95 &6611954401356246169
Animator:
serializedVersion: 5
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2464504760772767737}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 0}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!114 &4257580493320060063
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2464504760772767737}
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}
networkIDs: []
customExpressions: 0
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: 0
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: 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 &7095484051158404692
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2464504760772767737}
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 &3134446681435896768
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2780879708549973278}
- component: {fileID: 2470606632396626262}
m_Layer: 0
m_Name: Delete
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2780879708549973278
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3134446681435896768}
serializedVersion: 2
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_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 3251791125987375227}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2470606632396626262
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3134446681435896768}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 0
m_shapes:
- Object:
referencePath: shape deletion test mesh
targetObject: {fileID: 0}
ShapeName: bottom
ChangeType: 0
Value: 50
--- !u!1 &7874409458034691206
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3787319563290092876}
- component: {fileID: 8462455628590652122}
m_Layer: 0
m_Name: PriorSet
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &3787319563290092876
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7874409458034691206}
serializedVersion: 2
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_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 3251791125987375227}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8462455628590652122
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7874409458034691206}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 0
m_shapes:
- Object:
referencePath: shape deletion test mesh
targetObject: {fileID: 0}
ShapeName: bottom
ChangeType: 1
Value: 50
--- !u!1 &7956182162252432618
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3617623734196600728}
- component: {fileID: 4167915178638071617}
- component: {fileID: 3280847981733507148}
m_Layer: 0
m_Name: MenuSet
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &3617623734196600728
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7956182162252432618}
serializedVersion: 2
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_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 3251791125987375227}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4167915178638071617
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7956182162252432618}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 0
m_shapes:
- Object:
referencePath: shape deletion test mesh
targetObject: {fileID: 0}
ShapeName: bottom
ChangeType: 1
Value: 0
--- !u!114 &3280847981733507148
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7956182162252432618}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3}
m_Name:
m_EditorClassIdentifier:
Control:
name:
icon: {fileID: 0}
type: 102
parameter:
name:
value: 1
style: 0
subMenu: {fileID: 0}
subParameters: []
labels: []
MenuSource: 1
menuSource_otherObjectChildren: {fileID: 0}
isSynced: 1
isSaved: 1
isDefault: 0
automaticValue: 1
--- !u!1 &8389945206789797712
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6867583134219554799}
- component: {fileID: 8099891503683627458}
m_Layer: 0
m_Name: NullSet
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &6867583134219554799
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8389945206789797712}
serializedVersion: 2
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_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 3251791125987375227}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8099891503683627458
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8389945206789797712}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 0
m_shapes:
- Object:
referencePath: shape deletion test mesh
targetObject: {fileID: 0}
ShapeName: bottom
ChangeType: 1
Value: 0
--- !u!1001 &9210451080691405271
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 3251791125987375227}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071067
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_DirtyAABB
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_AABB.m_Extent.z
value: 2
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_BlendShapeWeights.Array.data[0]
value: 0
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
propertyPath: m_Name
value: shape deletion test mesh
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: fe5b76dae94c07345b74d51e9a9a8440, type: 3}
--- !u!4 &8671858138418525756 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: fe5b76dae94c07345b74d51e9a9a8440,
type: 3}
m_PrefabInstance: {fileID: 9210451080691405271}
m_PrefabAsset: {fileID: 0}

View File

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

View File

@ -0,0 +1,50 @@
using System.Linq;
using modular_avatar_tests;
using nadena.dev.modular_avatar.core;
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using UnityEditor.Animations;
using UnityEngine;
namespace UnitTests.ReactiveComponent
{
internal class ObjectToggleTests : TestBase
{
[Test]
public void WhenObjectIsAlwaysOn_CorrectProxyParameterIsGenerated()
{
var root = CreateRoot("root");
var obj = CreateChild(root, "obj");
var toggle = CreateChild(root, "toggle");
// Prevent obj from being removed by the GC game objects pass
obj.AddComponent<MeshRenderer>();
var toggleComponent = toggle.AddComponent<ModularAvatarObjectToggle>();
var aor = new AvatarObjectReference();
aor.Set(obj);
toggleComponent.Objects = new()
{
new()
{
Active = false,
Object = aor
}
};
AvatarProcessor.ProcessAvatar(root);
// TODO: Ideally we should start using play mode testing for these things...
var fx = (AnimatorController)FindFxController(root).animatorController;
var readableProp = fx.parameters.FirstOrDefault(
p => p.name.StartsWith("__MA/ReadableProp/obj/UnityEngine.GameObject/m_IsActive")
);
Assert.IsNotNull(readableProp);
Assert.AreEqual(readableProp.defaultFloat, 0);
Assert.IsFalse(obj.activeSelf);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c68d69f7b4a46c5b2ce3d8f26b0fa76
timeCreated: 1729376563

View File

@ -0,0 +1,98 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using modular_avatar_tests;
using nadena.dev.modular_avatar.core;
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using UnityEngine;
public class ShapeDeletionAnalysis : TestBase
{
[Test]
public void BasicShapeDeletionAnalysis()
{
var root = CreatePrefab("DeletionTest.prefab");
var mesh = AssertPreviewDeletion(root);
AssertBuildDeletion(mesh, root);
}
[Test]
public void WhenShapeDeletionIsConditionedOnSubsequentChanger_DoesNotDelete()
{
var root = CreatePrefab("DeletionTest.prefab");
root.transform.Find("MenuSet").gameObject.SetActive(true);
AssertPreviewDeletion(root);
AssertNoMeshDeletion(root);
var mesh = root.GetComponentInChildren<SkinnedMeshRenderer>();
Assert.AreEqual(100, mesh.GetBlendShapeWeight(mesh.sharedMesh.GetBlendShapeIndex("bottom")));
}
[Test]
public void WhenShapeDeletionIsConditionedOnItself_DoesNotDelete()
{
var root = CreatePrefab("DeletionTest.prefab");
root.transform.Find("Delete").gameObject.AddComponent<ModularAvatarMenuItem>().InitSettings();
AssertNoPreviewDeletion(root);
AssertNoMeshDeletion(root);
var mesh = root.GetComponentInChildren<SkinnedMeshRenderer>();
// deletion action is initially off, so we use the shape changer above it, which is set to 50.
Assert.AreEqual(50f, mesh.GetBlendShapeWeight(mesh.sharedMesh.GetBlendShapeIndex("bottom")));
}
private static void AssertBuildDeletion(SkinnedMeshRenderer mesh, GameObject root)
{
var originalSharedMesh = mesh.sharedMesh;
AvatarProcessor.ProcessAvatar(root);
Assert.AreNotEqual(originalSharedMesh, mesh.sharedMesh);
Assert.IsTrue(mesh.sharedMesh.vertices.All(v => v.z >= 0));
}
private static SkinnedMeshRenderer AssertPreviewDeletion(GameObject root)
{
var mesh = root.GetComponentInChildren<SkinnedMeshRenderer>();
var analysis = new ReactiveObjectAnalyzer().Analyze(root);
var deletedShape = analysis.Shapes.GetValueOrDefault(new TargetProp()
{
TargetObject = mesh,
PropertyName = "deletedShape.bottom"
});
Assert.IsNotNull(deletedShape);
var activeGroup = deletedShape.actionGroups.LastOrDefault(ag => ag.InitiallyActive);
Assert.AreEqual(1.0f, activeGroup?.Value);
return mesh;
}
private static void AssertNoPreviewDeletion(GameObject root)
{
var mesh = root.GetComponentInChildren<SkinnedMeshRenderer>();
var analysis = new ReactiveObjectAnalyzer().Analyze(root);
var deletedShape = analysis.Shapes.GetValueOrDefault(new TargetProp()
{
TargetObject = mesh,
PropertyName = "deletedShape.bottom"
});
if (deletedShape != null)
{
var activeGroup = deletedShape.actionGroups.LastOrDefault(ag => ag.InitiallyActive);
Assert.IsFalse(activeGroup?.Value is float f && f > 0);
}
}
private static void AssertNoMeshDeletion(GameObject root)
{
var mesh = root.GetComponentInChildren<SkinnedMeshRenderer>();
var originalSharedMesh = mesh.sharedMesh;
AvatarProcessor.ProcessAvatar(root);
Assert.AreEqual(originalSharedMesh, mesh.sharedMesh);
}
}

View File

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

View File

@ -0,0 +1,109 @@
fileFormatVersion: 2
guid: fe5b76dae94c07345b74d51e9a9a8440
ModelImporter:
serializedVersion: 22200
internalIDToNameTable: []
externalObjects: {}
materials:
materialImportMode: 2
materialName: 0
materialSearch: 1
materialLocation: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
removeConstantScaleCurves: 0
motionNodeName:
rigImportErrors:
rigImportWarnings:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
importAnimatedCustomProperties: 0
importConstraints: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
extraUserProperties: []
clipAnimations: []
isReadable: 0
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
useSRGBMaterialColor: 1
sortHierarchyByName: 1
importPhysicalCameras: 1
importVisibility: 1
importBlendShapes: 1
importCameras: 1
importLights: 1
nodeNameCollisionStrategy: 1
fileIdsGeneration: 2
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
keepQuads: 0
weldVertices: 1
bakeAxisConversion: 0
preserveHierarchy: 0
skinWeightsMode: 0
maxBonesPerVertex: 4
minBoneWeight: 0.001
optimizeBones: 1
meshOptimizationFlags: -1
indexFormat: 0
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVMarginMethod: 1
secondaryUVMinLightmapResolution: 40
secondaryUVMinObjectScale: 1
secondaryUVPackMargin: 4
useFileScale: 1
strictVertexDataChecks: 0
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
normalCalculationMode: 4
legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0
blendShapeNormalImportMode: 1
normalSmoothingSource: 0
referencedClips: []
importAnimation: 1
humanDescription:
serializedVersion: 3
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
globalScale: 1
rootMotionBoneName:
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
autoGenerateAvatarMappingIfUnspecified: 1
animationType: 2
humanoidOversampling: 1
avatarSetup: 0
addHumanoidExtraRootOnlyWhenUsingAvatar: 1
importBlendShapeDeformPercent: 1
remapMaterialsIfMaterialImportModeIsNone: 0
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -14,7 +14,67 @@ namespace ShapeChangerTests
[Test]
public void SetsCorrectInitialStatesAndAnimations()
{
var root = CreatePrefab("SCDefaultAnimation.prefab");
SetsCorrectInitialStatesAndAnimations("SCDefaultAnimation.prefab");
}
[Test]
public void SetsCorrectInitialStatesAndAnimationsForInactiveSC()
{
var root = CreatePrefab("SCDefaultAnimationInactive.prefab");
AvatarProcessor.ProcessAvatar(root);
var fx = (AnimatorController) FindFxController(root).animatorController;
var baseLayer = fx.layers[0];
var bt = baseLayer.stateMachine.states[0].state.motion as BlendTree;
Assert.NotNull(bt);
var subBt = bt.children[0].motion as BlendTree;
Assert.NotNull(subBt);
var clip = subBt.children[0].motion as AnimationClip;
Assert.NotNull(clip);
var smr = root.transform.Find("test mesh").GetComponent<SkinnedMeshRenderer>();
var sharedMesh = smr.sharedMesh;
var bindings = AnimationUtility.GetCurveBindings(clip);
var curve = AnimationUtility.GetEditorCurve(clip, EditorCurveBinding.FloatCurve(
"test mesh",
typeof(SkinnedMeshRenderer),
"blendShape.key1"
));
Assert.IsNull(curve); // always off MenuItem (due to object disable), no curve should be generated
curve = AnimationUtility.GetEditorCurve(clip, EditorCurveBinding.FloatCurve(
"test mesh",
typeof(SkinnedMeshRenderer),
"blendShape.key2"
));
// Always-on delete, no curve should be generated
Assert.IsNull(curve);
curve = AnimationUtility.GetEditorCurve(clip, EditorCurveBinding.FloatCurve(
"test mesh",
typeof(SkinnedMeshRenderer),
"blendShape.key3"
));
// Always-on set, no curve should be generated
Assert.IsNull(curve);
// Check actual blendshape states
Assert.AreEqual(10.0f, smr.GetBlendShapeWeight(sharedMesh.GetBlendShapeIndex("key1")), 0.1f);
Assert.AreEqual(5.0f, smr.GetBlendShapeWeight(sharedMesh.GetBlendShapeIndex("key2")), 0.1f);
Assert.AreEqual(100.0f, smr.GetBlendShapeWeight(sharedMesh.GetBlendShapeIndex("key3")), 0.1f);
}
[Test]
public void SetsCorrectInitialStatesAndAnimationsForInvertedSC()
{
SetsCorrectInitialStatesAndAnimations("SCDefaultAnimationInverted.prefab");
}
private void SetsCorrectInitialStatesAndAnimations(string prefabPath)
{
var root = CreatePrefab(prefabPath);
AvatarProcessor.ProcessAvatar(root);
var fx = (AnimatorController) FindFxController(root).animatorController;

View File

@ -46,10 +46,13 @@ MonoBehaviour:
m_EditorClassIdentifier:
m_inverted: 0
m_targetRenderer:
referencePath: test mesh
referencePath:
targetObject: {fileID: 0}
m_shapes:
- ShapeName: key2
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key2
ChangeType: 0
Value: 100
--- !u!1 &2598725701317979415
@ -98,10 +101,13 @@ MonoBehaviour:
m_EditorClassIdentifier:
m_inverted: 0
m_targetRenderer:
referencePath: test mesh
referencePath:
targetObject: {fileID: 0}
m_shapes:
- ShapeName: key1
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key1
ChangeType: 1
Value: 10
--- !u!1 &2845086157653980983
@ -150,10 +156,13 @@ MonoBehaviour:
m_EditorClassIdentifier:
m_inverted: 0
m_targetRenderer:
referencePath: test mesh
referencePath:
targetObject: {fileID: 0}
m_shapes:
- ShapeName: key3
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key3
ChangeType: 1
Value: 100
--- !u!1 &6385483934583485188
@ -174,7 +183,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
m_IsActive: 1
--- !u!4 &569625391371299408
Transform:
m_ObjectHideFlags: 0
@ -204,10 +213,13 @@ MonoBehaviour:
m_EditorClassIdentifier:
m_inverted: 0
m_targetRenderer:
referencePath: test mesh
referencePath:
targetObject: {fileID: 0}
m_shapes:
- ShapeName: key1
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key1
ChangeType: 1
Value: 20
--- !u!114 &2918390808850211981
@ -238,6 +250,7 @@ MonoBehaviour:
isSynced: 1
isSaved: 1
isDefault: 0
automaticValue: 0
--- !u!114 &664065153831629983
MonoBehaviour:
m_ObjectHideFlags: 0

View File

@ -0,0 +1,668 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1307328145036867423
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7471115643889882934}
- component: {fileID: 2015798673852064281}
m_Layer: 0
m_Name: AlwaysOffDelete
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &7471115643889882934
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1307328145036867423}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2015798673852064281
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1307328145036867423}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key2
ChangeType: 0
Value: 100
--- !u!1 &2598725701317979415
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1861262250770563182}
- component: {fileID: 8866671501173891171}
m_Layer: 0
m_Name: Toggled
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &1861262250770563182
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2598725701317979415}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8866671501173891171
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2598725701317979415}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key1
ChangeType: 1
Value: 10
--- !u!1 &2845086157653980983
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 110069860838053623}
- component: {fileID: 8218581995269956798}
m_Layer: 0
m_Name: AlwaysOffSet
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &110069860838053623
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2845086157653980983}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8218581995269956798
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2845086157653980983}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key3
ChangeType: 1
Value: 100
--- !u!1 &6385483934583485188
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 569625391371299408}
- component: {fileID: 3841502665919975468}
- component: {fileID: 2918390808850211981}
- component: {fileID: 664065153831629983}
m_Layer: 0
m_Name: InitialOffToggled
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &569625391371299408
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &3841502665919975468
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 0
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key1
ChangeType: 1
Value: 20
--- !u!114 &2918390808850211981
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3}
m_Name:
m_EditorClassIdentifier:
Control:
name:
icon: {fileID: 0}
type: 102
parameter:
name:
value: 1
style: 0
subMenu: {fileID: 0}
subParameters: []
labels: []
MenuSource: 1
menuSource_otherObjectChildren: {fileID: 0}
isSynced: 1
isSaved: 1
isDefault: 0
automaticValue: 0
--- !u!114 &664065153831629983
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3}
m_Name:
m_EditorClassIdentifier:
menuToAppend: {fileID: 0}
installTargetMenu: {fileID: 0}
--- !u!1 &6855505756433160176
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8936933457054072598}
- component: {fileID: 6580323041906195452}
- component: {fileID: 146169679456758165}
- component: {fileID: 5146811121193962360}
m_Layer: 0
m_Name: SCDefaultAnimationInactive
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8936933457054072598
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1.0024816, y: 0.25853348, z: -0.63345385}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1861262250770563182}
- {fileID: 7471115643889882934}
- {fileID: 110069860838053623}
- {fileID: 569625391371299408}
- {fileID: 1326682634762807916}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!95 &6580323041906195452
Animator:
serializedVersion: 5
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 0}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!114 &146169679456758165
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
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}
networkIDs: []
customExpressions: 0
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: 0
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: 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 &5146811121193962360
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
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!1001 &1577363430154308999
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 8936933457054072598}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalPosition.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071067
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_DirtyAABB
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_AABB.m_Extent.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_AABB.m_Extent.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_BlendShapeWeights.Array.data[0]
value: 5
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_BlendShapeWeights.Array.data[1]
value: 6
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_BlendShapeWeights.Array.data[2]
value: 7
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_Name
value: test mesh
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
--- !u!4 &1326682634762807916 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
m_PrefabInstance: {fileID: 1577363430154308999}
m_PrefabAsset: {fileID: 0}

View File

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

View File

@ -0,0 +1,668 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1307328145036867423
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7471115643889882934}
- component: {fileID: 2015798673852064281}
m_Layer: 0
m_Name: AlwaysOffDelete
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &7471115643889882934
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1307328145036867423}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2015798673852064281
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1307328145036867423}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key2
ChangeType: 0
Value: 100
--- !u!1 &2598725701317979415
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1861262250770563182}
- component: {fileID: 8866671501173891171}
m_Layer: 0
m_Name: Toggled
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &1861262250770563182
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2598725701317979415}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8866671501173891171
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2598725701317979415}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key1
ChangeType: 1
Value: 10
--- !u!1 &2845086157653980983
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 110069860838053623}
- component: {fileID: 8218581995269956798}
m_Layer: 0
m_Name: AlwaysOffSet
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!4 &110069860838053623
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2845086157653980983}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8218581995269956798
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2845086157653980983}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key3
ChangeType: 1
Value: 100
--- !u!1 &6385483934583485188
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 569625391371299408}
- component: {fileID: 3841502665919975468}
- component: {fileID: 2918390808850211981}
- component: {fileID: 664065153831629983}
m_Layer: 0
m_Name: InitialOnToggled
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &569625391371299408
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
serializedVersion: 2
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_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8936933457054072598}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &3841502665919975468
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2db441f589c3407bb6fb5f02ff8ab541, type: 3}
m_Name:
m_EditorClassIdentifier:
m_inverted: 1
m_shapes:
- Object:
referencePath: test mesh
targetObject: {fileID: 0}
ShapeName: key1
ChangeType: 1
Value: 20
--- !u!114 &2918390808850211981
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3}
m_Name:
m_EditorClassIdentifier:
Control:
name:
icon: {fileID: 0}
type: 102
parameter:
name:
value: 1
style: 0
subMenu: {fileID: 0}
subParameters: []
labels: []
MenuSource: 1
menuSource_otherObjectChildren: {fileID: 0}
isSynced: 1
isSaved: 1
isDefault: 1
automaticValue: 0
--- !u!114 &664065153831629983
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6385483934583485188}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3}
m_Name:
m_EditorClassIdentifier:
menuToAppend: {fileID: 0}
installTargetMenu: {fileID: 0}
--- !u!1 &6855505756433160176
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8936933457054072598}
- component: {fileID: 6580323041906195452}
- component: {fileID: 146169679456758165}
- component: {fileID: 5146811121193962360}
m_Layer: 0
m_Name: SCDefaultAnimationInverted
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8936933457054072598
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1.0024816, y: 0.25853348, z: -0.63345385}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1861262250770563182}
- {fileID: 7471115643889882934}
- {fileID: 110069860838053623}
- {fileID: 569625391371299408}
- {fileID: 1326682634762807916}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!95 &6580323041906195452
Animator:
serializedVersion: 5
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 0}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!114 &146169679456758165
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
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}
networkIDs: []
customExpressions: 0
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: 0
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: 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 &5146811121193962360
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6855505756433160176}
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!1001 &1577363430154308999
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 8936933457054072598}
m_Modifications:
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalPosition.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071067
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_DirtyAABB
value: 0
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_AABB.m_Extent.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_AABB.m_Extent.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_BlendShapeWeights.Array.data[0]
value: 5
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_BlendShapeWeights.Array.data[1]
value: 6
objectReference: {fileID: 0}
- target: {fileID: -3887185075125053422, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_BlendShapeWeights.Array.data[2]
value: 7
objectReference: {fileID: 0}
- target: {fileID: 919132149155446097, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
propertyPath: m_Name
value: test mesh
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
--- !u!4 &1326682634762807916 stripped
Transform:
m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: cd28f61dacdc2424d951194ff69ba154, type: 3}
m_PrefabInstance: {fileID: 1577363430154308999}
m_PrefabAsset: {fileID: 0}

View File

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

View File

@ -698,6 +698,32 @@ namespace modular_avatar_tests.VirtualMenuTests
Assert.AreEqual(4, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[5].subParameters.Length);
}
[Test]
public void MergeArmatureAndMenuInstallerOnSameObjectWorks()
{
var root = CreateRoot("root");
var armature = CreateChild(root, "Armature");
var installer = armature.AddComponent<ModularAvatarMenuInstaller>();
var merge = installer.gameObject.AddComponent<ModularAvatarMergeArmature>();
merge.mergeTarget.Set(root);
var menu = Create<VRCExpressionsMenu>();
menu.controls.Add(new VRCExpressionsMenu.Control()
{
name = "control",
type = VRCExpressionsMenu.Control.ControlType.Toggle
});
installer.menuToAppend = menu;
AvatarProcessor.ProcessAvatar(root);
var realizedMenu = root.GetComponent<VRCAvatarDescriptor>().expressionsMenu;
Assert.AreEqual(1, realizedMenu.controls.Count);
Assert.AreEqual("control", realizedMenu.controls[0].name);
}
ModularAvatarMenuInstaller CreateInstaller(string name)
{
GameObject obj = new GameObject();

View File

@ -1,5 +1,4 @@

---
---
sidebar_position: 900
---

View File

@ -23,6 +23,7 @@
justify-content: center;
column-gap: 2rem;
row-gap: 1rem;
margin-bottom: 1em;
}
@media screen and (max-width: 996px) {
@ -36,4 +37,4 @@ div.logo {
text-align: center;
display: flex;
justify-content: center;
}
}

View File

@ -29,7 +29,7 @@ function HomepageHeader() {
<p className="hero__subtitle">
<Translate>Drag-and-Drop Avatar Assembly</Translate>
</p>
<div className={`button-group ${styles.buttons}`}>
<div className={`${styles.buttons}`}>
<InstallButton/>
<Link
className={`button button--secondary button--lg ${styles.button}`}
@ -43,7 +43,7 @@ function HomepageHeader() {
<Translate>Tutorials</Translate>
</Link>
</div>
<div className={`button-group ${styles.buttons}`}>
<div className={`${styles.buttons}`}>
<a href={"https://discord.gg/dV4cVpewmM"} className={`discordLink`}>
<img className={`button button--lg ${styles.button}`}
alt="Discord"

View File

@ -1,7 +1,7 @@
{
"name": "nadena.dev.modular-avatar",
"displayName": "Modular Avatar",
"version": "1.10.0",
"version": "1.10.4",
"unity": "2022.3",
"description": "A suite of tools for assembling your avatar out of reusable components",
"author": {
@ -16,6 +16,6 @@
},
"vpmDependencies": {
"com.vrchat.avatars": ">=3.7.0",
"nadena.dev.ndmf": ">=1.5.0 <2.0.0-a"
"nadena.dev.ndmf": ">=1.5.4 <2.0.0-a"
}
}