mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2024-12-29 02:35:06 +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 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)
|
||||
{
|
||||
if (enable == null)
|
||||
@ -106,8 +117,8 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
||||
{
|
||||
PropertyOverrides.Value = PropertyOverrides.Value.SetItem(prop, 0f);
|
||||
}
|
||||
|
||||
EditorApplication.delayCall += RefreshUI;
|
||||
|
||||
RequestRefresh();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
EditorApplication.delayCall += RefreshUI;
|
||||
}
|
||||
|
||||
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();
|
||||
RequestRefresh();
|
||||
}
|
||||
|
||||
private void ShowButton(Rect rect)
|
||||
@ -194,7 +191,8 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
||||
_btn_clear.clickable.clicked += () =>
|
||||
{
|
||||
PropertyOverrides.Value = ImmutableDictionary<string, float>.Empty;
|
||||
RefreshUI();
|
||||
MenuItemOverrides.Value = ImmutableDictionary<string, ModularAvatarMenuItem>.Empty;
|
||||
RequestRefresh();
|
||||
};
|
||||
|
||||
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;
|
||||
f_inspecting.SetValueWithoutNotify(currentSelection);
|
||||
|
||||
RefreshUI();
|
||||
RequestRefresh();
|
||||
}
|
||||
|
||||
private void RefreshUI()
|
||||
{
|
||||
_refreshPending = false;
|
||||
|
||||
var avatar = RuntimeUtil.FindAvatarInParents(currentSelection?.transform);
|
||||
|
||||
if (avatar == null)
|
||||
@ -221,8 +221,8 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
||||
e_debugInfo.style.display = DisplayStyle.None;
|
||||
return;
|
||||
}
|
||||
|
||||
_btn_clear.SetEnabled(!PropertyOverrides.Value.IsEmpty);
|
||||
|
||||
_btn_clear.SetEnabled(!PropertyOverrides.Value.IsEmpty || !MenuItemOverrides.Value.IsEmpty);
|
||||
|
||||
e_debugInfo.style.display = DisplayStyle.Flex;
|
||||
|
||||
@ -243,7 +243,7 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
private string _menuItemOverrideProperty;
|
||||
private ModularAvatarMenuItem _menuItemOverrideTarget;
|
||||
|
||||
private void BindOverrideToMenuItem(string overrideElemName, ModularAvatarMenuItem mami)
|
||||
{
|
||||
var elem = e_debugInfo.Q<VisualElement>(overrideElemName);
|
||||
@ -279,9 +282,20 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
||||
else
|
||||
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)
|
||||
{
|
||||
var elem = e_debugInfo.Q<VisualElement>(overrideElemName);
|
||||
@ -302,11 +316,15 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
|
||||
{
|
||||
soc.SetWithoutNotify(null);
|
||||
}
|
||||
|
||||
soc.OnStateOverrideChanged += value =>
|
||||
{
|
||||
UpdatePropertyOverride(property, value, targetValue);
|
||||
};
|
||||
|
||||
_propertyOverrideProperty = property;
|
||||
_propertyOverrideTargetValue = targetValue;
|
||||
soc.OnStateOverrideChanged += OnParameterOverrideChanged;
|
||||
}
|
||||
|
||||
private void OnParameterOverrideChanged(bool? state)
|
||||
{
|
||||
UpdatePropertyOverride(_propertyOverrideProperty, state, _propertyOverrideTargetValue);
|
||||
}
|
||||
|
||||
private void SetAffectedBy(GameObject gameObject, Dictionary<TargetProp, AnimatedProperty> shapes)
|
||||
|
@ -9,17 +9,27 @@ namespace nadena.dev.modular_avatar.core
|
||||
[Serializable]
|
||||
public class AvatarObjectReference
|
||||
{
|
||||
private static long HIERARCHY_CHANGED_SEQ = long.MinValue;
|
||||
private long ReferencesLockedAtFrame = long.MinValue;
|
||||
|
||||
public static string AVATAR_ROOT = "$$$AVATAR_ROOT$$$";
|
||||
public string referencePath;
|
||||
|
||||
[SerializeField] internal GameObject targetObject;
|
||||
|
||||
|
||||
private long _cacheSeq = long.MinValue;
|
||||
private bool _cacheValid;
|
||||
private string _cachedPath;
|
||||
private GameObject _cachedReference;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoadMethod]
|
||||
private static void Init()
|
||||
{
|
||||
EditorApplication.hierarchyChanged += () => HIERARCHY_CHANGED_SEQ += 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
public AvatarObjectReference Clone()
|
||||
{
|
||||
return new AvatarObjectReference
|
||||
@ -54,10 +64,12 @@ namespace nadena.dev.modular_avatar.core
|
||||
public GameObject Get(Component container)
|
||||
{
|
||||
bool cacheValid = _cacheValid || ReferencesLockedAtFrame == Time.frameCount;
|
||||
cacheValid &= HIERARCHY_CHANGED_SEQ == _cacheSeq;
|
||||
|
||||
if (cacheValid && _cachedPath == referencePath && _cachedReference != null) return _cachedReference;
|
||||
|
||||
_cacheValid = true;
|
||||
_cacheSeq = HIERARCHY_CHANGED_SEQ;
|
||||
_cachedPath = referencePath;
|
||||
|
||||
if (string.IsNullOrEmpty(referencePath))
|
||||
@ -66,9 +78,6 @@ namespace nadena.dev.modular_avatar.core
|
||||
return _cachedReference;
|
||||
}
|
||||
|
||||
RuntimeUtil.OnHierarchyChanged -= InvalidateCache;
|
||||
RuntimeUtil.OnHierarchyChanged += InvalidateCache;
|
||||
|
||||
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(container.transform);
|
||||
if (avatarTransform == null) return (_cachedReference = null);
|
||||
|
||||
@ -129,13 +138,7 @@ namespace nadena.dev.modular_avatar.core
|
||||
if (referencePath == AVATAR_ROOT) return targetObject == avatarRoot;
|
||||
return avatarRoot.transform.Find(referencePath)?.gameObject == targetObject;
|
||||
}
|
||||
|
||||
private void InvalidateCache()
|
||||
{
|
||||
RuntimeUtil.OnHierarchyChanged -= InvalidateCache;
|
||||
_cacheValid = false;
|
||||
}
|
||||
|
||||
|
||||
protected bool Equals(AvatarObjectReference other)
|
||||
{
|
||||
return GetDirectTarget() == other.GetDirectTarget() && referencePath == other.referencePath;
|
||||
|
Loading…
Reference in New Issue
Block a user