From a4523c852081e47e521576a1c10c89d60e79e592 Mon Sep 17 00:00:00 2001
From: pandravrc <162582491+pandravrc@users.noreply.github.com>
Date: Sun, 8 Sep 2024 06:06:35 +0900
Subject: [PATCH] Close #3
---
Editor/EmotePrefab.cs | 80 ++++++++++++++++
Editor/EmotePrefab.cs.meta | 11 +++
Runtime/EmotePrefab.cs | 10 ++
Runtime/EmotePrefab.cs.meta | 11 +++
Runtime/Generic.cs | 185 ++++++++++++++++++++++++++++++++++++
Runtime/Generic.cs.meta | 11 +++
6 files changed, 308 insertions(+)
create mode 100644 Editor/EmotePrefab.cs
create mode 100644 Editor/EmotePrefab.cs.meta
create mode 100644 Runtime/EmotePrefab.cs
create mode 100644 Runtime/EmotePrefab.cs.meta
create mode 100644 Runtime/Generic.cs
create mode 100644 Runtime/Generic.cs.meta
diff --git a/Editor/EmotePrefab.cs b/Editor/EmotePrefab.cs
new file mode 100644
index 0000000..c03ef96
--- /dev/null
+++ b/Editor/EmotePrefab.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using nadena.dev.ndmf;
+using nadena.dev.modular_avatar.core;
+using nadena.dev.modular_avatar.core.editor;
+using UnityEngine;
+using UnityEditor;
+using UnityEditor.Animations;
+using VRC.SDK3.Avatars.Components;
+using com.github.pandrabox.emoteprefab.runtime;
+using static com.github.pandrabox.emoteprefab.runtime.Generic;
+using com.github.pandrabox.emoteprefab.editor;
+using Pan.Lib;
+
+[assembly: ExportsPlugin(typeof(EmotePrefabPass))]
+
+namespace com.github.pandrabox.emoteprefab.editor
+{
+ ///
+ /// To call from Unity menu (Debug Only, Comment out upon release.)
+ ///
+ public class EmotePrefabUnityMenu : MonoBehaviour
+ {
+ [MenuItem("PanDev/EmotePrefab")]
+ static void GenEmotePrefab()
+ {
+ var Target = Selection.activeGameObject;
+ var AvatarDescriptor = FindComponentFromParent(Target);
+ new EmotePrefabMain().Run(AvatarDescriptor);
+ }
+ }
+ ///
+ /// To call from NDMF
+ ///
+ public class EmotePrefabPass : Plugin
+ {
+ protected override void Configure()
+ {
+ //try
+ //{
+ InPhase(BuildPhase.Transforming).BeforePlugin("nadena.dev.modular-avatar").Run("PanEmotePrefab", ctx =>
+ {
+ var TargetComponents = ctx.AvatarRootTransform.GetComponentsInChildren(false);
+ foreach (var T in TargetComponents)
+ {
+ new EmotePrefabMain().Run(ctx.AvatarDescriptor);
+ return;
+ }
+ });
+ //}
+ //catch (Exception e)
+ //{
+ // Debug.LogError($@"[Pan:EmotePrefab]{e}");
+ //}
+ }
+ }
+ ///
+ /// Actual operation
+ ///
+ public class EmotePrefabMain : MonoBehaviour
+ {
+ VRCAvatarDescriptor AvatarDescriptor;
+ public void Run(VRCAvatarDescriptor AvatarDescriptor)//,GameObject AvatarRootObject
+ {
+ this.AvatarDescriptor = AvatarDescriptor;
+ ActionLayerReplace();
+ }
+ private void ActionLayerReplace()
+ {
+ string ActionAnimatorPath = $@"Packages\com.github.pandrabox.emoteprefab\Assets\BearsDen\CustomAnimatorControllers\Action.controller";
+ var AssignController= AssetDatabase.LoadAssetAtPath(ActionAnimatorPath);
+ if (AssignController == null) {
+ throw new Exception("EmotePrefab ActionLayerReplace AssignController Not Found");
+ }
+ AvatarDescriptor.baseAnimationLayers[3].isDefault = false;
+ AvatarDescriptor.baseAnimationLayers[3].animatorController = AssignController;
+ }
+ }
+}
diff --git a/Editor/EmotePrefab.cs.meta b/Editor/EmotePrefab.cs.meta
new file mode 100644
index 0000000..2427de5
--- /dev/null
+++ b/Editor/EmotePrefab.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 68305e62a0c630a49990bb9f73cb1102
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/EmotePrefab.cs b/Runtime/EmotePrefab.cs
new file mode 100644
index 0000000..ba224d8
--- /dev/null
+++ b/Runtime/EmotePrefab.cs
@@ -0,0 +1,10 @@
+using UnityEngine;
+
+namespace com.github.pandrabox.emoteprefab.runtime
+{
+ [AddComponentMenu("Pan/EmotePrefab")]
+ public class EmotePrefab : MonoBehaviour, VRC.SDKBase.IEditorOnly
+ {
+ // public RuntimeAnimatorController animator;
+ }
+}
\ No newline at end of file
diff --git a/Runtime/EmotePrefab.cs.meta b/Runtime/EmotePrefab.cs.meta
new file mode 100644
index 0000000..0d05e33
--- /dev/null
+++ b/Runtime/EmotePrefab.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 2811c4e709a521c45bf91cd7041f1db2
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Generic.cs b/Runtime/Generic.cs
new file mode 100644
index 0000000..dd00d41
--- /dev/null
+++ b/Runtime/Generic.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using com.github.pandrabox.emoteprefab.runtime;
+using VRC.SDK3.Avatars.Components;
+
+
+namespace com.github.pandrabox.emoteprefab.runtime
+{
+ public static class Generic
+ {
+ ///
+ /// Searches for a specific component in the self or parent direction.
+ /// Example of use: var Descriptor = FindComponentFromParent(MyGameObject);
+ ///
+ /// Target Component Name
+ /// GameObject to search from
+ /// The first component found, or null if none.
+ public static T FindComponentFromParent(GameObject CurrentObject) where T : Component
+ {
+ while (CurrentObject != null)
+ {
+ var component = CurrentObject.GetComponent();
+ if (component != null)
+ {
+ return component;
+ }
+ CurrentObject = CurrentObject.transform.parent?.gameObject;
+ }
+ return null;
+ }
+ ///
+ /// Searches for a specific component in the self or parent direction.
+ /// Example of use: var Descriptor = FindComponentFromParent(MyTransform);
+ ///
+ /// Target Component Name
+ /// Transform to search from
+ /// The first component found, or null if none.
+ public static T FindComponentFromParent(Transform CurrentTransform) where T : Component
+ {
+ return FindComponentFromParent(CurrentTransform?.gameObject);
+ }
+ public static GameObject GetAvatarRootObject(GameObject Target)
+ {
+ return FindComponentFromParent(Target)?.gameObject;
+ }
+ public static GameObject GetAvatarRootObject(Transform Target)
+ {
+ return FindComponentFromParent(Target)?.gameObject;
+ }
+ public static Transform GetAvatarRootTransform(GameObject Target)
+ {
+ return FindComponentFromParent(Target)?.gameObject?.transform;
+ }
+ public static Transform GetAvatarRootTransform(Transform Target)
+ {
+ return FindComponentFromParent(Target)?.gameObject?.transform;
+ }
+ public static bool IsInAvatar(GameObject Target)
+ {
+ return GetAvatarRootObject(Target) != null;
+ }
+ public static bool IsInAvatar(Transform Target)
+ {
+ return IsInAvatar(Target.gameObject);
+ }
+
+ public static GUIStyle TitleStyle()
+ {
+ GUIStyle style = new GUIStyle(GUI.skin.label);
+ style.normal.background = MakeTex(1, 1, new Color(255f / 255f, 128f / 255f, 0f / 255f, 1f));
+ style.normal.textColor = Color.black;
+ style.fontStyle = FontStyle.Bold;
+ return style;
+ }
+ public static Texture2D MakeTex(int width, int height, Color color)
+ {
+ Color[] pix = new Color[width * height];
+ for (int i = 0; i < pix.Length; ++i)
+ {
+ pix[i] = color;
+ }
+ Texture2D result = new Texture2D(width, height);
+ result.SetPixels(pix);
+ result.Apply();
+ return result;
+ }
+ public static bool IsWithinErrorRange(Vector3 vector3, float referenceValue, float errorThreshold)
+ {
+ return Mathf.Abs(vector3.x - referenceValue) <= errorThreshold &&
+ Mathf.Abs(vector3.y - referenceValue) <= errorThreshold &&
+ Mathf.Abs(vector3.z - referenceValue) <= errorThreshold;
+ }
+
+ public static void SetEditorOnly(string TargetName, bool SW, GameObject ParentObject = null)
+ {
+ var Targets = GetGameObjectsByName(TargetName, ParentObject);
+ foreach (var Target in Targets)
+ {
+ SetEditorOnly(Target, SW);
+ }
+ }
+ public static void SetEditorOnly(GameObject Target, bool SW)
+ {
+ if (SW)
+ {
+ Target.tag = "EditorOnly";
+ Target.SetActive(false);
+ }
+ else
+ {
+ Target.tag = "Untagged";
+ Target.SetActive(true);
+ }
+ }
+ public static void SetEditorOnly(Transform Target, bool SW)
+ {
+ SetEditorOnly(Target.gameObject, SW);
+ }
+
+
+ public static Transform[] GetTransformsByName(string TargetName, Transform ParentTransform = null)
+ {
+ Transform[] Transforms;
+ if (ParentTransform != null)
+ {
+ Transforms = ParentTransform.GetComponentsInChildren(true)?.Where(t => t.name == TargetName)?.ToArray();
+ }
+ else
+ {
+ Transforms = GameObject.FindObjectsOfType()?.Where(t => t.name == TargetName)?.ToArray();
+ }
+ return Transforms;
+ }
+ public static Transform[] GetTransformsByName(string TargetName, GameObject ParentObject = null)
+ {
+ return GetTransformsByName(TargetName, ParentObject.transform);
+ }
+ public static GameObject[] GetGameObjectsByName(string TargetName, Transform ParentTransform = null)
+ {
+ Transform[] Transforms = GetTransformsByName(TargetName, ParentTransform);
+ GameObject[] GameObjects = new GameObject[Transforms.Length];
+ for (int i = 0; i < Transforms.Length; i++)
+ {
+ GameObjects[i] = Transforms[i].gameObject;
+ }
+ return GameObjects;
+ }
+ public static GameObject[] GetGameObjectsByName(string TargetName, GameObject ParentGameObject = null)
+ {
+ return GetGameObjectsByName(TargetName, ParentGameObject.transform);
+ }
+
+
+
+
+ public static bool IsTargetEditorOnly(string TargetName, GameObject ParentObject = null)
+ {
+ Transform[] Transforms = GetTransformsByName(TargetName, ParentObject);
+ if (Transforms == null || Transforms.Length < 1) { return false; }
+ return IsTargetEditorOnly(Transforms[0].gameObject);
+ }
+ public static bool IsTargetEditorOnly(GameObject target)
+ {
+ return target.tag == "EditorOnly" && target.activeSelf == false;
+ }
+
+ public static float DELTA = 0.00001f;
+
+ public static string[] GestureNames = new string[] { "Neutral", "Fist", "HandOpen", "FingerPoint", "Victory", "RocknRoll", "HandGun", "Thumbsup" };
+ public enum Gesture
+ {
+ Neutral,
+ Fist,
+ HandOpen,
+ FingerPoint,
+ Victory,
+ RocknRoll,
+ HandGun,
+ Thumbsup
+ }
+ public const int GESTURENUM = 8;
+ }
+}
diff --git a/Runtime/Generic.cs.meta b/Runtime/Generic.cs.meta
new file mode 100644
index 0000000..07d134d
--- /dev/null
+++ b/Runtime/Generic.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: be10de7f91398bf41847f1fcae5172de
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: