From d1a6662f0f42602dfb5d9e56d39971a88b66b552 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 25 Oct 2023 22:47:27 +0900 Subject: [PATCH] feat: ActivenessAnimation of FindUnusedObjects --- .../FindUnusedObjectsProcessor.cs | 121 ++++++++++++++++++ .../TraceAndOptimize/GCComponentInfo.cs | 2 +- .../TraceAndOptimizeProcessor.cs | 2 + Runtime/TraceAndOptimize.cs | 2 + 4 files changed, 126 insertions(+), 1 deletion(-) diff --git a/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs b/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs index 20d049eb7..d0f0f8458 100644 --- a/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs +++ b/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs @@ -70,6 +70,7 @@ internal readonly struct FindUnusedObjectsProcessor private readonly HashSet _exclusions; private readonly bool _preserveEndBone; private readonly bool _noConfigureMergeBone; + private readonly bool _noActivenessAnimation; private readonly bool _gcDebug; public FindUnusedObjectsProcessor(BuildContext context, TraceAndOptimizeState state) @@ -79,6 +80,7 @@ public FindUnusedObjectsProcessor(BuildContext context, TraceAndOptimizeState st _modifications = state.Modifications; _preserveEndBone = state.PreserveEndBone; _noConfigureMergeBone = state.NoConfigureMergeBone; + _noActivenessAnimation = state.NoActivenessAnimation; _gcDebug = state.GCDebug; _exclusions = state.Exclusions; } @@ -95,6 +97,125 @@ public void ProcessNew() Sweep(componentInfos); if (!_noConfigureMergeBone) MergeBone(componentInfos); + if (!_noActivenessAnimation) + ActivenessAnimation(componentInfos); + } + + private void ActivenessAnimation(GCComponentInfoHolder componentInfos) + { + // entrypoint -> affected activeness animated components / GameObjects + Dictionary> entryPointActiveness = + new Dictionary>(); + + foreach (var componentInfo in componentInfos.AllInformation) + { + if (!componentInfo.Component) continue; // swept + if (componentInfo.IsEntrypoint) continue; + if (!componentInfo.BehaviourComponent) continue; + if (_modifications.GetModifiedProperties(componentInfo.Component).ContainsKey("m_Enabled")) + continue; // enabled is animated so we will not generate activeness animation + + HashSet resultSet; + using (var enumerator = componentInfo.DependantEntrypoint.Keys.GetEnumerator()) + { + System.Diagnostics.Debug.Assert(enumerator.MoveNext()); + resultSet = GetEntrypointActiveness(enumerator.Current, _modifications, _context.AvatarRootTransform); + + // resultSet.Count == 0 => no longer meaning + if (enumerator.MoveNext() && resultSet.Count != 0) + { + resultSet = new HashSet(resultSet); + + do + { + var current = GetEntrypointActiveness(enumerator.Current, _modifications, + _context.AvatarRootTransform); + resultSet.IntersectWith(current); + } while (enumerator.MoveNext() && resultSet.Count != 0); + } + } + + if (resultSet.Count == 0) + continue; // there are no common activeness animation + + resultSet.Remove(componentInfo.Component.transform); + resultSet.ExceptWith(componentInfo.Component.transform.ParentEnumerable()); + + Component commonActiveness; + // TODO: we may use all activeness with nested identity transform + // if activeness animation is not changed + if (resultSet.Count == 0) + { + // the only activeness is parent of this component so adding animation is not required + continue; + } + if (resultSet.Count == 1) + { + commonActiveness = resultSet.First(); + } + else + { + // TODO: currently this is using most-child component but I don't know is this the best. + var nonTransform = resultSet.FirstOrDefault(x => !(x is Transform)); + if (nonTransform != null) + { + // unlikely: deepest common activeness is the entrypoint component. + commonActiveness = nonTransform; + } + else + { + // likely: deepest common activeness is parent + commonActiveness = null; + foreach (var component in resultSet) + { + var transform = (Transform)component; + if (commonActiveness == null) commonActiveness = transform; + else + { + // if commonActiveness is parent of transform, transform is children of commonActiveness + if (transform.ParentEnumerable().Contains(commonActiveness)) + commonActiveness = transform; + } + } + + System.Diagnostics.Debug.Assert(commonActiveness != null); + } + } + + if (commonActiveness is Transform) + { + _context.Extension().MappingBuilder + .RecordCopyProperty(commonActiveness.gameObject, "m_IsActive", + componentInfo.Component, "m_Enabled"); + } + else + { + _context.Extension().MappingBuilder + .RecordCopyProperty(commonActiveness, "m_Enabled", + componentInfo.Component, "m_Enabled"); + } + } + + return; + + HashSet GetEntrypointActiveness(Component entryPoint, + ImmutableModificationsContainer modifications, + Transform avatarRoot) + { + if (entryPointActiveness.TryGetValue(entryPoint, out var found)) + return found; + var set = new HashSet(); + + if (modifications.GetModifiedProperties(entryPoint).ContainsKey("m_Enabled")) + set.Add(entryPoint); + + for (var transform = entryPoint.transform; transform != avatarRoot; transform = transform.parent) + if (modifications.GetModifiedProperties(transform.gameObject).ContainsKey("m_IsActive")) + set.Add(transform); + + entryPointActiveness.Add(entryPoint, set); + return set; + } } private void Mark(GCComponentInfoHolder componentInfos) diff --git a/Editor/Processors/TraceAndOptimize/GCComponentInfo.cs b/Editor/Processors/TraceAndOptimize/GCComponentInfo.cs index d2939f97e..5f5c6c760 100644 --- a/Editor/Processors/TraceAndOptimize/GCComponentInfo.cs +++ b/Editor/Processors/TraceAndOptimize/GCComponentInfo.cs @@ -29,7 +29,7 @@ private void InitializeDependencies(Transform transform, bool? parentActiveness) { if (component is Transform) continue; var activeness = ComputeActiveness(component, transformActiveness); - _dependencies.Add(transform, new GCComponentInfo(component, activeness)); + _dependencies.Add(component, new GCComponentInfo(component, activeness)); } // process children diff --git a/Editor/Processors/TraceAndOptimize/TraceAndOptimizeProcessor.cs b/Editor/Processors/TraceAndOptimize/TraceAndOptimizeProcessor.cs index 7acc465e9..e04d91d01 100644 --- a/Editor/Processors/TraceAndOptimize/TraceAndOptimizeProcessor.cs +++ b/Editor/Processors/TraceAndOptimize/TraceAndOptimizeProcessor.cs @@ -15,6 +15,7 @@ class TraceAndOptimizeState public HashSet Exclusions = new HashSet(); public bool GCDebug; public bool NoConfigureMergeBone; + public bool NoActivenessAnimation; public bool SkipFreezingNonAnimatedBlendShape; public bool SkipFreezingMeaninglessBlendShape; @@ -38,6 +39,7 @@ public void Initialize(TraceAndOptimize config) Exclusions = new HashSet(config.advancedSettings.exclusions); GCDebug = config.advancedSettings.gcDebug; NoConfigureMergeBone = config.advancedSettings.noConfigureMergeBone; + NoActivenessAnimation = config.advancedSettings.noActivenessAnimation; SkipFreezingNonAnimatedBlendShape = config.advancedSettings.skipFreezingNonAnimatedBlendShape; SkipFreezingMeaninglessBlendShape = config.advancedSettings.skipFreezingMeaninglessBlendShape; diff --git a/Runtime/TraceAndOptimize.cs b/Runtime/TraceAndOptimize.cs index ddd7bd90d..87382af52 100644 --- a/Runtime/TraceAndOptimize.cs +++ b/Runtime/TraceAndOptimize.cs @@ -49,6 +49,8 @@ public struct AdvancedSettings [ToggleLeft] public bool noConfigureMergeBone; [ToggleLeft] + public bool noActivenessAnimation; + [ToggleLeft] public bool skipFreezingNonAnimatedBlendShape; [ToggleLeft] public bool skipFreezingMeaninglessBlendShape;