diff options
| -rw-r--r-- | Scripts/YOTSCore.cs | 7 | ||||
| -rw-r--r-- | Scripts/YOTSNDMFGenerator.cs | 48 |
2 files changed, 50 insertions, 5 deletions
diff --git a/Scripts/YOTSCore.cs b/Scripts/YOTSCore.cs index 0fc8ccb..4421607 100644 --- a/Scripts/YOTSCore.cs +++ b/Scripts/YOTSCore.cs @@ -59,11 +59,10 @@ namespace YOTS [SerializeField]
public List<ExternalAnimationSpec> externalAnimations = new List<ExternalAnimationSpec>();
- // 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.
+ // Where to put the toggle in the menu. Defaults to the top-level menu.
+ // For example, if you put "Clothes" here, it'll be placed under /Clothes.
[SerializeField]
- public string menuPath = "/YOTS";
+ public string menuPath = "/";
// The default value of the toggle. Range from 0-1.
// For example, if you want a gimmick to start toggled off, set this to
diff --git a/Scripts/YOTSNDMFGenerator.cs b/Scripts/YOTSNDMFGenerator.cs index 4471fa1..8a2faac 100644 --- a/Scripts/YOTSNDMFGenerator.cs +++ b/Scripts/YOTSNDMFGenerator.cs @@ -104,11 +104,14 @@ namespace YOTS descriptor.expressionsMenu = menu;
descriptor.expressionParameters = parameters;
+ // Resolve bare mesh names to full hierarchy paths.
+ var resolvedJson = ResolveMeshNames(config.jsonConfig, ctx.AvatarRootObject.transform);
+
// Generate the YOTS animator.
RuntimeAnimatorController generatedAnimator = null;
try {
generatedAnimator = YOTSCore.GenerateAnimator(
- config.jsonConfig,
+ resolvedJson,
parameters,
menu
);
@@ -172,6 +175,49 @@ namespace YOTS public bool skipGeneration;
}
+ // Resolve bare mesh names (no '/') in meshToggles/inverseMeshToggles to all
+ // matching hierarchy paths. Names containing '/' are kept as explicit paths.
+ private static string ResolveMeshNames(string jsonConfig, Transform avatarRoot) {
+ var config = JsonUtility.FromJson<AnimatorConfigFile>(jsonConfig);
+ var nameToPathsMap = BuildNameToPathsMap(avatarRoot);
+ foreach (var toggle in config.toggles) {
+ toggle.meshToggles = ExpandMeshNames(toggle.meshToggles, nameToPathsMap);
+ toggle.inverseMeshToggles = ExpandMeshNames(toggle.inverseMeshToggles, nameToPathsMap);
+ }
+ return JsonUtility.ToJson(config);
+ }
+
+ private static List<string> ExpandMeshNames(List<string> names, Dictionary<string, List<string>> nameToPathsMap) {
+ if (names == null) return null;
+ var resolved = new List<string>();
+ foreach (var name in names) {
+ if (name.Contains('/')) {
+ resolved.Add(name);
+ } else if (nameToPathsMap.TryGetValue(name, out var paths)) {
+ resolved.AddRange(paths);
+ } else {
+ resolved.Add(name);
+ }
+ }
+ return resolved;
+ }
+
+ private static Dictionary<string, List<string>> BuildNameToPathsMap(Transform root) {
+ var map = new Dictionary<string, List<string>>();
+ CollectPaths(root, "", map);
+ return map;
+ }
+
+ private static void CollectPaths(Transform current, string currentPath, Dictionary<string, List<string>> map) {
+ foreach (Transform child in current) {
+ string childPath = currentPath == "" ? child.name : currentPath + "/" + child.name;
+ if (!map.ContainsKey(child.name))
+ map[child.name] = new List<string>();
+ map[child.name].Add(childPath);
+ CollectPaths(child, childPath, map);
+ }
+ }
+
private static VRCExpressionsMenu DeepCopyMenu(VRCExpressionsMenu sourceMenu) {
var copiedMenu = UnityEngine.Object.Instantiate(sourceMenu);
// Deep copy all submenu references
|
