mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2024-12-29 02:35:06 +08:00
fix: incorrect handling of shape key deletion (#1258)
This change reworks delete handling to be more consistent with other properties, by treating it as a virtual property (`deletedShape.{blendshapeName}`) instead of a weird additional field of blendshape keys. This then fixes a number of issues (e.g. broken preview for delete keys). Fixes: #1253
This commit is contained in:
parent
c379d730ca
commit
30cafb21e4
@ -8,7 +8,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
public TargetProp TargetProp { get; }
|
||||
public string ControlParam { get; set; }
|
||||
|
||||
public bool alwaysDeleted;
|
||||
public object currentState;
|
||||
|
||||
// Objects which trigger deletion of this shape key.
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using nadena.dev.modular_avatar.animation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace nadena.dev.modular_avatar.core.editor
|
||||
@ -9,8 +8,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,15 +30,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)
|
||||
|| ControllingConditions.Any(c => c.IsConstant && !c.InitiallyActive);
|
||||
public bool IsConstantOn => IsConstant && InitiallyActive;
|
||||
|
||||
public bool IsConstantActive => IsConstant && InitiallyActive ^ Inverted;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"AGK: {TargetProp}={Value}";
|
||||
@ -57,7 +56,6 @@ 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;
|
||||
}
|
||||
|
@ -124,50 +124,55 @@ 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, renderer, currentValue, value, changer, shape);
|
||||
|
||||
key = new TargetProp
|
||||
{
|
||||
info = new AnimatedProperty(key, renderer.GetBlendShapeWeight(shapeId));
|
||||
shapeKeys[key] = info;
|
||||
TargetObject = renderer,
|
||||
PropertyName = DeletedShapePrefix + shape.ShapeName
|
||||
};
|
||||
|
||||
// Add initial state
|
||||
var agk = new ReactionRule(key, value);
|
||||
agk.Value = renderer.GetBlendShapeWeight(shapeId);
|
||||
info.actionGroups.Add(agk);
|
||||
}
|
||||
|
||||
var action = ObjectRule(key, changer, value);
|
||||
action.Inverted = _computeContext.Observe(changer, c => c.Inverted);
|
||||
var isCurrentlyActive = changer.gameObject.activeInHierarchy;
|
||||
|
||||
if (shape.ChangeType == ShapeChangeType.Delete)
|
||||
{
|
||||
action.IsDelete = true;
|
||||
|
||||
if (isCurrentlyActive) info.currentState = 100;
|
||||
|
||||
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, renderer, 0, value, changer, shape);
|
||||
}
|
||||
}
|
||||
|
||||
return shapeKeys;
|
||||
|
||||
void RegisterAction(TargetProp key, SkinnedMeshRenderer renderer, float currentValue, float value,
|
||||
ModularAvatarShapeChanger changer, ChangedShape shape)
|
||||
{
|
||||
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)
|
||||
|
@ -18,6 +18,9 @@ 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 ImmutableDictionary<string, float> ForcePropertyOverrides { get; set; } = ImmutableDictionary<string, float>.Empty;
|
||||
|
||||
@ -58,7 +61,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;
|
||||
@ -86,7 +88,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
|
||||
@ -98,7 +99,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
{
|
||||
result.Shapes = new();
|
||||
result.InitialStates = new();
|
||||
result.DeletedShapes = new();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -109,7 +109,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;
|
||||
@ -165,7 +165,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);
|
||||
}
|
||||
@ -264,18 +264,17 @@ 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())
|
||||
{
|
||||
@ -285,18 +284,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
shapes.Remove(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
var deletions = info.actionGroups.Where(agk => agk.IsDelete).ToList();
|
||||
if (deletions.Any(d => d.InitiallyActive))
|
||||
{
|
||||
// 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)
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using nadena.dev.modular_avatar.animation;
|
||||
using UnityEditor;
|
||||
@ -42,10 +41,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);
|
||||
|
||||
@ -53,8 +53,6 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
{
|
||||
ProcessShapeKey(groups);
|
||||
}
|
||||
|
||||
ProcessMeshDeletion(deletedShapes);
|
||||
}
|
||||
|
||||
private void GenerateActiveSelfProxies(Dictionary<TargetProp, AnimatedProperty> shapes)
|
||||
@ -225,30 +223,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
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,10 +290,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);
|
||||
}
|
||||
|
@ -72,8 +72,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;
|
||||
@ -83,16 +83,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;
|
||||
}
|
||||
|
||||
@ -103,15 +116,30 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
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)
|
||||
|
@ -471,7 +471,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);
|
||||
@ -504,9 +504,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);
|
||||
|
666
UnitTests~/ReactiveComponent/DeletionTest.prefab
Normal file
666
UnitTests~/ReactiveComponent/DeletionTest.prefab
Normal 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}
|
7
UnitTests~/ReactiveComponent/DeletionTest.prefab.meta
Normal file
7
UnitTests~/ReactiveComponent/DeletionTest.prefab.meta
Normal file
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a82669288fc87d94db320a2494fd76c5
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
98
UnitTests~/ReactiveComponent/ShapeDeletionAnalysis.cs
Normal file
98
UnitTests~/ReactiveComponent/ShapeDeletionAnalysis.cs
Normal 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);
|
||||
}
|
||||
}
|
11
UnitTests~/ReactiveComponent/ShapeDeletionAnalysis.cs.meta
Normal file
11
UnitTests~/ReactiveComponent/ShapeDeletionAnalysis.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18eb55e1b66a00243a91142456dfd5f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
BIN
UnitTests~/ReactiveComponent/shape deletion test mesh.fbx
Normal file
BIN
UnitTests~/ReactiveComponent/shape deletion test mesh.fbx
Normal file
Binary file not shown.
109
UnitTests~/ReactiveComponent/shape deletion test mesh.fbx.meta
Normal file
109
UnitTests~/ReactiveComponent/shape deletion test mesh.fbx.meta
Normal 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:
|
Loading…
Reference in New Issue
Block a user