Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Animator Parser V2.1 #1227

Merged
merged 11 commits into from
Oct 5, 2024
1 change: 1 addition & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog].

### Changed
- Animator Parser Debug Window now supports ObjectReference animation support `#1222`
- Reimplemented Animator Parser node system `#1227`

### Deprecated

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The format is based on [Keep a Changelog].
- Allow multiple component for Remove Mesh components with API `#1216` `#1218`
- This allows non-destructive tools to add Remove Mesh components even if Remove Mesh component are added before.
- Animator Parser Debug Window now supports ObjectReference animation support `#1222`
- Reimplemented Animator Parser node system `#1227`

### Deprecated

Expand Down
32 changes: 16 additions & 16 deletions Editor/AnimatorParserV2/AnimationParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,21 @@ private ImmutableNodeContainer ParseBlendTree(GameObject root, BlendTree blendTr
var children = blendTree.children;

return NodesMerger.Merge<
ImmutableNodeContainer, ImmutablePropModNode<float>, ImmutablePropModNode<Object>,
BlendTreeElement<float>, BlendTreeElement<Object>,
ImmutableNodeContainer, ImmutableNodeContainer, ImmutablePropModNode<float>,
ImmutablePropModNode<Object>,
ImmutableNodeContainer, ImmutablePropModNode<FloatValueInfo>, ImmutablePropModNode<ObjectValueInfo>,
BlendTreeElement<FloatValueInfo>, BlendTreeElement<ObjectValueInfo>,
ImmutableNodeContainer, ImmutableNodeContainer, ImmutablePropModNode<FloatValueInfo>,
ImmutablePropModNode<ObjectValueInfo>,
BlendTreeMergeProperty
>(children.Select(x => ParseMotionInner(root, x.motion, mapping)),
new BlendTreeMergeProperty(blendTree.blendType));
}

internal readonly struct BlendTreeMergeProperty :
IMergeProperty1<
ImmutableNodeContainer, ImmutablePropModNode<float>, ImmutablePropModNode<Object>,
BlendTreeElement<float>, BlendTreeElement<Object>,
ImmutableNodeContainer, ImmutableNodeContainer, ImmutablePropModNode<float>,
ImmutablePropModNode<Object>
ImmutableNodeContainer, ImmutablePropModNode<FloatValueInfo>, ImmutablePropModNode<ObjectValueInfo>,
BlendTreeElement<FloatValueInfo>, BlendTreeElement<ObjectValueInfo>,
ImmutableNodeContainer, ImmutableNodeContainer, ImmutablePropModNode<FloatValueInfo>,
ImmutablePropModNode<ObjectValueInfo>
>
{
private readonly BlendTreeType _blendType;
Expand All @@ -76,17 +76,17 @@ public BlendTreeMergeProperty(BlendTreeType blendType)
public ImmutableNodeContainer CreateContainer() => new();
public ImmutableNodeContainer GetContainer(ImmutableNodeContainer source) => source;

public BlendTreeElement<float> GetIntermediate(ImmutableNodeContainer source,
ImmutablePropModNode<float> node, int index) => new BlendTreeElement<float>(index, node);
public BlendTreeElement<FloatValueInfo> GetIntermediate(ImmutableNodeContainer source,
ImmutablePropModNode<FloatValueInfo> node, int index) => new BlendTreeElement<FloatValueInfo>(index, node);

public BlendTreeElement<Object> GetIntermediate(ImmutableNodeContainer source,
ImmutablePropModNode<Object> node, int index) => new BlendTreeElement<Object>(index, node);
public BlendTreeElement<ObjectValueInfo> GetIntermediate(ImmutableNodeContainer source,
ImmutablePropModNode<ObjectValueInfo> node, int index) => new BlendTreeElement<ObjectValueInfo>(index, node);

public ImmutablePropModNode<float> MergeNode(List<BlendTreeElement<float>> nodes, int sourceCount) =>
new BlendTreeNode<float>(nodes, _blendType, partial: nodes.Count != sourceCount);
public ImmutablePropModNode<FloatValueInfo> MergeNode(List<BlendTreeElement<FloatValueInfo>> nodes, int sourceCount) =>
new BlendTreeNode<FloatValueInfo>(nodes, _blendType, partial: nodes.Count != sourceCount);

public ImmutablePropModNode<Object> MergeNode(List<BlendTreeElement<Object>> nodes, int sourceCount) =>
new BlendTreeNode<Object>(nodes, _blendType, partial: nodes.Count != sourceCount);
public ImmutablePropModNode<ObjectValueInfo> MergeNode(List<BlendTreeElement<ObjectValueInfo>> nodes, int sourceCount) =>
new BlendTreeNode<ObjectValueInfo>(nodes, _blendType, partial: nodes.Count != sourceCount);
}

