feat: object references are now corrected when their target path is renamed/changes (#1323)

This commit is contained in:
bd_ 2024-10-27 10:07:23 -07:00 committed by GitHub
parent 1153abd16e
commit 32ea6678f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 8 deletions

View File

@ -11,30 +11,51 @@ namespace nadena.dev.modular_avatar.core
{ {
private static ComputeContext _context; private static ComputeContext _context;
private static PrefabStage _lastStage; private static int? _lastStage;
private static int? GetCurrentContentsRootId(out GameObject contentsRoot)
{
contentsRoot = null;
var stage = PrefabStageUtility.GetCurrentPrefabStage();
if (stage == null || stage.prefabContentsRoot == null) return null;
contentsRoot = stage.prefabContentsRoot;
return stage.prefabContentsRoot.GetInstanceID();
}
[InitializeOnLoadMethod] [InitializeOnLoadMethod]
private static void Init() private static void Init()
{ {
EditorApplication.delayCall += ProcessObjectReferences; EditorApplication.delayCall += ProcessObjectReferences;
EditorApplication.update += () => EditorApplication.update += () =>
{ {
if (PrefabStageUtility.GetCurrentPrefabStage() != _lastStage) _context?.Invalidate?.Invoke(); var curStage = GetCurrentContentsRootId(out _);
Debug.Log($"{_lastStage} => {curStage}");
if (curStage != _lastStage)
{
_context?.Invalidate?.Invoke();
}
}; };
} }
private static void ProcessObjectReferences() private static void ProcessObjectReferences()
{ {
_lastStage = PrefabStageUtility.GetCurrentPrefabStage(); _lastStage = GetCurrentContentsRootId(out var contentsRoot);
AvatarObjectReference.InvalidateAll();
_context = new ComputeContext("ObjectReferenceFixer"); _context = new ComputeContext("ObjectReferenceFixer");
_context.InvokeOnInvalidate<object>(typeof(ObjectReferenceFixer), _ => ProcessObjectReferences()); _context.InvokeOnInvalidate<object>(typeof(ObjectReferenceFixer), _ => ProcessObjectReferences());
IEnumerable<IHaveObjReferences> withReferences = _context.GetComponentsByType<IHaveObjReferences>(); IEnumerable<IHaveObjReferences> withReferences = _context.GetComponentsByType<IHaveObjReferences>();
if (_lastStage != null) if (contentsRoot != null)
withReferences = withReferences =
withReferences.Concat( withReferences.Concat(
_context.GetComponentsInChildren<IHaveObjReferences>(_lastStage.prefabContentsRoot, true) _context.GetComponentsInChildren<IHaveObjReferences>(contentsRoot, true)
); );
foreach (var obj in withReferences) foreach (var obj in withReferences)
@ -56,10 +77,26 @@ namespace nadena.dev.modular_avatar.core
foreach (var (targetObject, referencePath, objRef) in references) foreach (var (targetObject, referencePath, objRef) in references)
{ {
if (targetObject == null) continue; var resolvedTarget = objRef.Get(component);
_context.ObservePath(targetObject.transform); if (objRef.Get(component) == null) continue;
if (targetObject == null)
{
Undo.RecordObject(component, "");
objRef.targetObject = resolvedTarget;
dirty = true;
}
else
{
// Direct object reference always wins in the event of a conflict.
resolvedTarget = targetObject;
}
if (!targetObject.transform.IsChildOf(avatar.transform)) continue; foreach (var t in _context.ObservePath(resolvedTarget.transform))
{
_context.Observe(t.gameObject, g => g.name);
}
if (!resolvedTarget.transform.IsChildOf(avatar.transform)) continue;
if (objRef.IsConsistent(avatar)) continue; if (objRef.IsConsistent(avatar)) continue;

View File

@ -29,6 +29,11 @@ namespace nadena.dev.modular_avatar.core
EditorApplication.hierarchyChanged += () => HIERARCHY_CHANGED_SEQ += 1; EditorApplication.hierarchyChanged += () => HIERARCHY_CHANGED_SEQ += 1;
} }
#endif #endif
internal static void InvalidateAll()
{
HIERARCHY_CHANGED_SEQ++;
}
public AvatarObjectReference Clone() public AvatarObjectReference Clone()
{ {