mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-01 20:25:07 +08:00
fix: performance issues when RO Simulator is open for too long (#1101)
Also fix an issue where the clear overrides button doesn't work for menu item overrides. Closes: #1100
This commit is contained in:
parent
422ed5cfb1
commit
389ae4f2cc
@ -93,6 +93,17 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
private Dictionary<(int, string), bool> foldoutState = new();
|
private Dictionary<(int, string), bool> foldoutState = new();
|
||||||
private Button _btn_clear;
|
private Button _btn_clear;
|
||||||
|
|
||||||
|
private bool _refreshPending;
|
||||||
|
|
||||||
|
private void RequestRefresh()
|
||||||
|
{
|
||||||
|
if (_refreshPending) return;
|
||||||
|
|
||||||
|
_refreshPending = true;
|
||||||
|
|
||||||
|
EditorApplication.delayCall += RefreshUI;
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdatePropertyOverride(string prop, bool? enable, float f_val)
|
private void UpdatePropertyOverride(string prop, bool? enable, float f_val)
|
||||||
{
|
{
|
||||||
if (enable == null)
|
if (enable == null)
|
||||||
@ -107,7 +118,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
PropertyOverrides.Value = PropertyOverrides.Value.SetItem(prop, 0f);
|
PropertyOverrides.Value = PropertyOverrides.Value.SetItem(prop, 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorApplication.delayCall += RefreshUI;
|
RequestRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMenuItemOverride(string prop, ModularAvatarMenuItem item, bool? value)
|
private void UpdateMenuItemOverride(string prop, ModularAvatarMenuItem item, bool? value)
|
||||||
@ -126,21 +137,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
MenuItemOverrides.Value = MenuItemOverrides.Value.SetItem(prop, null);
|
MenuItemOverrides.Value = MenuItemOverrides.Value.SetItem(prop, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorApplication.delayCall += RefreshUI;
|
RequestRefresh();
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdatePropertyOverride(string prop, bool? value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
PropertyOverrides.Value = PropertyOverrides.Value.Remove(prop);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PropertyOverrides.Value = PropertyOverrides.Value.SetItem(prop, value.Value ? 1f : 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshUI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowButton(Rect rect)
|
private void ShowButton(Rect rect)
|
||||||
@ -194,7 +191,8 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
_btn_clear.clickable.clicked += () =>
|
_btn_clear.clickable.clicked += () =>
|
||||||
{
|
{
|
||||||
PropertyOverrides.Value = ImmutableDictionary<string, float>.Empty;
|
PropertyOverrides.Value = ImmutableDictionary<string, float>.Empty;
|
||||||
RefreshUI();
|
MenuItemOverrides.Value = ImmutableDictionary<string, ModularAvatarMenuItem>.Empty;
|
||||||
|
RequestRefresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
e_debugInfo = root.Q<VisualElement>("debug-info");
|
e_debugInfo = root.Q<VisualElement>("debug-info");
|
||||||
@ -209,11 +207,13 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
currentSelection = locked ? f_inspecting.value as GameObject : Selection.activeGameObject;
|
currentSelection = locked ? f_inspecting.value as GameObject : Selection.activeGameObject;
|
||||||
f_inspecting.SetValueWithoutNotify(currentSelection);
|
f_inspecting.SetValueWithoutNotify(currentSelection);
|
||||||
|
|
||||||
RefreshUI();
|
RequestRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RefreshUI()
|
private void RefreshUI()
|
||||||
{
|
{
|
||||||
|
_refreshPending = false;
|
||||||
|
|
||||||
var avatar = RuntimeUtil.FindAvatarInParents(currentSelection?.transform);
|
var avatar = RuntimeUtil.FindAvatarInParents(currentSelection?.transform);
|
||||||
|
|
||||||
if (avatar == null)
|
if (avatar == null)
|
||||||
@ -222,7 +222,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_btn_clear.SetEnabled(!PropertyOverrides.Value.IsEmpty);
|
_btn_clear.SetEnabled(!PropertyOverrides.Value.IsEmpty || !MenuItemOverrides.Value.IsEmpty);
|
||||||
|
|
||||||
e_debugInfo.style.display = DisplayStyle.Flex;
|
e_debugInfo.style.display = DisplayStyle.Flex;
|
||||||
|
|
||||||
@ -243,7 +243,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
{
|
{
|
||||||
if (self.is_enabled)
|
if (self.is_enabled)
|
||||||
{
|
{
|
||||||
self.RefreshUI();
|
self.RequestRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +254,9 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
BindOverrideToMenuItem("this-menu-override", mami);
|
BindOverrideToMenuItem("this-menu-override", mami);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string _menuItemOverrideProperty;
|
||||||
|
private ModularAvatarMenuItem _menuItemOverrideTarget;
|
||||||
|
|
||||||
private void BindOverrideToMenuItem(string overrideElemName, ModularAvatarMenuItem mami)
|
private void BindOverrideToMenuItem(string overrideElemName, ModularAvatarMenuItem mami)
|
||||||
{
|
{
|
||||||
var elem = e_debugInfo.Q<VisualElement>(overrideElemName);
|
var elem = e_debugInfo.Q<VisualElement>(overrideElemName);
|
||||||
@ -279,9 +282,20 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
else
|
else
|
||||||
soc.SetWithoutNotify(null);
|
soc.SetWithoutNotify(null);
|
||||||
|
|
||||||
soc.OnStateOverrideChanged += value => { UpdateMenuItemOverride(prop, mami, value); };
|
// Avoid multiple registration of the same delegate here by reusing the same delegate instead of binding
|
||||||
|
// these properties in a closure
|
||||||
|
_menuItemOverrideProperty = prop;
|
||||||
|
_menuItemOverrideTarget = mami;
|
||||||
|
soc.OnStateOverrideChanged += MenuItemOverrideChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MenuItemOverrideChanged(bool? obj)
|
||||||
|
{
|
||||||
|
UpdateMenuItemOverride(_menuItemOverrideProperty, _menuItemOverrideTarget, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _propertyOverrideProperty;
|
||||||
|
private float _propertyOverrideTargetValue;
|
||||||
private void BindOverrideToParameter(string overrideElemName, string property, float targetValue)
|
private void BindOverrideToParameter(string overrideElemName, string property, float targetValue)
|
||||||
{
|
{
|
||||||
var elem = e_debugInfo.Q<VisualElement>(overrideElemName);
|
var elem = e_debugInfo.Q<VisualElement>(overrideElemName);
|
||||||
@ -303,10 +317,14 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
|||||||
soc.SetWithoutNotify(null);
|
soc.SetWithoutNotify(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
soc.OnStateOverrideChanged += value =>
|
_propertyOverrideProperty = property;
|
||||||
|
_propertyOverrideTargetValue = targetValue;
|
||||||
|
soc.OnStateOverrideChanged += OnParameterOverrideChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnParameterOverrideChanged(bool? state)
|
||||||
{
|
{
|
||||||
UpdatePropertyOverride(property, value, targetValue);
|
UpdatePropertyOverride(_propertyOverrideProperty, state, _propertyOverrideTargetValue);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetAffectedBy(GameObject gameObject, Dictionary<TargetProp, AnimatedProperty> shapes)
|
private void SetAffectedBy(GameObject gameObject, Dictionary<TargetProp, AnimatedProperty> shapes)
|
||||||
|
@ -9,6 +9,7 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class AvatarObjectReference
|
public class AvatarObjectReference
|
||||||
{
|
{
|
||||||
|
private static long HIERARCHY_CHANGED_SEQ = long.MinValue;
|
||||||
private long ReferencesLockedAtFrame = long.MinValue;
|
private long ReferencesLockedAtFrame = long.MinValue;
|
||||||
|
|
||||||
public static string AVATAR_ROOT = "$$$AVATAR_ROOT$$$";
|
public static string AVATAR_ROOT = "$$$AVATAR_ROOT$$$";
|
||||||
@ -16,10 +17,19 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
|
|
||||||
[SerializeField] internal GameObject targetObject;
|
[SerializeField] internal GameObject targetObject;
|
||||||
|
|
||||||
|
private long _cacheSeq = long.MinValue;
|
||||||
private bool _cacheValid;
|
private bool _cacheValid;
|
||||||
private string _cachedPath;
|
private string _cachedPath;
|
||||||
private GameObject _cachedReference;
|
private GameObject _cachedReference;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[InitializeOnLoadMethod]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
EditorApplication.hierarchyChanged += () => HIERARCHY_CHANGED_SEQ += 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public AvatarObjectReference Clone()
|
public AvatarObjectReference Clone()
|
||||||
{
|
{
|
||||||
return new AvatarObjectReference
|
return new AvatarObjectReference
|
||||||
@ -54,10 +64,12 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
public GameObject Get(Component container)
|
public GameObject Get(Component container)
|
||||||
{
|
{
|
||||||
bool cacheValid = _cacheValid || ReferencesLockedAtFrame == Time.frameCount;
|
bool cacheValid = _cacheValid || ReferencesLockedAtFrame == Time.frameCount;
|
||||||
|
cacheValid &= HIERARCHY_CHANGED_SEQ == _cacheSeq;
|
||||||
|
|
||||||
if (cacheValid && _cachedPath == referencePath && _cachedReference != null) return _cachedReference;
|
if (cacheValid && _cachedPath == referencePath && _cachedReference != null) return _cachedReference;
|
||||||
|
|
||||||
_cacheValid = true;
|
_cacheValid = true;
|
||||||
|
_cacheSeq = HIERARCHY_CHANGED_SEQ;
|
||||||
_cachedPath = referencePath;
|
_cachedPath = referencePath;
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(referencePath))
|
if (string.IsNullOrEmpty(referencePath))
|
||||||
@ -66,9 +78,6 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
return _cachedReference;
|
return _cachedReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeUtil.OnHierarchyChanged -= InvalidateCache;
|
|
||||||
RuntimeUtil.OnHierarchyChanged += InvalidateCache;
|
|
||||||
|
|
||||||
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(container.transform);
|
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(container.transform);
|
||||||
if (avatarTransform == null) return (_cachedReference = null);
|
if (avatarTransform == null) return (_cachedReference = null);
|
||||||
|
|
||||||
@ -130,12 +139,6 @@ namespace nadena.dev.modular_avatar.core
|
|||||||
return avatarRoot.transform.Find(referencePath)?.gameObject == targetObject;
|
return avatarRoot.transform.Find(referencePath)?.gameObject == targetObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InvalidateCache()
|
|
||||||
{
|
|
||||||
RuntimeUtil.OnHierarchyChanged -= InvalidateCache;
|
|
||||||
_cacheValid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool Equals(AvatarObjectReference other)
|
protected bool Equals(AvatarObjectReference other)
|
||||||
{
|
{
|
||||||
return GetDirectTarget() == other.GetDirectTarget() && referencePath == other.referencePath;
|
return GetDirectTarget() == other.GetDirectTarget() && referencePath == other.referencePath;
|
||||||
|
Loading…
Reference in New Issue
Block a user