From 3c7d7df216fe1537362b19520b304cc6e5d856a6 Mon Sep 17 00:00:00 2001 From: yum Date: Wed, 19 Feb 2025 03:26:58 -0800 Subject: organize, update readme --- Scripts/YOTSNDMFGenerator.cs | 111 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 Scripts/YOTSNDMFGenerator.cs (limited to 'Scripts/YOTSNDMFGenerator.cs') diff --git a/Scripts/YOTSNDMFGenerator.cs b/Scripts/YOTSNDMFGenerator.cs new file mode 100644 index 0000000..e6e0585 --- /dev/null +++ b/Scripts/YOTSNDMFGenerator.cs @@ -0,0 +1,111 @@ +#if UNITY_EDITOR + +using UnityEngine; +using nadena.dev.ndmf; +using nadena.dev.ndmf.builtin; +using nadena.dev.ndmf.localization; +using nadena.dev.ndmf.VRChat; +using VRC.SDK3.Avatars.ScriptableObjects; +using UnityEditor; +using System; +using System.Collections.Generic; + +[assembly: ExportsPlugin(typeof(YOTS.YOTSNDMFGenerator))] + +namespace YOTS +{ + public class YOTSNDMFGenerator : Plugin + { + private readonly Localizer localizer = new Localizer("en-us", () => new List<(string, Func)> + { + ("en-us", key => key) // Simple pass-through for English + }); + + public override string DisplayName => "YOTS Animator Generator"; + + protected override void Configure() + { + // First pass: Store config data + InPhase(BuildPhase.Resolving) + .Run("Cache YOTS Config", ctx => { + var config = ctx.AvatarRootObject.GetComponentInChildren(); + 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().jsonConfig = config.jsonConfig.text; + }) + // Shoutsout anatawa12/AvatarOptimizer + .BeforePass(RemoveEditorOnlyPass.Instance); + + // Second pass: Generate animator + InPhase(BuildPhase.Transforming) + .Run("Generate YOTS Animator", ctx => { + var state = ctx.GetState(); + 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.GetState(); + if (config == null) { + ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_config", + "No YOTS config component found on the avatar."); + return; + } + if (config.jsonConfig == null) { + ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_json", + "YOTS config component is missing JSON config file."); + return; + } + // Get descriptor + var descriptor = ctx.AvatarDescriptor; + if (descriptor == null) { + ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_descriptor", + "Avatar descriptor is missing."); + return; + } + RuntimeAnimatorController animator = descriptor.baseAnimationLayers[4].animatorController; + if (animator == null) { + ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_animator", + "FX layer is missing."); + return; + } + var menu = descriptor.expressionsMenu; + var parameters = descriptor.expressionParameters; + if (parameters == null || menu == null) + { + ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.missing_assets", + "Avatar parameters or menu is missing."); + return; + } + menu = UnityEngine.Object.Instantiate(menu); + parameters = UnityEngine.Object.Instantiate(parameters); + descriptor.expressionsMenu = menu; + descriptor.expressionParameters = parameters; + RuntimeAnimatorController generatedAnimator = YOTSCore.GenerateAnimator( + state.jsonConfig, + parameters, + menu + ); + if (generatedAnimator == null) { + ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.generation_failed", + "Failed to generate animator controller."); + return; + } + // TODO merge animators + descriptor.baseAnimationLayers[4].animatorController = generatedAnimator; + } + ); + } + + private class YOTSBuildState + { + public string jsonConfig; + } + } +} + +#endif // UNITY_EDITOR -- cgit v1.2.3