diff --git a/Editor/Processors/ApplyObjectMapping.cs b/Editor/Processors/ApplyObjectMapping.cs index 4722d3e0a..c1dd18fb0 100644 --- a/Editor/Processors/ApplyObjectMapping.cs +++ b/Editor/Processors/ApplyObjectMapping.cs @@ -24,65 +24,26 @@ protected override void Execute(BuildContext context) var serialized = new SerializedObject(component); AnimatorControllerMapper mapper = null; SpecialMappingApplier.Apply(component.GetType(), serialized, mapping, ref mapper); - var p = serialized.GetIterator(); - var enterChildren = true; - while (p.Next(enterChildren)) - { - if (p.propertyType == SerializedPropertyType.ObjectReference) - { - if (mapping.MapComponentInstance(p.objectReferenceInstanceIDValue, out var mappedComponent)) - p.objectReferenceValue = mappedComponent; - if (p.objectReferenceValue is AnimatorController controller) - { - if (mapper == null) - mapper = new AnimatorControllerMapper(mapping.CreateAnimationMapper(component.gameObject)); - - // ReSharper disable once AccessToModifiedClosure - var mapped = BuildReport.ReportingObject(controller, - () => mapper.MapAnimatorController(controller)); - if (mapped != null) - p.objectReferenceValue = mapped; - } - } + foreach (var p in serialized.ObjectReferenceProperties()) + { + if (mapping.MapComponentInstance(p.objectReferenceInstanceIDValue, out var mappedComponent)) + p.objectReferenceValue = mappedComponent; - switch (p.propertyType) + if (p.objectReferenceValue is AnimatorController controller) { - case SerializedPropertyType.String: - case SerializedPropertyType.Integer: - case SerializedPropertyType.Boolean: - case SerializedPropertyType.Float: - case SerializedPropertyType.Color: - case SerializedPropertyType.ObjectReference: - case SerializedPropertyType.LayerMask: - case SerializedPropertyType.Enum: - case SerializedPropertyType.Vector2: - case SerializedPropertyType.Vector3: - case SerializedPropertyType.Vector4: - case SerializedPropertyType.Rect: - case SerializedPropertyType.ArraySize: - case SerializedPropertyType.Character: - case SerializedPropertyType.AnimationCurve: - case SerializedPropertyType.Bounds: - case SerializedPropertyType.Gradient: - case SerializedPropertyType.Quaternion: - case SerializedPropertyType.FixedBufferSize: - case SerializedPropertyType.Vector2Int: - case SerializedPropertyType.Vector3Int: - case SerializedPropertyType.RectInt: - case SerializedPropertyType.BoundsInt: - enterChildren = false; - break; - case SerializedPropertyType.Generic: - case SerializedPropertyType.ExposedReference: - case SerializedPropertyType.ManagedReference: - default: - enterChildren = true; - break; + if (mapper == null) + mapper = new AnimatorControllerMapper(mapping.CreateAnimationMapper(component.gameObject)); + + // ReSharper disable once AccessToModifiedClosure + var mapped = BuildReport.ReportingObject(controller, + () => mapper.MapAnimatorController(controller)); + if (mapped != null) + p.objectReferenceValue = mapped; } } - serialized.ApplyModifiedProperties(); + serialized.ApplyModifiedPropertiesWithoutUndo(); }); } } @@ -295,26 +256,13 @@ private T DeepClone(T original, Func visitor) where T : Objec _cache[original] = obj; - SerializedObject so = new SerializedObject(obj); - SerializedProperty prop = so.GetIterator(); - - bool enterChildren = true; - while (prop.Next(enterChildren)) + using (var so = new SerializedObject(obj)) { - enterChildren = true; - switch (prop.propertyType) - { - case SerializedPropertyType.ObjectReference: - prop.objectReferenceValue = DeepClone(prop.objectReferenceValue, visitor); - break; - // Iterating strings can get super slow... - case SerializedPropertyType.String: - enterChildren = false; - break; - } - } + foreach (var prop in so.ObjectReferenceProperties()) + prop.objectReferenceValue = DeepClone(prop.objectReferenceValue, visitor); - so.ApplyModifiedPropertiesWithoutUndo(); + so.ApplyModifiedPropertiesWithoutUndo(); + } return (T)obj; } diff --git a/Editor/Processors/SkinnedMeshes/MergeSkinnedMeshProcessor.cs b/Editor/Processors/SkinnedMeshes/MergeSkinnedMeshProcessor.cs index 9494ec09f..801c9feea 100644 --- a/Editor/Processors/SkinnedMeshes/MergeSkinnedMeshProcessor.cs +++ b/Editor/Processors/SkinnedMeshes/MergeSkinnedMeshProcessor.cs @@ -228,20 +228,17 @@ private bool CheckAnimateSubMeshIndex(OptimizerSession session, MeshInfo2[] mesh { if (component is Transform) continue; - var serialized = new SerializedObject(component); - var prop = serialized.GetIterator(); - var enterChildren = true; - while (prop.Next(enterChildren)) + using (var serialized = new SerializedObject(component)) { - enterChildren = prop.propertyType == SerializedPropertyType.Generic; - - if (prop.propertyType == SerializedPropertyType.ObjectReference && - prop.objectReferenceValue is AnimatorController controller && - controller.animationClips + foreach (var prop in serialized.ObjectReferenceProperties()) + { + if (!(prop.objectReferenceValue is AnimatorController controller)) continue; + if (controller.animationClips .SelectMany(x => AnimationUtility.GetObjectReferenceCurveBindings(x)) .Select(x => (AnimationUtility.GetAnimatedObject(component.gameObject, x), x.propertyName)) .Any(targetProperties.Contains)) - return true; + return true; + } } } return false; diff --git a/Editor/Processors/TraceAndOptimize/ComponentDependencyCollector.cs b/Editor/Processors/TraceAndOptimize/ComponentDependencyCollector.cs index 38377ab92..c05e1da16 100644 --- a/Editor/Processors/TraceAndOptimize/ComponentDependencyCollector.cs +++ b/Editor/Processors/TraceAndOptimize/ComponentDependencyCollector.cs @@ -136,52 +136,12 @@ private void FallbackDependenciesParser(Component component) dependencies.EntrypointComponent = true; using (var serialized = new SerializedObject(component)) { - var iterator = serialized.GetIterator(); - var enterChildren = true; - while (iterator.Next(enterChildren)) + foreach (var property in serialized.ObjectReferenceProperties()) { - if (iterator.propertyType == SerializedPropertyType.ObjectReference) - { - if (iterator.objectReferenceValue is GameObject go) - dependencies.AddAlwaysDependency(go.transform); - else if (iterator.objectReferenceValue is Component com) - dependencies.AddAlwaysDependency(com); - } - - switch (iterator.propertyType) - { - case SerializedPropertyType.String: - case SerializedPropertyType.Integer: - case SerializedPropertyType.Boolean: - case SerializedPropertyType.Float: - case SerializedPropertyType.Color: - case SerializedPropertyType.ObjectReference: - case SerializedPropertyType.LayerMask: - case SerializedPropertyType.Enum: - case SerializedPropertyType.Vector2: - case SerializedPropertyType.Vector3: - case SerializedPropertyType.Vector4: - case SerializedPropertyType.Rect: - case SerializedPropertyType.ArraySize: - case SerializedPropertyType.Character: - case SerializedPropertyType.AnimationCurve: - case SerializedPropertyType.Bounds: - case SerializedPropertyType.Gradient: - case SerializedPropertyType.Quaternion: - case SerializedPropertyType.FixedBufferSize: - case SerializedPropertyType.Vector2Int: - case SerializedPropertyType.Vector3Int: - case SerializedPropertyType.RectInt: - case SerializedPropertyType.BoundsInt: - enterChildren = false; - break; - case SerializedPropertyType.Generic: - case SerializedPropertyType.ExposedReference: - case SerializedPropertyType.ManagedReference: - default: - enterChildren = true; - break; - } + if (property.objectReferenceValue is GameObject go) + dependencies.AddAlwaysDependency(go.transform); + else if (property.objectReferenceValue is Component com) + dependencies.AddAlwaysDependency(com); } } } diff --git a/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs b/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs index d36283459..67cc863c7 100644 --- a/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs +++ b/Editor/Processors/TraceAndOptimize/FindUnusedObjectsProcessor.cs @@ -458,51 +458,11 @@ void AddGameObject(GameObject gameObject) using (var serialized = new SerializedObject(component)) { - var iter = serialized.GetIterator(); - var enterChildren = true; - while (iter.Next(enterChildren)) + foreach (var iter in serialized.ObjectReferenceProperties()) { - if (iter.propertyType == SerializedPropertyType.ObjectReference) - { - var value = iter.objectReferenceValue; - if (value is Component c && !EditorUtility.IsPersistent(value)) - AddGameObject(c.gameObject); - } - - switch (iter.propertyType) - { - case SerializedPropertyType.Integer: - case SerializedPropertyType.Boolean: - case SerializedPropertyType.Float: - case SerializedPropertyType.String: - case SerializedPropertyType.Color: - case SerializedPropertyType.ObjectReference: - case SerializedPropertyType.Enum: - case SerializedPropertyType.Vector2: - case SerializedPropertyType.Vector3: - case SerializedPropertyType.Vector4: - case SerializedPropertyType.Rect: - case SerializedPropertyType.ArraySize: - case SerializedPropertyType.Character: - case SerializedPropertyType.Bounds: - case SerializedPropertyType.Quaternion: - case SerializedPropertyType.FixedBufferSize: - case SerializedPropertyType.Vector2Int: - case SerializedPropertyType.Vector3Int: - case SerializedPropertyType.RectInt: - case SerializedPropertyType.BoundsInt: - enterChildren = false; - break; - case SerializedPropertyType.Generic: - case SerializedPropertyType.LayerMask: - case SerializedPropertyType.AnimationCurve: - case SerializedPropertyType.Gradient: - case SerializedPropertyType.ExposedReference: - case SerializedPropertyType.ManagedReference: - default: - enterChildren = true; - break; - } + var value = iter.objectReferenceValue; + if (value is Component c && !EditorUtility.IsPersistent(value)) + AddGameObject(c.gameObject); } } } diff --git a/Editor/Utils/Utils.ObjectReferencePropertiesEnumerable.cs b/Editor/Utils/Utils.ObjectReferencePropertiesEnumerable.cs new file mode 100644 index 000000000..b4c025a05 --- /dev/null +++ b/Editor/Utils/Utils.ObjectReferencePropertiesEnumerable.cs @@ -0,0 +1,90 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEditor; + +namespace Anatawa12.AvatarOptimizer +{ + internal partial class Utils + { + public static ObjectReferencePropertiesEnumerable ObjectReferenceProperties(this SerializedObject obj) + => new ObjectReferencePropertiesEnumerable(obj); + + public readonly struct ObjectReferencePropertiesEnumerable : IEnumerable + { + private readonly SerializedObject _obj; + + public ObjectReferencePropertiesEnumerable(SerializedObject obj) => _obj = obj; + + public Enumerator GetEnumerator() => new Enumerator(_obj); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator : IEnumerator + { + private readonly SerializedProperty _iterator; + + public Enumerator(SerializedObject obj) => _iterator = obj.GetIterator(); + + public bool MoveNext() + { + while (true) + { + bool enterChildren; + switch (_iterator.propertyType) + { + case SerializedPropertyType.String: + case SerializedPropertyType.Integer: + case SerializedPropertyType.Boolean: + case SerializedPropertyType.Float: + case SerializedPropertyType.Color: + case SerializedPropertyType.ObjectReference: + case SerializedPropertyType.LayerMask: + case SerializedPropertyType.Enum: + case SerializedPropertyType.Vector2: + case SerializedPropertyType.Vector3: + case SerializedPropertyType.Vector4: + case SerializedPropertyType.Rect: + case SerializedPropertyType.ArraySize: + case SerializedPropertyType.Character: + case SerializedPropertyType.AnimationCurve: + case SerializedPropertyType.Bounds: + case SerializedPropertyType.Gradient: + case SerializedPropertyType.Quaternion: + case SerializedPropertyType.FixedBufferSize: + case SerializedPropertyType.Vector2Int: + case SerializedPropertyType.Vector3Int: + case SerializedPropertyType.RectInt: + case SerializedPropertyType.BoundsInt: + enterChildren = false; + break; + case SerializedPropertyType.Generic: + case SerializedPropertyType.ExposedReference: + case SerializedPropertyType.ManagedReference: + default: + enterChildren = true; + break; + } + + if (!_iterator.Next(enterChildren)) return false; + if (_iterator.propertyType == SerializedPropertyType.ObjectReference) + return true; + } + } + + public void Reset() + { + var obj = _iterator.serializedObject; + Dispose(); + this = new Enumerator(obj); + } + + public SerializedProperty Current => _iterator; + object IEnumerator.Current => Current; + + public void Dispose() + { + } + } + } + } +} \ No newline at end of file diff --git a/Editor/Utils/Utils.ObjectReferencePropertiesEnumerable.cs.meta b/Editor/Utils/Utils.ObjectReferencePropertiesEnumerable.cs.meta new file mode 100644 index 000000000..2df0decfc --- /dev/null +++ b/Editor/Utils/Utils.ObjectReferencePropertiesEnumerable.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3afedfb6fd1b45b28d978c5f63de68b6 +timeCreated: 1695888802 \ No newline at end of file