mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-01 20:25:07 +08:00
Remove the need for an av3emu patch
This commit is contained in:
parent
cf82c93e55
commit
ab51e9dd82
@ -34,13 +34,34 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
public static class ApplyOnPlay
|
public static class ApplyOnPlay
|
||||||
{
|
{
|
||||||
private const string MENU_NAME = "Tools/Modular Avatar/Apply on Play";
|
private const string MENU_NAME = "Tools/Modular Avatar/Apply on Play";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need to process avatars before lyuma's av3 emulator wakes up and processes avatars; it does this in Awake,
|
||||||
|
* so we have to do our processing in Awake as well. This seems to work fine when first entering play mode, but
|
||||||
|
* if you subsequently enable an initially-disabled avatar, processing from within Awake causes an editor crash.
|
||||||
|
*
|
||||||
|
* To workaround this, we initially process in awake; then, after OnPlayModeStateChanged is invoked (ie, after
|
||||||
|
* all initially-enabled components have Awake called), we switch to processing from Start instead.
|
||||||
|
*/
|
||||||
|
private static RuntimeUtil.OnDemandSource armedSource = RuntimeUtil.OnDemandSource.Awake;
|
||||||
|
|
||||||
static ApplyOnPlay()
|
static ApplyOnPlay()
|
||||||
{
|
{
|
||||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||||
|
RuntimeUtil.OnDemandProcessAvatar = MaybeProcessAvatar;
|
||||||
Menu.SetChecked(MENU_NAME, ModularAvatarSettings.applyOnPlay);
|
Menu.SetChecked(MENU_NAME, ModularAvatarSettings.applyOnPlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void MaybeProcessAvatar(RuntimeUtil.OnDemandSource source, AvatarTagComponent component)
|
||||||
|
{
|
||||||
|
if (ModularAvatarSettings.applyOnPlay && source == armedSource && component != null)
|
||||||
|
{
|
||||||
|
var avatar = RuntimeUtil.FindAvatarInParents(component.transform);
|
||||||
|
if (avatar == null) return;
|
||||||
|
AvatarProcessor.ProcessAvatar(avatar.gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MenuItem(MENU_NAME)]
|
[MenuItem(MENU_NAME)]
|
||||||
private static void ToggleApplyOnPlay()
|
private static void ToggleApplyOnPlay()
|
||||||
{
|
{
|
||||||
@ -50,35 +71,9 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
|
|
||||||
private static void OnPlayModeStateChanged(PlayModeStateChange obj)
|
private static void OnPlayModeStateChanged(PlayModeStateChange obj)
|
||||||
{
|
{
|
||||||
if (obj == PlayModeStateChange.EnteredPlayMode && ModularAvatarSettings.applyOnPlay)
|
if (obj == PlayModeStateChange.EnteredPlayMode)
|
||||||
{
|
{
|
||||||
// TODO - only apply modular avatar changes?
|
armedSource = RuntimeUtil.OnDemandSource.Start;
|
||||||
foreach (var root in SceneManager.GetActiveScene().GetRootGameObjects())
|
|
||||||
{
|
|
||||||
foreach (var avatar in root.GetComponentsInChildren<VRCAvatarDescriptor>(true))
|
|
||||||
{
|
|
||||||
if (avatar.GetComponentsInChildren<AvatarTagComponent>(true).Length > 0)
|
|
||||||
{
|
|
||||||
UnpackPrefabsCompletely(avatar.gameObject);
|
|
||||||
VRCBuildPipelineCallbacks.OnPreprocessAvatar(avatar.gameObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void UnpackPrefabsCompletely(GameObject obj)
|
|
||||||
{
|
|
||||||
if (PrefabUtility.IsAnyPrefabInstanceRoot(obj))
|
|
||||||
{
|
|
||||||
PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (Transform child in obj.transform)
|
|
||||||
{
|
|
||||||
UnpackPrefabsCompletely(child.gameObject);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,35 +25,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
using VRC.SDK3.Avatars.Components;
|
using VRC.SDK3.Avatars.Components;
|
||||||
using VRC.SDKBase.Editor.BuildPipeline;
|
using VRC.SDKBase.Editor.BuildPipeline;
|
||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
namespace net.fushizen.modular_avatar.core.editor
|
||||||
{
|
{
|
||||||
[InitializeOnLoad]
|
[InitializeOnLoad]
|
||||||
internal class Av3EmuHook
|
internal class AvatarProcessor : IVRCSDKPreprocessAvatarCallback, IVRCSDKPostprocessAvatarCallback
|
||||||
{
|
{
|
||||||
static Av3EmuHook()
|
static AvatarProcessor()
|
||||||
{
|
{
|
||||||
if (EditorApplication.isPlayingOrWillChangePlaymode)
|
|
||||||
{
|
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
var runtime = assembly.GetType("LyumaAv3Runtime");
|
|
||||||
if (runtime == null) continue;
|
|
||||||
|
|
||||||
var addHook = runtime.GetMethod("AddInitAvatarHook", BindingFlags.Static | BindingFlags.Public);
|
|
||||||
if (addHook == null) continue;
|
|
||||||
|
|
||||||
addHook.Invoke(null, new object[]
|
|
||||||
{
|
|
||||||
-999999,
|
|
||||||
(Action<VRCAvatarDescriptor>)(av => VRCBuildPipelineCallbacks.OnPreprocessAvatar(av.gameObject))
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,5 +46,42 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
Util.DeleteTemporaryAssets();
|
Util.DeleteTemporaryAssets();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int callbackOrder => -9000;
|
||||||
|
|
||||||
|
public void OnPostprocessAvatar()
|
||||||
|
{
|
||||||
|
Util.DeleteTemporaryAssets();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnPreprocessAvatar(GameObject avatarGameObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessAvatar(avatarGameObject);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogError(e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ProcessAvatar(GameObject avatarGameObject)
|
||||||
|
{
|
||||||
|
BoneDatabase.ResetBones();
|
||||||
|
PathMappings.Clear();
|
||||||
|
|
||||||
|
new MergeArmatureHook().OnPreprocessAvatar(avatarGameObject);
|
||||||
|
new RetargetMeshes().OnPreprocessAvatar(avatarGameObject);
|
||||||
|
new BoneProxyProcessor().OnPreprocessAvatar(avatarGameObject);
|
||||||
|
new MergeAnimatorProcessor().OnPreprocessAvatar(avatarGameObject);
|
||||||
|
|
||||||
|
foreach (var component in avatarGameObject.GetComponentsInChildren<AvatarTagComponent>(true))
|
||||||
|
{
|
||||||
|
UnityEngine.Object.DestroyImmediate(component);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -28,11 +28,9 @@ using VRC.SDKBase.Editor.BuildPipeline;
|
|||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
namespace net.fushizen.modular_avatar.core.editor
|
||||||
{
|
{
|
||||||
public class BoneProxyHook : HookBase
|
internal class BoneProxyProcessor
|
||||||
{
|
{
|
||||||
public override int callbackOrder => HookSequence.SEQ_BONE_PROXY;
|
internal void OnPreprocessAvatar(GameObject avatarGameObject)
|
||||||
|
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
|
||||||
{
|
{
|
||||||
var boneProxies = avatarGameObject.GetComponentsInChildren<ModularAvatarBoneProxy>(true);
|
var boneProxies = avatarGameObject.GetComponentsInChildren<ModularAvatarBoneProxy>(true);
|
||||||
|
|
||||||
@ -56,8 +54,6 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
Object.DestroyImmediate(proxy);
|
Object.DestroyImmediate(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using VRC.SDKBase.Editor.BuildPipeline;
|
|
||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
|
||||||
{
|
|
||||||
public abstract class HookBase : IVRCSDKPreprocessAvatarCallback
|
|
||||||
{
|
|
||||||
public bool OnPreprocessAvatar(GameObject avatarGameObject)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return OnPreprocessAvatarWrapped(avatarGameObject);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.LogError(e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract bool OnPreprocessAvatarWrapped(GameObject avatarGameObject);
|
|
||||||
public abstract int callbackOrder { get; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d65a87d13d234177b18f1b0fbbf12360
|
|
||||||
timeCreated: 1662780435
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2022 bd_
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
|
||||||
{
|
|
||||||
internal static class HookSequence
|
|
||||||
{
|
|
||||||
public const int SEQ_RESETTERS = -90000;
|
|
||||||
public const int SEQ_MERGE_ARMATURE = SEQ_RESETTERS + 1;
|
|
||||||
public const int SEQ_RETARGET_MESH = SEQ_MERGE_ARMATURE + 1;
|
|
||||||
public const int SEQ_BONE_PROXY = SEQ_RETARGET_MESH + 1;
|
|
||||||
public const int SEQ_MERGE_ANIMATORS = SEQ_BONE_PROXY + 1;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9e6b3680d07242d38d5b2c6b00951ca0
|
|
||||||
timeCreated: 1661632859
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2022 bd_
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using UnityEngine;
|
|
||||||
using VRC.SDKBase.Editor.BuildPipeline;
|
|
||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Ensure that any AvatarTagComponents are purged just before upload.
|
|
||||||
*/
|
|
||||||
public class LastResortTagComponentCleaner : HookBase
|
|
||||||
{
|
|
||||||
public override int callbackOrder => 0;
|
|
||||||
|
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
|
||||||
{
|
|
||||||
foreach (var component in avatarGameObject.GetComponentsInChildren<AvatarTagComponent>(true))
|
|
||||||
{
|
|
||||||
UnityEngine.Object.DestroyImmediate(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 921628a5f4434452bcfa3a926d4ebdac
|
|
||||||
timeCreated: 1661564171
|
|
@ -31,20 +31,18 @@ using VRC.SDKBase.Editor.BuildPipeline;
|
|||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
namespace net.fushizen.modular_avatar.core.editor
|
||||||
{
|
{
|
||||||
public class MergeAnimatorHook : HookBase
|
internal class MergeAnimatorProcessor
|
||||||
{
|
{
|
||||||
private const string SAMPLE_PATH_PACKAGE = "Packages/com.vrchat.avatars/Samples/AV3 Demo Assets/Animation/Controllers";
|
private const string SAMPLE_PATH_PACKAGE = "Packages/com.vrchat.avatars/Samples/AV3 Demo Assets/Animation/Controllers";
|
||||||
private const string SAMPLE_PATH_LEGACY = "Assets/VRCSDK/Examples3/Animation/Controllers";
|
private const string SAMPLE_PATH_LEGACY = "Assets/VRCSDK/Examples3/Animation/Controllers";
|
||||||
|
|
||||||
public override int callbackOrder => HookSequence.SEQ_MERGE_ANIMATORS;
|
|
||||||
|
|
||||||
private Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorController> defaultControllers_ =
|
private Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorController> defaultControllers_ =
|
||||||
new Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorController>();
|
new Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorController>();
|
||||||
|
|
||||||
Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorCombiner> mergeSessions =
|
Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorCombiner> mergeSessions =
|
||||||
new Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorCombiner>();
|
new Dictionary<VRCAvatarDescriptor.AnimLayerType, AnimatorCombiner>();
|
||||||
|
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
internal void OnPreprocessAvatar(GameObject avatarGameObject)
|
||||||
{
|
{
|
||||||
defaultControllers_.Clear();
|
defaultControllers_.Clear();
|
||||||
mergeSessions.Clear();
|
mergeSessions.Clear();
|
||||||
@ -84,8 +82,6 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
|
|
||||||
descriptor.baseAnimationLayers = FinishSessions(descriptor.baseAnimationLayers);
|
descriptor.baseAnimationLayers = FinishSessions(descriptor.baseAnimationLayers);
|
||||||
descriptor.specialAnimationLayers = FinishSessions(descriptor.specialAnimationLayers);
|
descriptor.specialAnimationLayers = FinishSessions(descriptor.specialAnimationLayers);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private VRCAvatarDescriptor.CustomAnimLayer[] FinishSessions(
|
private VRCAvatarDescriptor.CustomAnimLayer[] FinishSessions(
|
@ -34,14 +34,12 @@ using Vector3 = UnityEngine.Vector3;
|
|||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
namespace net.fushizen.modular_avatar.core.editor
|
||||||
{
|
{
|
||||||
public class MergeArmatureHook : HookBase
|
public class MergeArmatureHook
|
||||||
{
|
{
|
||||||
public override int callbackOrder => HookSequence.SEQ_MERGE_ARMATURE;
|
|
||||||
|
|
||||||
private Dictionary<Transform, Transform> BoneRemappings = new Dictionary<Transform, Transform>();
|
private Dictionary<Transform, Transform> BoneRemappings = new Dictionary<Transform, Transform>();
|
||||||
private List<GameObject> ToDelete = new List<GameObject>();
|
private List<GameObject> ToDelete = new List<GameObject>();
|
||||||
|
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
internal bool OnPreprocessAvatar(GameObject avatarGameObject)
|
||||||
{
|
{
|
||||||
BoneRemappings.Clear();
|
BoneRemappings.Clear();
|
||||||
ToDelete.Clear();
|
ToDelete.Clear();
|
||||||
|
@ -30,16 +30,6 @@ using VRC.SDKBase.Editor.BuildPipeline;
|
|||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core.editor
|
namespace net.fushizen.modular_avatar.core.editor
|
||||||
{
|
{
|
||||||
internal class MeshRetargeterResetHook : HookBase
|
|
||||||
{
|
|
||||||
public override int callbackOrder => HookSequence.SEQ_RESETTERS;
|
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
|
||||||
{
|
|
||||||
BoneDatabase.ResetBones();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class BoneDatabase
|
internal static class BoneDatabase
|
||||||
{
|
{
|
||||||
private static Dictionary<Transform, bool> IsRetargetable = new Dictionary<Transform, bool>();
|
private static Dictionary<Transform, bool> IsRetargetable = new Dictionary<Transform, bool>();
|
||||||
@ -84,10 +74,9 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class RetargetMeshes : HookBase
|
internal class RetargetMeshes
|
||||||
{
|
{
|
||||||
public override int callbackOrder => HookSequence.SEQ_RETARGET_MESH;
|
internal void OnPreprocessAvatar(GameObject avatarGameObject)
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
|
||||||
{
|
{
|
||||||
foreach (var renderer in avatarGameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true))
|
foreach (var renderer in avatarGameObject.GetComponentsInChildren<SkinnedMeshRenderer>(true))
|
||||||
{
|
{
|
||||||
@ -131,8 +120,6 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,14 +73,4 @@ namespace net.fushizen.modular_avatar.core.editor
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ClearPathMappings : HookBase
|
|
||||||
{
|
|
||||||
public override int callbackOrder => HookSequence.SEQ_RESETTERS;
|
|
||||||
protected override bool OnPreprocessAvatarWrapped(GameObject avatarGameObject)
|
|
||||||
{
|
|
||||||
PathMappings.Clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -22,6 +22,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core
|
namespace net.fushizen.modular_avatar.core
|
||||||
@ -29,7 +30,19 @@ namespace net.fushizen.modular_avatar.core
|
|||||||
/**
|
/**
|
||||||
* This abstract base class is injected into the VRCSDK avatar component allowlist to avoid
|
* This abstract base class is injected into the VRCSDK avatar component allowlist to avoid
|
||||||
*/
|
*/
|
||||||
|
[DefaultExecutionOrder(-9999)] // run before av3emu
|
||||||
public abstract class AvatarTagComponent : MonoBehaviour
|
public abstract class AvatarTagComponent : 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,7 +37,17 @@ namespace net.fushizen.modular_avatar.core
|
|||||||
|
|
||||||
// Initialized in Util
|
// Initialized in Util
|
||||||
public static Action<NullCallback> delayCall = (_) => { };
|
public static Action<NullCallback> delayCall = (_) => { };
|
||||||
|
|
||||||
|
public enum OnDemandSource
|
||||||
|
{
|
||||||
|
Awake,
|
||||||
|
Start
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void OnDemandProcessAvatarDelegate(OnDemandSource source, AvatarTagComponent component);
|
||||||
|
|
||||||
|
public static OnDemandProcessAvatarDelegate OnDemandProcessAvatar = (_m, _c) => { };
|
||||||
|
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
public static string RelativePath(GameObject root, GameObject child)
|
public static string RelativePath(GameObject root, GameObject child)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user