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

Better activeness animation #880

Merged
merged 6 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The format is based on [Keep a Changelog].
- Bones swung by unused PhysBones (which will be removed by AAO) are not merged `#850`
- Note that To fix this problem, AnimatorParser is almost completely rewritten.
- It's not expected to have behavior change, but if you found some, please report it.
- Re-fix Nested Constraint can be broken with Trace and Optimize `#880`

### Security

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The format is based on [Keep a Changelog].
- Bones swung by unused PhysBones (which will be removed by AAO) are not merged `#850`
- Note that To fix this problem, AnimatorParser is almost completely rewritten.
- It's not expected to have behavior change, but if you found some, please report it.
- Re-fix Nested Constraint can be broken with Trace and Optimize `#880`

### Security

Expand Down
10 changes: 1 addition & 9 deletions Editor/APIInternal/ComponentInfos.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,7 @@ protected override void CollectDependency(T component, ComponentDependencyCollec
.EvenIfDependantDisabled();
for (var i = 0; i < component.sourceCount; i++)
collector.AddDependency(component.GetSource(i).sourceTransform);
var isNestedConstraint =
component.GetComponentsInChildren<IConstraint>() != null &&
component.GetComponentsInParent<IConstraint>() != null;
// for nested constraint, our optimizer may breaks the constraint
// https://github.com/anatawa12/AvatarOptimizer/issues/856
if (isNestedConstraint)
collector.MarkBehaviour();
else
collector.MarkHeavyBehaviour();
collector.MarkHeavyBehaviour();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,9 @@ public void Init(GCComponentInfo info)
public MeshInfo2 GetMeshInfoFor(SkinnedMeshRenderer renderer) =>
_collector._session.GetMeshInfoFor(renderer);

public override void MarkEntrypoint() => _info.EntrypointComponent = true;

public override void MarkHeavyBehaviour() => _info.HeavyBehaviourComponent = true;
public override void MarkBehaviour()
{
// currently NOP
}
public override void MarkEntrypoint() => _info.MarkEntrypoint();
public override void MarkHeavyBehaviour() => _info.MarkHeavyBehaviour();
public override void MarkBehaviour() => _info.MarkBehaviour();

private API.ComponentDependencyInfo AddDependencyInternal(
[NotNull] GCComponentInfo info,
Expand Down
54 changes: 46 additions & 8 deletions Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using nadena.dev.ndmf;
Expand All @@ -21,14 +22,17 @@ protected override void Execute(BuildContext context, TraceAndOptimizeState stat
internal readonly struct MarkObjectContext {
private readonly GCComponentInfoHolder _componentInfos;

private readonly Func<GCComponentInfo, Dictionary<Component, GCComponentInfo.DependencyType>> _getDependantMap;
private readonly Queue<Component> _processPending;
private readonly Component _entrypoint;

public MarkObjectContext(GCComponentInfoHolder componentInfos, Component entrypoint)
public MarkObjectContext(GCComponentInfoHolder componentInfos, Component entrypoint,
Func<GCComponentInfo, Dictionary<Component, GCComponentInfo.DependencyType>> getDependantMap)
{
_componentInfos = componentInfos;
_processPending = new Queue<Component>();
_entrypoint = entrypoint;
_getDependantMap = getDependantMap;
}

public void MarkComponent(Component component,
Expand All @@ -37,14 +41,15 @@ public void MarkComponent(Component component,
var dependencies = _componentInfos.TryGetInfo(component);
if (dependencies == null) return;

if (dependencies.DependantEntrypoint.TryGetValue(_entrypoint, out var existingFlags))
var dependantMap = _getDependantMap(dependencies);
if (dependantMap.TryGetValue(_entrypoint, out var existingFlags))
{
dependencies.DependantEntrypoint[_entrypoint] = existingFlags | type;
dependantMap[_entrypoint] = existingFlags | type;
}
else
{
_processPending.Enqueue(component);
dependencies.DependantEntrypoint.Add(_entrypoint, type);
dependantMap.Add(_entrypoint, type);
}
}

Expand Down Expand Up @@ -94,6 +99,7 @@ public void ProcessNew()
Sweep(componentInfos);
if (!_noConfigureMergeBone)
MergeBone(componentInfos);
MarkDependant(componentInfos);
if (!_noActivenessAnimation)
ActivenessAnimation(componentInfos);
}
Expand All @@ -113,7 +119,7 @@ private void ActivenessAnimation(GCComponentInfoHolder componentInfos)
continue; // enabled is animated so we will not generate activeness animation

HashSet<Component> resultSet;
using (var enumerator = componentInfo.DependantEntrypoint.Keys.GetEnumerator())
using (var enumerator = componentInfo.DependantComponents.GetEnumerator())
{
System.Diagnostics.Debug.Assert(enumerator.MoveNext());
resultSet = GetEntrypointActiveness(enumerator.Current, _context);
Expand Down Expand Up @@ -227,15 +233,16 @@ private void Mark(GCComponentInfoHolder componentInfos)
if (componentInfo.IsEntrypoint)
{
var component = componentInfo.Component;
var markContext = new MarkObjectContext(componentInfos, component);

var markContext = new MarkObjectContext(componentInfos, component, GetDependantMap);
markContext.MarkComponent(component, GCComponentInfo.DependencyType.Normal);
markContext.MarkRecursively();
}
}

if (_exclusions.Count != 0) {
// excluded GameObjects must be exists
var markContext = new MarkObjectContext(componentInfos, _context.AvatarRootTransform);
var markContext = new MarkObjectContext(componentInfos, _context.AvatarRootTransform, GetDependantMap);

foreach (var gameObject in _exclusions)
foreach (var component in gameObject.GetComponents<Component>())
Expand All @@ -244,6 +251,8 @@ private void Mark(GCComponentInfoHolder componentInfos)
markContext.MarkRecursively();
}

Dictionary<Component, GCComponentInfo.DependencyType> GetDependantMap(GCComponentInfo x) =>
x.DependantEntrypoint;
}

private void Sweep(GCComponentInfoHolder componentInfos)
Expand All @@ -268,6 +277,35 @@ private void Sweep(GCComponentInfoHolder componentInfos)
}
}

private void MarkDependant(GCComponentInfoHolder componentInfos)
{
// entrypoint for mark & sweep is active-able GameObjects
foreach (var componentInfo in componentInfos.AllInformation)
{
if (componentInfo.BehaviourComponent)
{
var component = componentInfo.Component;
var markContext = new MarkObjectContext(componentInfos, component, GetDependantMap);
markContext.MarkComponent(component, GCComponentInfo.DependencyType.Normal);
markContext.MarkRecursively();
}
}

if (_exclusions.Count != 0) {
// excluded GameObjects must be exists
var markContext = new MarkObjectContext(componentInfos, _context.AvatarRootTransform, GetDependantMap);

foreach (var gameObject in _exclusions)
foreach (var component in gameObject.GetComponents<Component>())
markContext.MarkComponent(component, GCComponentInfo.DependencyType.Normal);

markContext.MarkRecursively();
}

Dictionary<Component, GCComponentInfo.DependencyType> GetDependantMap(GCComponentInfo x) =>
x.DependantBehaviours;
}

private void MergeBone(GCComponentInfoHolder componentInfos)
{
ConfigureRecursive(_context.AvatarRootTransform, _context);
Expand Down Expand Up @@ -307,7 +345,7 @@ private void MergeBone(GCComponentInfoHolder componentInfos)
// Components must be Transform Only
if (transform.GetComponents<Component>().Length != 1) return NotMerged();
// The bone cannot be used generally
if ((componentInfos.GetInfo(transform).AllUsages & ~AllowedUsages) != 0) return NotMerged();
if ((componentInfos.GetInfo(transform).AllEntrypointUsages & ~AllowedUsages) != 0) return NotMerged();
// must not be animated
if (TransformAnimated(transform, context)) return NotMerged();

Expand Down
23 changes: 22 additions & 1 deletion Editor/Processors/TraceAndOptimize/GCComponentInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using nadena.dev.ndmf;
using UnityEngine;
Expand Down Expand Up @@ -62,6 +63,11 @@ internal class GCComponentInfo
/// </summary>
public bool HeavyBehaviourComponent = false;

/// <summary>
/// True if activeness of this component has meaning
/// </summary>
public bool BehaviourComponent => _behaviourComponent || HeavyBehaviourComponent;

/// <summary>
/// Dependencies of this component
/// </summary>
Expand All @@ -74,9 +80,18 @@ internal class GCComponentInfo
[NotNull] internal readonly Dictionary<Component, DependencyType> DependantEntrypoint =
new Dictionary<Component, DependencyType>();

/// <summary>
/// Dependants entrypoint components
/// </summary>
[NotNull] internal readonly Dictionary<Component, DependencyType> DependantBehaviours =
new Dictionary<Component, DependencyType>();

internal IEnumerable<Component> DependantComponents =>
DependantEntrypoint.Keys.Concat(DependantBehaviours.Keys);

internal readonly Component Component;

public DependencyType AllUsages
public DependencyType AllEntrypointUsages
{
get
{
Expand All @@ -90,6 +105,7 @@ public DependencyType AllUsages
public bool IsEntrypoint => EntrypointComponent && Activeness != false;

public readonly bool? Activeness;
private bool _behaviourComponent = false;

public GCComponentInfo(Component component, bool? activeness)
{
Expand All @@ -98,6 +114,11 @@ public GCComponentInfo(Component component, bool? activeness)
Activeness = activeness;
}


public void MarkEntrypoint() => EntrypointComponent = true;
public void MarkHeavyBehaviour() => HeavyBehaviourComponent = true;
public void MarkBehaviour() => _behaviourComponent = true;

[Flags]
public enum DependencyType : byte
{
Expand Down
Loading