summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-02-19 02:24:48 -0800
committeryum <yum.food.vr@gmail.com>2025-02-19 02:24:48 -0800
commit0675266fac2d1b9b1af9b89b5830bc7efedfed21 (patch)
treebe94c1665757f53f0becf4a7fa9ab078d08e911a
parent6b5018777d9cc7c362fafa3c673659770a6a5bca (diff)
Fix upload
Scripts must be wrapped in `#if UNITY_EDITOR` or build shits the bed. Also document config structs.
-rw-r--r--YOTSCore.cs33
-rw-r--r--YOTSNDMFConfig.cs11
-rw-r--r--YOTSNDMFGenerator.cs40
3 files changed, 76 insertions, 8 deletions
diff --git a/YOTSCore.cs b/YOTSCore.cs
index 4e0e6ee..a7e275a 100644
--- a/YOTSCore.cs
+++ b/YOTSCore.cs
@@ -1,3 +1,5 @@
+#if UNITY_EDITOR
+
using System;
using System.Collections.Generic;
using System.IO;
@@ -13,23 +15,42 @@ namespace YOTS
[System.Serializable]
public class ToggleSpec
{
+ // The name of the toggle. This is plumbed into the menu, the VRChat
+ // parameters, and the animator parameters.
[SerializeField]
public string name;
+ // The type of toggle.
+ // Accepted values:
+ // "toggle" - A boolean toggle. Creates a boolean sync param.
+ // "radial" - A radial puppet. Creates a float sync param.
[SerializeField]
public string type = "toggle";
- // Dependencies are evaluated before this one. They must share one or
- // more attributes with this spec.
+ // Dependencies are toggles that will be evaluated before this one. If
+ // you have two toggles which animate the same thing, one must depend
+ // on the other.
[SerializeField]
public List<string> dependencies = new List<string>();
+
+ // The name of meshes to toggle.
+ // For example, "Body" or "Shirt".
[SerializeField]
public List<string> meshToggles = new List<string>();
+
+ // Blendshapes to animate.
[SerializeField]
public List<BlendShapeSpec> blendShapes = new List<BlendShapeSpec>();
+
+ // Where to put the toggle in the menu. All toggles are placed under
+ // /YOTS. So if you put "Clothes" here, it'll be placed under
+ // /YOTS/Clothes.
[SerializeField]
public string menuPath = "/";
+ // The default value of the toggle.
+ // For example, if you want a gimmick to start toggled off, set this to
+ // 0.0f.
[SerializeField]
public float defaultValue = 1.0f;
@@ -57,15 +78,21 @@ namespace YOTS
[System.Serializable]
public class BlendShapeSpec
{
+ // The path to the mesh renderer to apply the blend shape to.
+ // For example, "Body" or "Shirt".
[SerializeField]
public string path;
+ // The name of the blend shape to apply.
+ // For example, "Chest_Hide" or "Boobs+".
[SerializeField]
public string blendShape;
+ // The value of the blendshape when the toggle is off. Range from 0-100.
[SerializeField]
public float offValue = 0.0f;
+ // The value of the blendshape when the toggle is on. Range from 0-100.
[SerializeField]
public float onValue = 100.0f;
@@ -1028,3 +1055,5 @@ namespace YOTS
}
}
}
+
+#endif // UNITY_EDITOR
diff --git a/YOTSNDMFConfig.cs b/YOTSNDMFConfig.cs
index baf92b8..0609d18 100644
--- a/YOTSNDMFConfig.cs
+++ b/YOTSNDMFConfig.cs
@@ -1,11 +1,22 @@
+#if UNITY_EDITOR
+
using UnityEngine;
+using nadena.dev.ndmf;
using VRC.SDK3.Avatars.ScriptableObjects;
namespace YOTS
{
+ [DisallowMultipleComponent]
public class YOTSNDMFConfig : MonoBehaviour
{
[Tooltip("The JSON configuration file.")]
public TextAsset jsonConfig;
+
+ void OnValidate()
+ {
+ gameObject.tag = "EditorOnly";
+ }
}
}
+
+#endif // UNITY_EDITOR
diff --git a/YOTSNDMFGenerator.cs b/YOTSNDMFGenerator.cs
index d8dba78..e6e0585 100644
--- a/YOTSNDMFGenerator.cs
+++ b/YOTSNDMFGenerator.cs
@@ -1,7 +1,10 @@
+#if UNITY_EDITOR
+
using UnityEngine;
using nadena.dev.ndmf;
-using nadena.dev.ndmf.VRChat;
+using nadena.dev.ndmf.builtin;
using nadena.dev.ndmf.localization;
+using nadena.dev.ndmf.VRChat;
using VRC.SDK3.Avatars.ScriptableObjects;
using UnityEditor;
using System;
@@ -22,13 +25,31 @@ namespace YOTS
protected override void Configure()
{
- // Use a different pass name in play mode to indicate temporary processing.
+ // First pass: Store config data
+ InPhase(BuildPhase.Resolving)
+ .Run("Cache YOTS Config", ctx => {
+ var config = ctx.AvatarRootObject.GetComponentInChildren<YOTSNDMFConfig>();
+ if (config == null || config.jsonConfig == null) {
+ ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_config",
+ "No YOTS config found on the avatar.");
+ return;
+ }
+ ctx.GetState<YOTSBuildState>().jsonConfig = config.jsonConfig.text;
+ })
+ // Shoutsout anatawa12/AvatarOptimizer
+ .BeforePass(RemoveEditorOnlyPass.Instance);
+
+ // Second pass: Generate animator
InPhase(BuildPhase.Transforming)
.Run("Generate YOTS Animator", ctx => {
- // ctx is a BuildContext
- // https://ndmf.nadena.dev/api/nadena.dev.ndmf.BuildContext.html
+ var state = ctx.GetState<YOTSBuildState>();
+ if (string.IsNullOrEmpty(state.jsonConfig)) {
+ ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_config",
+ "No YOTS config found on the avatar.");
+ return;
+ }
// Get config
- var config = ctx.AvatarRootObject.GetComponentInChildren<YOTSNDMFConfig>();
+ var config = ctx.GetState<YOTSBuildState>();
if (config == null) {
ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_config",
"No YOTS config component found on the avatar.");
@@ -65,7 +86,7 @@ namespace YOTS
descriptor.expressionsMenu = menu;
descriptor.expressionParameters = parameters;
RuntimeAnimatorController generatedAnimator = YOTSCore.GenerateAnimator(
- config.jsonConfig.text,
+ state.jsonConfig,
parameters,
menu
);
@@ -79,5 +100,12 @@ namespace YOTS
}
);
}
+
+ private class YOTSBuildState
+ {
+ public string jsonConfig;
+ }
}
}
+
+#endif // UNITY_EDITOR