Skip to content

Commit

Permalink
Merge pull request #137 from anatawa12/remake-object-mapping-system
Browse files Browse the repository at this point in the history
Remake object mapping system
  • Loading branch information
anatawa12 authored May 9, 2023
2 parents 71facc8 + ab8f1e5 commit 622589c
Show file tree
Hide file tree
Showing 19 changed files with 885 additions and 63 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ The format is based on [Keep a Changelog].
- This is based on Modular Avatar's Error Reporting Window. thanks `@bdunderscore`

### Changed
- Improved & reimplemented Animation (re)generation system `#137`
- This is completely internal changes. Should not break your project
- In previous implementation, animations for GameObjects moved by MergeBone, MergePhysBone or else doesn't work well
- This reimplementation should fix this problem

### Deprecated

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ The format is based on [Keep a Changelog].
- This is based on Modular Avatar's Error Reporting Window. thanks `@bdunderscore`

### Changed
- Improved & reimplemented Animation (re)generation system `#137`
- This is completely internal changes. Should not break your project
- In previous implementation, animations for GameObjects moved by MergeBone, MergePhysBone or else doesn't work well
- This reimplementation should fix this problem

### Deprecated

Expand Down
457 changes: 457 additions & 0 deletions Editor/ObjectMapping.cs

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions Editor/ObjectMapping.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion Editor/OptimizerSession.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Anatawa12.AvatarOptimizer
{
Expand All @@ -12,6 +14,7 @@ internal class OptimizerSession
private readonly List<Object> _toDestroy = new List<Object>();
private readonly HashSet<Object> _added = new HashSet<Object>();
private readonly DummyObject _assetFileObject;
public ObjectMappingBuilder MappingBuilder { get; }

public OptimizerSession(GameObject rootObject, bool addToAsset)
{
Expand All @@ -24,10 +27,11 @@ public OptimizerSession(GameObject rootObject, bool addToAsset)
{
_assetFileObject = null;
}

MappingBuilder = new ObjectMappingBuilder(rootObject);
}

public void AddObjectMapping<T>(T oldValue, T newValue) where T : Object => _mapping[oldValue] = newValue;
internal Dictionary<Object, Object> GetMapping() => _mapping;

public void Destroy(Object merge) => _toDestroy.Add(merge);
internal List<Object> GetObjectsToDestroy() => _toDestroy;
Expand Down Expand Up @@ -65,5 +69,11 @@ public void MarkDirtyAll()
foreach (var o in _added)
EditorUtility.SetDirty(o);
}

public string RelativePath(Transform child)
{
return Utils.RelativePath(_rootObject.transform, child) ??
throw new ArgumentException("child is not child of rootObject", nameof(child));
}
}
}
55 changes: 20 additions & 35 deletions Editor/Processors/ApplyObjectMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.Assertions;
using Object = UnityEngine.Object;

