SharedVRCStuff/GestureManagerExporter/GestureManagerExporter.cs

133 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using VRC.SDKBase;
using BlackStartX.GestureManager.Editor.Modules.Vrc3;
using BlackStartX.GestureManager.Editor.Modules.Vrc3.Params;
[InitializeOnLoad]
internal static class GestureManagerExporter
{
private static bool excludeAnimatorParameters = true;
private static bool sortByDescriptor = true;
static GestureManagerExporter()
{
var harmony = new Harmony("gay.lilyy.GestureManagerExporter");
harmony.PatchAll();
}
[HarmonyPatch]
private static class PatchParametersLayout
{
static MethodBase TargetMethod()
{
var nestedClass = typeof(ModuleVrc3).Assembly
.GetType("BlackStartX.GestureManager.Editor.Modules.Vrc3.Vrc3Debug.Avatar.Vrc3AvatarDebugWindow+Static");
return nestedClass?.GetMethod("ParametersLayout", BindingFlags.NonPublic | BindingFlags.Static);
}
static void Postfix(ModuleVrc3 module, float width)
{
excludeAnimatorParameters = GUILayout.Toggle(excludeAnimatorParameters, "Exclude Animator-Only Parameters", GUILayout.Width(width));
sortByDescriptor = GUILayout.Toggle(sortByDescriptor, "Sort by Parameters File", GUILayout.Width(width));
if (!GUILayout.Button("Export Parameters to JSON", GUILayout.Width(width))) return;
var path = EditorUtility.SaveFilePanel(
"Export Parameters",
"Assets",
"avatar_parameters.json",
"json"
);
if (string.IsNullOrEmpty(path)) return;
var parameters = new Dictionary<string, object>();
var avatarDescriptor = module.AvatarDescriptor;
foreach (var param in module.Params)
{
if (excludeAnimatorParameters) {
if (avatarDescriptor.expressionParameters.FindParameter(param.Key) == null) {
continue;
}
}
object value = param.Value.Type switch
{
AnimatorControllerParameterType.Float => param.Value.FloatValue(),
AnimatorControllerParameterType.Int => param.Value.IntValue(),
AnimatorControllerParameterType.Bool => param.Value.BoolValue(),
AnimatorControllerParameterType.Trigger => param.Value.BoolValue(),
_ => throw new ArgumentOutOfRangeException(nameof(param.Value.Type), param.Value.Type, null)
};
parameters[param.Key] = new
{
type = param.Value.TypeText,
value
};
}
if (sortByDescriptor) {
var orderedParams = new Dictionary<string, object>();
var paramNamesInDescriptor = avatarDescriptor.expressionParameters.parameters
.Select(p => p.name)
.Where(name => parameters.ContainsKey(name));
foreach (var name in paramNamesInDescriptor)
orderedParams[name] = parameters[name];
var unmatchedParams = parameters.Keys
.Where(k => !orderedParams.ContainsKey(k))
.OrderBy(k => k);
foreach (var name in unmatchedParams)
orderedParams[name] = parameters[name];
parameters = orderedParams;
}
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
FloatFormatHandling = FloatFormatHandling.String, // We'll format floats ourselves
Converters = new List<JsonConverter> { new Float2DecimalConverter() }
};
var json = JsonConvert.SerializeObject(parameters, settings);
File.WriteAllText(path, json);
EditorUtility.DisplayDialog("Export Complete", $"{parameters.Count} Parameters have been exported successfully!", "OK");
}
}
}
class Float2DecimalConverter : JsonConverter
{
public override bool CanConvert(Type objectType) =>
objectType == typeof(float) || objectType == typeof(double);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is float f)
writer.WriteRawValue(f.ToString("0.00"));
else if (value is double d)
writer.WriteRawValue(d.ToString("0.00"));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) =>
throw new NotImplementedException();
}