diff options
| author | yum <yum.food.vr@gmail.com> | 2025-02-19 03:50:09 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-02-19 03:50:09 -0800 |
| commit | bb0db51131f2c00d6aa08093ea4514ef98c15a57 (patch) | |
| tree | 2cc779974306a42134679fef2db53b247b5fbf85 /Scripts/YOTSNDMFGenerator.cs | |
| parent | 3c7d7df216fe1537362b19520b304cc6e5d856a6 (diff) | |
Append YOTS animator to original one
Diffstat (limited to 'Scripts/YOTSNDMFGenerator.cs')
| -rw-r--r-- | Scripts/YOTSNDMFGenerator.cs | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/Scripts/YOTSNDMFGenerator.cs b/Scripts/YOTSNDMFGenerator.cs index e6e0585..864edf8 100644 --- a/Scripts/YOTSNDMFGenerator.cs +++ b/Scripts/YOTSNDMFGenerator.cs @@ -9,6 +9,8 @@ using VRC.SDK3.Avatars.ScriptableObjects; using UnityEditor;
using System;
using System.Collections.Generic;
+using System.Linq;
+using UnityEditor.Animations;
[assembly: ExportsPlugin(typeof(YOTS.YOTSNDMFGenerator))]
@@ -39,7 +41,7 @@ namespace YOTS // Shoutsout anatawa12/AvatarOptimizer
.BeforePass(RemoveEditorOnlyPass.Instance);
- // Second pass: Generate animator
+ // Second pass: Generate animator and merge with the original
InPhase(BuildPhase.Transforming)
.Run("Generate YOTS Animator", ctx => {
var state = ctx.GetState<YOTSBuildState>();
@@ -48,7 +50,7 @@ namespace YOTS "No YOTS config found on the avatar.");
return;
}
- // Get config
+
var config = ctx.GetState<YOTSBuildState>();
if (config == null) {
ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.no_config",
@@ -60,19 +62,15 @@ namespace YOTS "YOTS config component is missing JSON config file.");
return;
}
- // Get descriptor
+
+ // Get menu and parameters
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;
- }
+ RuntimeAnimatorController originalAnimator = descriptor.baseAnimationLayers[4].animatorController;
var menu = descriptor.expressionsMenu;
var parameters = descriptor.expressionParameters;
if (parameters == null || menu == null)
@@ -81,10 +79,13 @@ namespace YOTS "Avatar parameters or menu is missing.");
return;
}
+ // TODO do we need to make copies?
menu = UnityEngine.Object.Instantiate(menu);
parameters = UnityEngine.Object.Instantiate(parameters);
descriptor.expressionsMenu = menu;
descriptor.expressionParameters = parameters;
+
+ // Generate the YOTS animator.
RuntimeAnimatorController generatedAnimator = YOTSCore.GenerateAnimator(
state.jsonConfig,
parameters,
@@ -92,13 +93,58 @@ namespace YOTS );
if (generatedAnimator == null) {
ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.generation_failed",
- "Failed to generate animator controller.");
+ "Failed to generate animator.");
return;
}
- // TODO merge animators
- descriptor.baseAnimationLayers[4].animatorController = generatedAnimator;
+
+ if (originalAnimator == null)
+ {
+ descriptor.baseAnimationLayers[4].animatorController = generatedAnimator;
+ return;
+ }
+
+ AnimatorController originalController = originalAnimator as AnimatorController;
+ AnimatorController generatedController = generatedAnimator as AnimatorController;
+ MergeAnimatorControllers(localizer, originalController, generatedController);
+ descriptor.baseAnimationLayers[4].animatorController = originalController;
+ });
+ }
+
+ // Simply append generated params and layers to the original animator.
+ private static void MergeAnimatorControllers(Localizer localizer, AnimatorController original, AnimatorController generated)
+ {
+ // Merge parameters from generated into original.
+ foreach (var genParam in generated.parameters)
+ {
+ // This is an O(m*n) check but m and n should be small enough to not matter.
+ if (original.parameters.Any(p => p.name == genParam.name))
+ {
+ ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.parameter_conflict",
+ $"Parameter '{genParam.name}' already exists in the original animator.");
+ return;
}
- );
+ original.AddParameter(genParam);
+ }
+
+ // Append each YOTS layer after the original layers.
+ foreach (var genLayer in generated.layers)
+ {
+ // This isn't strictly an error but if someone already has layers named
+ // YOTS_* that's probably not on purpose.
+ if (original.layers.Any(l => l.name == genLayer.name))
+ {
+ ErrorReport.ReportError(localizer, ErrorSeverity.Error, "yots.error.layer_conflict",
+ $"Layer with name '{genLayer.name}' already exists in the original animator.");
+ return;
+ }
+ var newLayer = new AnimatorControllerLayer
+ {
+ name = genLayer.name,
+ defaultWeight = genLayer.defaultWeight,
+ stateMachine = genLayer.stateMachine
+ };
+ original.AddLayer(newLayer);
+ }
}
private class YOTSBuildState
|