namespace Anatawa12.AvatarOptimizer.Processors
Expand All @@ -14,8 +13,7 @@ internal class ApplyObjectMapping
{
public void Apply(OptimizerSession session)
{
var mapping = session.GetMapping();
mapping.FlattenMapping();
var mapping = session.MappingBuilder.BuildObjectMapping();

// replace all objects
foreach (var component in session.GetComponents<Component>())
Expand All @@ -27,13 +25,15 @@ public void Apply(OptimizerSession session)
{
if (p.propertyType == SerializedPropertyType.ObjectReference)
{
if (p.objectReferenceValue != null)
if (mapping.TryGetValue(p.objectReferenceValue, out var mapped))
p.objectReferenceValue = mapped;
if (mapping.InstanceIdToComponent.TryGetValue(p.objectReferenceInstanceIDValue,
out var mappedComponent))
p.objectReferenceValue = mappedComponent.component;

if (p.objectReferenceValue is AnimatorController controller)
{
if (mapper == null)
mapper = new AnimatorControllerMapper(mapping, component.transform, session);
mapper = new AnimatorControllerMapper(mapping,
session.RelativePath(component.transform), session);

// ReSharper disable once AccessToModifiedClosure
var mapped = BuildReport.ReportingObject(controller,
Expand All @@ -51,26 +51,17 @@ public void Apply(OptimizerSession session)

internal class AnimatorControllerMapper
{
private readonly Dictionary<(string, Type), string> _mapping = new Dictionary<(string, Type), string>();
private readonly ObjectMapping _mapping;
private readonly Dictionary<Object, Object> _cache = new Dictionary<Object, Object>();
private readonly OptimizerSession _session;
private readonly string _rootPath;
private bool _mapped = false;

public AnimatorControllerMapper(Dictionary<Object, Object> mapping, Transform root, OptimizerSession session)
public AnimatorControllerMapper(ObjectMapping mapping, string rootPath, OptimizerSession session)
{
_session = session;
foreach (var kvp in mapping)
{
if (!(kvp.Key is Component key)) continue;
if (kvp.Value == null) continue;
Assert.AreEqual(key.GetType(), kvp.Value.GetType());
var value = (Component) kvp.Value;
var relativeKey = Utils.RelativePath(root, key.transform);
if (relativeKey == null) continue;
var relativeValue = Utils.RelativePath(root, value.transform);
if (relativeValue == null) continue;
_mapping[(relativeKey, key.GetType())] = relativeValue;
}
_mapping = mapping;
_rootPath = rootPath;
}

public AnimatorController MapAnimatorController(AnimatorController controller)
Expand Down Expand Up @@ -115,18 +106,20 @@ private Object CustomClone(Object o)

foreach (var binding in AnimationUtility.GetCurveBindings(clip))
{
var newBinding = binding;
newBinding.path = MapPath(binding.path, binding.type);
var newBinding = _mapping.MapPath(_rootPath, binding);
_mapped |= newBinding != binding;
if (newBinding.type == null) continue;
newClip.SetCurve(newBinding.path, newBinding.type, newBinding.propertyName,
AnimationUtility.GetEditorCurve(clip, binding));
}

foreach (var objBinding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
foreach (var binding in AnimationUtility.GetObjectReferenceCurveBindings(clip))
{
var newBinding = objBinding;
newBinding.path = MapPath(objBinding.path, objBinding.type);
var newBinding = _mapping.MapPath(_rootPath, binding);
_mapped |= newBinding != binding;
if (newBinding.type == null) continue;
AnimationUtility.SetObjectReferenceCurve(newClip, newBinding,
AnimationUtility.GetObjectReferenceCurve(clip, objBinding));
AnimationUtility.GetObjectReferenceCurve(clip, binding));
}

newClip.wrapMode = clip.wrapMode;
Expand All @@ -143,14 +136,6 @@ private Object CustomClone(Object o)
}
}

private string MapPath(string bindingPath, Type bindingType)
{
if (!_mapping.TryGetValue((bindingPath, bindingType), out var newPath))
return bindingPath;
_mapped = true;
return newPath;
}

// https://github.com/bdunderscore/modular-avatar/blob/db49e2e210bc070671af963ff89df853ae4514a5/Packages/nadena.dev.modular-avatar/Editor/AnimatorMerger.cs#LL242-L340C10
// Originally under MIT License
// Copyright (c) 2022 bd_
Expand Down
18 changes: 2 additions & 16 deletions Editor/Processors/DeleteGameObjectProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,9 @@ public void Process(OptimizerSession session)
{
BuildReport.ReportingObjects(session.GetComponents<DeleteGameObject>(), mergePhysBone =>
{
void Destroy(Object obj)
{
session.Destroy(obj);
session.AddObjectMapping(obj, null);
}

session.MappingBuilder.RecordRemoveGameObject(mergePhysBone.gameObject);
mergePhysBone.transform.parent = null;
Destroy(mergePhysBone.gameObject);
foreach (var component in mergePhysBone.GetComponents<Component>())
Destroy(component);
mergePhysBone.transform.WalkChildren(x =>
{
Destroy(x.gameObject);
foreach (var component in x.GetComponents<Component>())
Destroy(component);
return true;
});
session.Destroy(mergePhysBone.gameObject);
});
}
}
Expand Down
9 changes: 6 additions & 3 deletions Editor/Processors/MakeChildrenProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Anatawa12.AvatarOptimizer.ErrorReporting;
using System.Linq;

namespace Anatawa12.AvatarOptimizer.Processors
{
Expand All @@ -8,9 +9,11 @@ public void Process(OptimizerSession session)
{
BuildReport.ReportingObjects(session.GetComponents<MakeChildren>(), makeChildren =>
{
foreach (var makeChildrenChild in makeChildren.children.GetAsSet())
if (makeChildrenChild)
makeChildrenChild.parent = makeChildren.transform;
foreach (var makeChildrenChild in makeChildren.children.GetAsSet().Where(x => x))
{
session.MappingBuilder.RecordMoveObject(makeChildrenChild.gameObject, makeChildren.gameObject);
makeChildrenChild.parent = makeChildren.transform;
}
});
}
}
Expand Down
4 changes: 4 additions & 0 deletions Editor/Processors/MergeBoneProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ public void Process(OptimizerSession session)
var mapping = pair.Key;
var mapped = pair.Value;
foreach (var child in mapping.DirectChildrenEnumerable())
{
session.MappingBuilder.RecordMoveObject(child.gameObject, mapped.gameObject);
child.parent = mapped;
}

session.Destroy(mapping.gameObject);
session.MappingBuilder.RecordRemoveGameObject(mapping.gameObject);
}
}

Expand Down
14 changes: 11 additions & 3 deletions Editor/Processors/MergePhysBoneProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ internal static void DoMerge(MergePhysBone merge, OptimizerSession session)
return; // error reported by validator

foreach (var physBone in sourceComponents)
physBone.GetTarget().parent = root;
{
var pbTarget = physBone.GetTarget();
session.MappingBuilder.RecordMoveObject(pbTarget.gameObject, root.gameObject);
pbTarget.parent = root;
}
}
else
{
Expand All @@ -58,10 +62,14 @@ internal static void DoMerge(MergePhysBone merge, OptimizerSession session)
}
else
{
root = Utils.NewGameObject("PhysBoneRoot", pb.GetTarget().parent).transform;
root = Utils.NewGameObject($"PhysBoneRoot-{Guid.NewGuid()}", pb.GetTarget().parent).transform;

foreach (var physBone in sourceComponents)
physBone.GetTarget().parent = root;
{
var pbTarget = physBone.GetTarget();
session.MappingBuilder.RecordMoveObject(pbTarget.gameObject, root.gameObject);
pbTarget.parent = root;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ internal abstract class EditSkinnedMeshProcessor<TComponent> : IEditSkinnedMeshP
public abstract int ProcessOrder { get; }
public IEnumerable<SkinnedMeshRenderer> Dependencies => Array.Empty<SkinnedMeshRenderer>();
protected TComponent Component { get; }
[Obsolete]
public SkinnedMeshRenderer Target { get; }

EditSkinnedMeshComponent IEditSkinnedMeshProcessor.Component => Component;
Expand Down
14 changes: 14 additions & 0 deletions Editor/Processors/SkinnedMeshes/FreezeBlendShapeProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,22 @@ public override void Process(OptimizerSession session, MeshInfo2 target, MeshInf
{
int srcI = 0, dstI = 0;
for (; srcI < target.BlendShapes.Count; srcI++)
{
if (!freezes[srcI])
{
// for keep prop: move the BlendShape index. name is not changed.
session.MappingBuilder.RecordMoveProperty(Target,
VProp.BlendShapeIndex(srcI),
VProp.BlendShapeIndex(dstI));
target.BlendShapes[dstI++] = target.BlendShapes[srcI];
}
else
{
// for frozen prop: remove that BlendShape
session.MappingBuilder.RecordRemoveProperty(Target, VProp.BlendShapeIndex(srcI));
session.MappingBuilder.RecordRemoveProperty(Target, $"blendShape.{target.BlendShapes[srcI].name}");
}
}

target.BlendShapes.RemoveRange(dstI, target.BlendShapes.Count - dstI);
}
Expand Down
16 changes: 13 additions & 3 deletions Editor/Processors/SkinnedMeshes/MergeSkinnedMeshProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,19 @@ TexCoordStatus TexCoordStatusMax(TexCoordStatus x, TexCoordStatus y) =>
target.SubMeshes[subMeshIndexMap[i][j]].Triangles.AddRange(meshInfo.SubMeshes[j].Triangles);

// add blend shape if not defined by name
foreach (var (name, weight) in meshInfo.BlendShapes)
if (target.BlendShapes.FindIndex(x => x.name == name) == -1)
for (var sourceI = 0; sourceI < meshInfo.BlendShapes.Count; sourceI++)
{
var (name, weight) = meshInfo.BlendShapes[sourceI];
var newIndex = target.BlendShapes.FindIndex(x => x.name == name);
if (newIndex == -1)
{
newIndex = target.BlendShapes.Count - 1;
target.BlendShapes.Add((name, weight));
}

session.MappingBuilder.RecordMoveProperty(meshInfo.SourceRenderer,
VProp.BlendShapeIndex(sourceI), VProp.BlendShapeIndex(newIndex));
}

target.Bones.AddRange(meshInfo.Bones);

Expand All @@ -62,7 +72,7 @@ TexCoordStatus TexCoordStatusMax(TexCoordStatus x, TexCoordStatus y) =>

foreach (var renderer in Component.renderersSet.GetAsSet())
{
session.AddObjectMapping(renderer, Target);
session.MappingBuilder.RecordMoveComponent(renderer, Component.gameObject);
session.Destroy(renderer);

// process removeEmptyRendererObject
Expand Down
3 changes: 3 additions & 0 deletions Editor/Processors/SkinnedMeshes/MeshInfo2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Anatawa12.AvatarOptimizer.Processors.SkinnedMeshes
{
internal class MeshInfo2
{
public readonly Renderer SourceRenderer;
public Bounds Bounds;
public readonly List<Vertex> Vertices = new List<Vertex>(0);

Expand All @@ -29,6 +30,7 @@ internal class MeshInfo2

public MeshInfo2(SkinnedMeshRenderer renderer)
{
SourceRenderer = renderer;
var mesh = renderer.sharedMesh ? renderer.sharedMesh : new Mesh();
ReadSkinnedMesh(mesh);

Expand All @@ -52,6 +54,7 @@ public MeshInfo2(SkinnedMeshRenderer renderer)

public MeshInfo2(MeshRenderer renderer)
{
SourceRenderer = renderer;
var mesh = renderer.GetComponent<MeshFilter>().sharedMesh;
ReadStaticMesh(mesh);

Expand Down
Loading

0 comments on commit 622589c

Please sign in to comment.