Merge remote-tracking branch 'bd/main' into enhancement/AddSubMenuCreatorModule

# Conflicts:
#	Packages/nadena.dev.modular-avatar/Editor/AvatarProcessor.cs
This commit is contained in:
raiti-chan 2022-12-18 22:17:40 +09:00
commit c2bca1ec25
9 changed files with 175 additions and 17 deletions

View File

@ -1,10 +1,10 @@
{ {
"dependencies": { "dependencies": {
"com.unity.collab-proxy": "1.10.2", "com.unity.collab-proxy": "1.10.2",
"com.unity.ide.rider": "3.0.16", "com.unity.ide.rider": "3.0.17",
"com.unity.ide.visualstudio": "2.0.11", "com.unity.ide.visualstudio": "2.0.17",
"com.unity.ide.vscode": "1.2.4", "com.unity.ide.vscode": "1.2.5",
"com.unity.test-framework": "1.1.29", "com.unity.test-framework": "1.1.33",
"com.unity.textmeshpro": "2.1.6", "com.unity.textmeshpro": "2.1.6",
"com.unity.timeline": "1.2.18", "com.unity.timeline": "1.2.18",
"com.unity.ugui": "1.0.0", "com.unity.ugui": "1.0.0",

View File

@ -23,6 +23,9 @@
*/ */
using UnityEditor; using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
{ {
@ -45,10 +48,10 @@ namespace nadena.dev.modular_avatar.core.editor
{ {
EditorApplication.playModeStateChanged += OnPlayModeStateChanged; EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
RuntimeUtil.OnDemandProcessAvatar = MaybeProcessAvatar; RuntimeUtil.OnDemandProcessAvatar = MaybeProcessAvatar;
Menu.SetChecked(MENU_NAME, ModularAvatarSettings.applyOnPlay); EditorApplication.delayCall += () => Menu.SetChecked(MENU_NAME, ModularAvatarSettings.applyOnPlay);
} }
private static void MaybeProcessAvatar(RuntimeUtil.OnDemandSource source, AvatarTagComponent component) private static void MaybeProcessAvatar(RuntimeUtil.OnDemandSource source, MonoBehaviour component)
{ {
if (ModularAvatarSettings.applyOnPlay && source == armedSource && component != null) if (ModularAvatarSettings.applyOnPlay && source == armedSource && component != null)
{ {

View File

@ -40,6 +40,12 @@ namespace nadena.dev.modular_avatar.core.editor
// Place after EditorOnly processing (which runs at -1024) but hopefully before most other user callbacks // Place after EditorOnly processing (which runs at -1024) but hopefully before most other user callbacks
public int callbackOrder => -25; public int callbackOrder => -25;
/// <summary>
/// Avoid recursive activation of avatar processing by suppressing starting processing while processing is
/// already in progress.
/// </summary>
private static bool nowProcessing = false;
public delegate void AvatarProcessorCallback(GameObject obj); public delegate void AvatarProcessorCallback(GameObject obj);
/// <summary> /// <summary>
@ -117,12 +123,16 @@ namespace nadena.dev.modular_avatar.core.editor
public static void ProcessAvatar(GameObject avatarGameObject) public static void ProcessAvatar(GameObject avatarGameObject)
{ {
if (nowProcessing) return;
try
{
nowProcessing = true;
BoneDatabase.ResetBones(); BoneDatabase.ResetBones();
PathMappings.Clear(); PathMappings.Clear();
ClonedMenuMappings.Clear(); ClonedMenuMappings.Clear();
try
{
// Sometimes people like to nest one avatar in another, when transplanting clothing. To avoid issues // Sometimes people like to nest one avatar in another, when transplanting clothing. To avoid issues
// with inconsistently determining the avatar root, we'll go ahead and remove the extra sub-avatars // with inconsistently determining the avatar root, we'll go ahead and remove the extra sub-avatars
// here. // here.
@ -150,9 +160,13 @@ namespace nadena.dev.modular_avatar.core.editor
PhysboneBlockerPass.Process(avatarGameObject); PhysboneBlockerPass.Process(avatarGameObject);
AfterProcessing?.Invoke(avatarGameObject); AfterProcessing?.Invoke(avatarGameObject);
FixupAnimatorDebugData(avatarGameObject);
} }
finally finally
{ {
nowProcessing = false;
// Ensure that we clean up AvatarTagComponents after failed processing. This ensures we don't re-enter // Ensure that we clean up AvatarTagComponents after failed processing. This ensures we don't re-enter
// processing from the Awake method on the unprocessed AvatarTagComponents // processing from the Awake method on the unprocessed AvatarTagComponents
foreach (var component in avatarGameObject.GetComponentsInChildren<AvatarTagComponent>(true)) foreach (var component in avatarGameObject.GetComponentsInChildren<AvatarTagComponent>(true))
@ -162,7 +176,12 @@ namespace nadena.dev.modular_avatar.core.editor
ClonedMenuMappings.Clear(); ClonedMenuMappings.Clear();
} }
FixupAnimatorDebugData(avatarGameObject); var activator = avatarGameObject.GetComponent<AvatarActivator>();
if (activator != null)
{
UnityEngine.Object.DestroyImmediate(activator);
}
}
} }
[SuppressMessage("ReSharper", "PossibleNullReferenceException")] [SuppressMessage("ReSharper", "PossibleNullReferenceException")]

View File

@ -0,0 +1,121 @@
#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core
{
/// <summary>
/// This component is used to trigger MA processing upon entering play mode (prior to Av3Emu running).
/// We create it on a hidden object via AvatarTagObject's OnValidate, and it will proceed to add MAAvatarActivator
/// components to all avatar roots which contain MA components. This MAAvatarActivator component then performs MA
/// processing on Awake.
///
/// Note that we do not directly process the avatars from MAActivator. This is to avoid processing avatars that are
/// initially inactive in the scene (which can have high overhead if the user has a lot of inactive avatars in the
/// scene).
/// </summary>
[AddComponentMenu("")]
[ExecuteInEditMode]
[DefaultExecutionOrder(-9998)]
public class Activator : MonoBehaviour
{
private const string TAG_OBJECT_NAME = "ModularAvatarInternal_Activator";
private void Awake()
{
if (!RuntimeUtil.isPlaying || this == null) return;
var scene = gameObject.scene;
foreach (var root in scene.GetRootGameObjects())
{
foreach (var avatar in root.GetComponentsInChildren<VRCAvatarDescriptor>())
{
if (avatar.GetComponentInChildren<AvatarTagComponent>(true) != null)
{
avatar.gameObject.GetOrAddComponent<AvatarActivator>().hideFlags = HideFlags.HideInInspector;
}
}
}
}
private bool HasMAComponentsInScene()
{
var scene = gameObject.scene;
foreach (var root in scene.GetRootGameObjects())
{
if (root.GetComponentInChildren<AvatarTagComponent>(true) != null) return true;
}
return false;
}
private void OnValidate()
{
EditorApplication.delayCall += () =>
{
if (this == null) return;
gameObject.hideFlags = HideFlags.HideInHierarchy;
if (!HasMAComponentsInScene())
{
var scene = gameObject.scene;
DestroyImmediate(gameObject);
EditorSceneManager.MarkSceneDirty(scene);
}
};
}
internal static void CreateIfNotPresent(Scene scene)
{
if (!scene.IsValid() || EditorSceneManager.IsPreviewScene(scene)) return;
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
foreach (var root in scene.GetRootGameObjects())
{
if (root.GetComponent<Activator>() != null) return;
}
var oldActiveScene = SceneManager.GetActiveScene();
try
{
SceneManager.SetActiveScene(scene);
var gameObject = new GameObject(TAG_OBJECT_NAME);
gameObject.AddComponent<Activator>();
gameObject.hideFlags = HideFlags.HideInHierarchy;
}
finally
{
SceneManager.SetActiveScene(oldActiveScene);
}
}
}
[AddComponentMenu("")]
[ExecuteInEditMode]
[DefaultExecutionOrder(-9997)]
public class AvatarActivator : MonoBehaviour
{
private void Awake()
{
if (!RuntimeUtil.isPlaying || this == null) return;
RuntimeUtil.OnDemandProcessAvatar(RuntimeUtil.OnDemandSource.Awake, this);
}
private void Start()
{
if (!RuntimeUtil.isPlaying || this == null) return;
RuntimeUtil.OnDemandProcessAvatar(RuntimeUtil.OnDemandSource.Start, this);
}
private void Update()
{
DestroyImmediate(this);
}
}
}
#endif

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e41c5d0c41074360bc33887977722a4d
timeCreated: 1671337621

View File

@ -22,7 +22,6 @@
* SOFTWARE. * SOFTWARE.
*/ */
using System;
using UnityEngine; using UnityEngine;
namespace nadena.dev.modular_avatar.core namespace nadena.dev.modular_avatar.core
@ -44,5 +43,18 @@ namespace nadena.dev.modular_avatar.core
if (!RuntimeUtil.isPlaying || this == null) return; if (!RuntimeUtil.isPlaying || this == null) return;
RuntimeUtil.OnDemandProcessAvatar(RuntimeUtil.OnDemandSource.Start, this); RuntimeUtil.OnDemandProcessAvatar(RuntimeUtil.OnDemandSource.Start, this);
} }
private void OnValidate()
{
if (RuntimeUtil.isPlaying) return;
RuntimeUtil.delayCall(() =>
{
if (this == null) return;
#if UNITY_EDITOR
Activator.CreateIfNotPresent(gameObject.scene);
#endif
});
}
} }
} }

View File

@ -49,7 +49,7 @@ namespace nadena.dev.modular_avatar.core
Start Start
} }
public delegate void OnDemandProcessAvatarDelegate(OnDemandSource source, AvatarTagComponent component); public delegate void OnDemandProcessAvatarDelegate(OnDemandSource source, MonoBehaviour component);
public static OnDemandProcessAvatarDelegate OnDemandProcessAvatar = (_m, _c) => { }; public static OnDemandProcessAvatarDelegate OnDemandProcessAvatar = (_m, _c) => { };

View File

@ -1,7 +1,7 @@
{ {
"name": "nadena.dev.modular-avatar", "name": "nadena.dev.modular-avatar",
"displayName": "Modular Avatar", "displayName": "Modular Avatar",
"version": "1.1.2", "version": "1.2.0-rc0",
"unity": "2019.4", "unity": "2019.4",
"description": "A suite of tools for assembling your avatar out of reusable components", "description": "A suite of tools for assembling your avatar out of reusable components",
"author": { "author": {

View File

@ -24,7 +24,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.ide.rider": { "com.unity.ide.rider": {
"version": "3.0.16", "version": "3.0.17",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -33,7 +33,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.ide.visualstudio": { "com.unity.ide.visualstudio": {
"version": "2.0.11", "version": "2.0.17",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@ -42,7 +42,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.ide.vscode": { "com.unity.ide.vscode": {
"version": "1.2.4", "version": "1.2.5",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": {}, "dependencies": {},
@ -63,7 +63,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.test-framework": { "com.unity.test-framework": {
"version": "1.1.29", "version": "1.1.33",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {