Skip to content

Commit

Permalink
feat: add support for recording object replacements in ObjectRegistry (
Browse files Browse the repository at this point in the history
  • Loading branch information
bdunderscore authored Dec 22, 2023
1 parent 688f21c commit 093f07d
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased]

### Added
- API to record when one object is replaced by another

### Fixed

Expand Down
69 changes: 64 additions & 5 deletions Editor/API/ObjectRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,21 @@ public void Dispose()
}
}

internal struct Entry
{
public UnityObject Object;
public ObjectReference Reference;
}

/// <summary>
/// The ObjectRegistry tracks the original position of objects on the avatar; this is used to be able to identify
/// the source of errors after objects have been moved within the hierarchy.
/// </summary>
public sealed class ObjectRegistry
{
// Reference hash code => objects
private static readonly Dictionary<int, List<ObjectReference>> _obj2ref =
new Dictionary<int, List<ObjectReference>>();
private readonly Dictionary<int, List<Entry>> _obj2ref =
new Dictionary<int, List<Entry>>();

static internal ObjectRegistry ActiveRegistry;
internal readonly Transform AvatarRoot;
Expand All @@ -63,12 +69,12 @@ private ObjectReference _GetReference(UnityObject obj)
if (obj == null) return null;
if (!_obj2ref.TryGetValue(RuntimeHelpers.GetHashCode(obj), out var refs))
{
_obj2ref[RuntimeHelpers.GetHashCode(obj)] = refs = new List<ObjectReference>();
_obj2ref[RuntimeHelpers.GetHashCode(obj)] = refs = new List<Entry>();
}

foreach (var r in refs)
{
if (r.Object == obj) return r;
if (r.Object == obj) return r.Reference;
}

string path = null;
Expand All @@ -83,9 +89,62 @@ private ObjectReference _GetReference(UnityObject obj)

var objref = new ObjectReference(obj, path);

refs.Add(objref);
refs.Add(new Entry()
{
Object = obj,
Reference = objref
});

return objref;
}

/// <summary>
/// Record that a particular object (asset or scene object) was replaced by a clone or transformed version.
/// This will be used to track the original object in error reports.
/// </summary>
/// <param name="oldObject"></param>
/// <param name="newObject"></param>
/// <returns>The ObjectReference for the objects in question</returns>
public static ObjectReference RegisterReplacedObject(UnityObject oldObject, UnityObject newObject)
{
return RegisterReplacedObject(GetReference(oldObject), newObject);
}

/// <summary>
/// Record that a particular object (asset or scene object) was replaced by a clone or transformed version.
/// This will be used to track the original object in error reports.
/// </summary>
/// <param name="oldObject"></param>
/// <param name="newObject"></param>
/// <returns>The ObjectReference for the objects in question</returns>
public static ObjectReference RegisterReplacedObject(ObjectReference oldObject, UnityObject newObject)
{
if (ActiveRegistry == null) return oldObject;

if (oldObject == null) throw new NullReferenceException("oldObject must not be null");
if (newObject == null) throw new NullReferenceException("newObject must not be null");

if (!ActiveRegistry._obj2ref.TryGetValue(RuntimeHelpers.GetHashCode(newObject), out var refs))
{
ActiveRegistry._obj2ref[RuntimeHelpers.GetHashCode(newObject)] = refs = new List<Entry>();
}

foreach (var r in refs)
{
if (r.Object == newObject)
{
throw new ArgumentException(
"RegisterReplacedObject must be called before GetReference is called on the new object");
}
}

refs.Add(new Entry()
{
Object = newObject,
Reference = oldObject
});

return oldObject;
}
}
}

0 comments on commit 093f07d

Please sign in to comment.