Skip to content

Commit

Permalink
Fix invalid child properties of edited managed references
Browse files Browse the repository at this point in the history
  • Loading branch information
arimger committed Jan 30, 2024
1 parent 1f6d113 commit 760c923
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 39 deletions.
33 changes: 15 additions & 18 deletions Assets/Editor Toolbox/Editor/Drawers/Helpers/DrawerDataStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,31 @@ namespace Toolbox.Editor.Drawers
/// Internal system responsible for keeping and clearing data between <see cref="UnityEditor.Editor"/>s.
/// This small system works only for attribute-based drawers and should be defined as a static field.
/// </summary>
/// <typeparam name="T">Key-related object.</typeparam>
/// <typeparam name="T1">Data to store.</typeparam>
/// <typeparam name="T2">Any type needed for storage item creation. Pass <see cref="EventArgs.Empty"/> if no additional data is needed.</typeparam>
public abstract class DrawerDataStorage<T, T1, T2> : DrawerDataStorageBase
/// <typeparam name="TKey">Key-related object.</typeparam>
/// <typeparam name="TData">Data to store.</typeparam>
/// <typeparam name="TArgs">Any type needed for storage item creation. Pass <see cref="EventArgs.Empty"/> if no additional data is needed.</typeparam>
public abstract class DrawerDataStorage<TKey, TData, TArgs> : DrawerDataStorageBase
{
protected readonly Dictionary<string, T1> items = new Dictionary<string, T1>();
protected readonly Dictionary<string, TData> items = new Dictionary<string, TData>();

protected readonly Func<T, T2, T1> createMethod;
protected readonly Action<T1> removeMethod;
protected readonly Func<TKey, TArgs, TData> createMethod;
protected readonly Action<TData> removeMethod;


public DrawerDataStorage(Func<T, T2, T1> createMethod) : this(createMethod, null)
public DrawerDataStorage(Func<TKey, TArgs, TData> createMethod) : this(createMethod, null)
{ }

public DrawerDataStorage(Func<T, T2, T1> createMethod, Action<T1> removeMethod)
public DrawerDataStorage(Func<TKey, TArgs, TData> createMethod, Action<TData> removeMethod)
{
this.createMethod = createMethod;
this.removeMethod = removeMethod;
}


protected abstract string GetKey(T context);

protected abstract string GetKey(TKey context);

/// <summary>
/// Returns and if needed creates new item.
/// </summary>
public virtual T1 ReturnItem(T context, T2 args)
public virtual TData ReturnItem(TKey context, TArgs args)
{
var key = GetKey(context);
if (items.TryGetValue(key, out var item))
Expand All @@ -47,12 +44,12 @@ public virtual T1 ReturnItem(T context, T2 args)
}
}

public virtual T1 CreateItem(T context, T2 args)
public virtual TData CreateItem(TKey context, TArgs args)
{
return CreateItem(context, args, true);
}

public virtual T1 CreateItem(T context, T2 args, bool append)
public virtual TData CreateItem(TKey context, TArgs args, bool append)
{
var item = createMethod(context, args);
if (append)
Expand All @@ -63,13 +60,13 @@ public virtual T1 CreateItem(T context, T2 args, bool append)
return item;
}

public virtual T1 AppendItem(T context, T1 item)
public virtual TData AppendItem(TKey context, TData item)
{
var key = GetKey(context);
return items[key] = item;
}

public virtual void ClearItem(T context)
public virtual void ClearItem(TKey context)
{
var key = GetKey(context);
if (removeMethod != null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
using System.Collections.Generic;

namespace Toolbox.Editor.Drawers
namespace Toolbox.Editor.Drawers
{
public abstract class DrawerDataStorageBase
{
static DrawerDataStorageBase()
{
ToolboxEditorHandler.OnEditorReload += () =>
{
for (var i = 0; i < storages.Count; i++)
{
storages[i].ClearItems();
}
};
}


protected DrawerDataStorageBase()
{
storages.Add(this);
DrawerStorageManager.AppendStorage(this);
}

~DrawerDataStorageBase()
{
storages.Remove(this);
DrawerStorageManager.RemoveStorage(this);
}


private static readonly List<DrawerDataStorageBase> storages = new List<DrawerDataStorageBase>();


/// <summary>
/// Called each time Editor is completely destroyed.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;

namespace Toolbox.Editor.Drawers
{
internal static class DrawerStorageManager
{
static DrawerStorageManager()
{
ToolboxEditorHandler.OnEditorReload -= ClearStorages;
ToolboxEditorHandler.OnEditorReload += ClearStorages;
}

private static readonly List<DrawerDataStorageBase> storages = new List<DrawerDataStorageBase>();

internal static void ClearStorages()
{
ClearStorages(null);
}

internal static void ClearStorages(Func<DrawerDataStorageBase, bool> predicate)
{
for (var i = 0; i < storages.Count; i++)
{
var storage = storages[i];
if (predicate != null && !predicate(storage))
{
continue;
}

storage.ClearItems();
}
}

internal static void AppendStorage(DrawerDataStorageBase storage)
{
storages.Add(storage);
}

internal static bool RemoveStorage(DrawerDataStorageBase storage)
{
return storages.Remove(storage);
}
}
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ private void UpdateTypeProperty(SerializedProperty property, Type targetType, Re
property.serializedObject.Update();
property.managedReferenceValue = obj;
property.serializedObject.ApplyModifiedProperties();

//NOTE: fix for invalid cached properties, e.g. changing parent's managed reference can change available children
// since we cannot check if cached property is "valid" we need to clear the whole cache
//TODO: reverse it and provide dedicated event when a managed property is changed through a dedicated handler
DrawerStorageManager.ClearStorages();
}

private Rect PrepareTypePropertyPosition(bool hasLabel, in Rect labelPosition, in Rect inputPosition, bool isPropertyExpanded)
Expand Down

0 comments on commit 760c923

Please sign in to comment.