private readonly Dictionary<(GameObject, AnimationClip), ImmutableNodeContainer> _parsedAnimationCache = new();
Expand Down
90 changes: 44 additions & 46 deletions Editor/AnimatorParserV2/AnimatorControllerPropModNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,36 @@

namespace Anatawa12.AvatarOptimizer.AnimatorParsersV2
{
class HumanoidAnimatorPropModNode : ComponentPropModNode<float, Animator>
class HumanoidAnimatorPropModNode : ComponentPropModNode<FloatValueInfo, Animator>
{
public HumanoidAnimatorPropModNode(Animator component) : base(component)
{
}

public override ValueInfo<float> Value => ValueInfo<float>.Variable;
public override FloatValueInfo Value => FloatValueInfo.Variable;
public override bool AppliedAlways => true;
}

internal readonly struct PlayableLayerNodeInfo<T> : ILayer<T>
where T : notnull
internal readonly struct PlayableLayerNodeInfo<TValueInfo> : ILayer<TValueInfo>
where TValueInfo : struct, IValueInfo<TValueInfo>
{
public AnimatorWeightState Weight { get; }
public AnimatorLayerBlendingMode BlendingMode { get; }
public int LayerIndex { get; }
public readonly AnimatorControllerPropModNode<T> Node;
PropModNode<T> ILayer<T>.Node => Node;
public readonly AnimatorControllerPropModNode<TValueInfo> Node;
PropModNode<TValueInfo> ILayer<TValueInfo>.Node => Node;
IPropModNode ILayer.Node => Node;

public PlayableLayerNodeInfo(AnimatorWeightState weight, AnimatorLayerBlendingMode blendingMode,
AnimatorControllerPropModNode<T> node, int layerIndex)
AnimatorControllerPropModNode<TValueInfo> node, int layerIndex)
{
Weight = weight;
BlendingMode = blendingMode;
LayerIndex = layerIndex;
Node = node;
}

public PlayableLayerNodeInfo(AnimatorControllerPropModNode<T> node, int layerIndex)
public PlayableLayerNodeInfo(AnimatorControllerPropModNode<TValueInfo> node, int layerIndex)
{
Weight = AnimatorWeightState.AlwaysOne;
BlendingMode = AnimatorLayerBlendingMode.Override;
Expand All @@ -45,48 +45,48 @@ public PlayableLayerNodeInfo(AnimatorControllerPropModNode<T> node, int layerInd
}
}

class AnimatorPropModNode<T> : ComponentPropModNode<T, Animator>
where T : notnull
class AnimatorPropModNode<TValueInfo> : ComponentPropModNode<TValueInfo, Animator>
where TValueInfo : struct, IValueInfo<TValueInfo>
{
private readonly IEnumerable<PlayableLayerNodeInfo<T>> _layersReversed;
private readonly IEnumerable<PlayableLayerNodeInfo<TValueInfo>> _layersReversed;

public AnimatorPropModNode(Animator component,IEnumerable<PlayableLayerNodeInfo<T>> layersReversed)
public AnimatorPropModNode(Animator component,IEnumerable<PlayableLayerNodeInfo<TValueInfo>> layersReversed)
: base(component)
{
_layersReversed = layersReversed;

_appliedAlways = new Lazy<bool>(
() => NodeImplUtils.AlwaysAppliedForOverriding<T, PlayableLayerNodeInfo<T>>(_layersReversed),
() => NodeImplUtils.AlwaysAppliedForOverriding(_layersReversed),
isThreadSafe: false);

_constantInfo = new Lazy<ValueInfo<T>>(
() => NodeImplUtils.ConstantInfoForOverriding<T, PlayableLayerNodeInfo<T>>(_layersReversed),
_constantInfo = new Lazy<TValueInfo>(
() => default(TValueInfo).ConstantInfoForOverriding(_layersReversed),
isThreadSafe: false);
}


private readonly Lazy<bool> _appliedAlways;
private readonly Lazy<ValueInfo<T>> _constantInfo;
private readonly Lazy<TValueInfo> _constantInfo;

public IEnumerable<PlayableLayerNodeInfo<T>> LayersReversed => _layersReversed;
public IEnumerable<PlayableLayerNodeInfo<TValueInfo>> LayersReversed => _layersReversed;
public override bool AppliedAlways => _appliedAlways.Value;
public override ValueInfo<T> Value => _constantInfo.Value;
public override TValueInfo Value => _constantInfo.Value;
public override IEnumerable<ObjectReference> ContextReferences => base.ContextReferences.Concat(
_layersReversed.SelectMany(x => x.Node.ContextReferences));
}

internal readonly struct AnimatorLayerNodeInfo<T> : ILayer<T>
where T : notnull
internal readonly struct AnimatorLayerNodeInfo<TValueInfo> : ILayer<TValueInfo>
where TValueInfo : struct, IValueInfo<TValueInfo>
{
public AnimatorWeightState Weight { get; }
public AnimatorLayerBlendingMode BlendingMode { get; }
public int LayerIndex { get; }
public readonly AnimatorLayerPropModNode<T> Node;
PropModNode<T> ILayer<T>.Node => Node;
public readonly AnimatorLayerPropModNode<TValueInfo> Node;
PropModNode<TValueInfo> ILayer<TValueInfo>.Node => Node;
IPropModNode ILayer.Node => Node;

public AnimatorLayerNodeInfo(AnimatorWeightState weight, AnimatorLayerBlendingMode blendingMode,
AnimatorLayerPropModNode<T> node, int layerIndex)
AnimatorLayerPropModNode<TValueInfo> node, int layerIndex)
{
Weight = weight;
BlendingMode = blendingMode;
Expand All @@ -95,32 +95,30 @@ public AnimatorLayerNodeInfo(AnimatorWeightState weight, AnimatorLayerBlendingMo
}
}

class AnimatorControllerPropModNode<T> : PropModNode<T>
where T : notnull
class AnimatorControllerPropModNode<TValueInfo> : PropModNode<TValueInfo>
where TValueInfo : struct, IValueInfo<TValueInfo>
{
private readonly IEnumerable<AnimatorLayerNodeInfo<T>> _layersReversed;
private readonly IEnumerable<AnimatorLayerNodeInfo<TValueInfo>> _layersReversed;

public static AnimatorControllerPropModNode<T>? Create(List<AnimatorLayerNodeInfo<T>> value)
public static AnimatorControllerPropModNode<TValueInfo>? Create(List<AnimatorLayerNodeInfo<TValueInfo>> value)
{
if (value.Count == 0) return null;
if (value.All(x => x.BlendingMode == AnimatorLayerBlendingMode.Additive && x.Node.Value.IsConstant))
return null; // unchanged constant

value.Reverse();
return new AnimatorControllerPropModNode<T>(value);
return new AnimatorControllerPropModNode<TValueInfo>(value);
}

private AnimatorControllerPropModNode(IEnumerable<AnimatorLayerNodeInfo<T>> layersReversed) =>
private AnimatorControllerPropModNode(IEnumerable<AnimatorLayerNodeInfo<TValueInfo>> layersReversed) =>
_layersReversed = layersReversed;

public IEnumerable<AnimatorLayerNodeInfo<T>> LayersReversed => _layersReversed;
public IEnumerable<AnimatorLayerNodeInfo<TValueInfo>> LayersReversed => _layersReversed;

public override ValueInfo<T> Value =>
NodeImplUtils.ConstantInfoForOverriding<T, AnimatorLayerNodeInfo<T>>(_layersReversed);
public override TValueInfo Value => default(TValueInfo).ConstantInfoForOverriding(_layersReversed);

// we may possible to implement complex logic which simulates state machine but not for now.
public override bool AppliedAlways =>
NodeImplUtils.AlwaysAppliedForOverriding<T, AnimatorLayerNodeInfo<T>>(_layersReversed);
public override bool AppliedAlways => NodeImplUtils.AlwaysAppliedForOverriding(_layersReversed);

public override IEnumerable<ObjectReference> ContextReferences =>
_layersReversed.SelectMany(x => x.Node.ContextReferences);
Expand All @@ -133,13 +131,13 @@ internal enum AnimatorWeightState
Variable
}

internal class AnimatorLayerPropModNode<T> : ImmutablePropModNode<T>
where T : notnull
internal class AnimatorLayerPropModNode<TValueInfo> : ImmutablePropModNode<TValueInfo>
where TValueInfo : struct, IValueInfo<TValueInfo>
{
private readonly IEnumerable<AnimatorStatePropModNode<T>> _children;
private readonly IEnumerable<AnimatorStatePropModNode<TValueInfo>> _children;
private readonly bool _partial;

public AnimatorLayerPropModNode(IEnumerable<AnimatorStatePropModNode<T>> children, bool partial)
public AnimatorLayerPropModNode(ICollection<AnimatorStatePropModNode<TValueInfo>> children, bool partial)
{
// expected to pass list or array
// ReSharper disable once PossibleMultipleEnumeration
Expand All @@ -150,27 +148,27 @@ public AnimatorLayerPropModNode(IEnumerable<AnimatorStatePropModNode<T>> childre
}

public override bool AppliedAlways => !_partial && _children.All(x => x.AppliedAlways);
public override ValueInfo<T> Value => NodeImplUtils.ConstantInfoForSideBySide(_children);
public override TValueInfo Value => default(TValueInfo).ConstantInfoForSideBySide(_children);
public override IEnumerable<ObjectReference> ContextReferences => _children.SelectMany(x => x.ContextReferences);
public IEnumerable<AnimatorStatePropModNode<T>> Children => _children;
public IEnumerable<AnimatorStatePropModNode<TValueInfo>> Children => _children;
}

internal class AnimatorStatePropModNode<T> : ImmutablePropModNode<T>
where T : notnull
internal class AnimatorStatePropModNode<TValueInfo> : ImmutablePropModNode<TValueInfo>
where TValueInfo : struct, IValueInfo<TValueInfo>
{
private readonly ImmutablePropModNode<T> _node;
private readonly ImmutablePropModNode<TValueInfo> _node;
private readonly AnimatorState _state;

public AnimatorStatePropModNode(ImmutablePropModNode<T> node, AnimatorState state)
public AnimatorStatePropModNode(ImmutablePropModNode<TValueInfo> node, AnimatorState state)
{
_node = node;
_state = state;
}

public ImmutablePropModNode<T> Node => _node;
public ImmutablePropModNode<TValueInfo> Node => _node;
public AnimatorState State => _state;
public override bool AppliedAlways => _node.AppliedAlways;
public override ValueInfo<T> Value => _node.Value;
public override TValueInfo Value => _node.Value;
public override IEnumerable<ObjectReference> ContextReferences => _node.ContextReferences;
}
}
Loading
Loading