上传YomovSDK

This commit is contained in:
Sora丶kong
2026-03-03 03:15:46 +08:00
parent 9096da7e6c
commit eb97f31065
6477 changed files with 1932208 additions and 3 deletions

View File

@@ -0,0 +1,343 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.UnityConverters.Configuration;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEngine;
// Unity 2020 also has a type cache: UnityEditor.TypeCache:
// https://docs.unity3d.com/2019.2/Documentation/ScriptReference/TypeCache.html
using TypeCache = Newtonsoft.Json.UnityConverters.Utility.TypeCache;
namespace Newtonsoft.Json.UnityConverters.Editor
{
using Editor = UnityEditor.Editor;
[CustomEditor(typeof(UnityConvertersConfig))]
public class UnityConvertersConfigEditor : Editor
{
private SerializedProperty _useUnityContractResolver;
private SerializedProperty _useAllOutsideConverters;
private SerializedProperty _outsideConverters;
private SerializedProperty _useAllUnityConverters;
private SerializedProperty _unityConverters;
private SerializedProperty _useAllJsonNetConverters;
private SerializedProperty _jsonNetConverters;
private SerializedProperty _autoSyncConverters;
private AnimBool _outsideConvertersShow;
private AnimBool _unityConvertersShow;
private AnimBool _jsonNetConvertersShow;
private AnimBool _autoSyncConvertersShow;
private bool _isDirty;
private static class Styles
{
public static GUIStyle headerStyle;
public static GUIStyle boldHeaderStyle;
static Styles()
{
headerStyle = new GUIStyle { fontSize = 20, wordWrap = true, normal = EditorStyles.label.normal };
boldHeaderStyle = new GUIStyle { fontSize = 20, fontStyle = FontStyle.Bold, wordWrap = true, normal = EditorStyles.label.normal };
}
}
private void OnEnable()
{
var config = (UnityConvertersConfig)target;
var grouped = UnityConverterInitializer.FindGroupedConverters(config);
// Hack around the "SerializedObjectNotCreatableException: Object at index 0 is null"
// error message
try
{
_ = serializedObject;
}
catch (Exception)
{
return;
}
_useUnityContractResolver = serializedObject.FindProperty(nameof(UnityConvertersConfig.useUnityContractResolver));
_useAllOutsideConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.useAllOutsideConverters));
_outsideConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.outsideConverters));
_useAllUnityConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.useAllUnityConverters));
_unityConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.unityConverters));
_useAllJsonNetConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.useAllJsonNetConverters));
_jsonNetConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.jsonNetConverters));
_autoSyncConverters = serializedObject.FindProperty(nameof(UnityConvertersConfig.autoSyncConverters));
_outsideConvertersShow = new AnimBool(_outsideConverters.isExpanded);
_unityConvertersShow = new AnimBool(_unityConverters.isExpanded);
_jsonNetConvertersShow = new AnimBool(_jsonNetConverters.isExpanded);
_autoSyncConvertersShow = new AnimBool(!_autoSyncConverters.boolValue);
_outsideConvertersShow.valueChanged.AddListener(Repaint);
_unityConvertersShow.valueChanged.AddListener(Repaint);
_jsonNetConvertersShow.valueChanged.AddListener(Repaint);
serializedObject.Update();
AddAndSetupConverters(_outsideConverters, grouped.outsideConverters, _useAllOutsideConverters.boolValue);
AddAndSetupConverters(_unityConverters, grouped.unityConverters, _useAllUnityConverters.boolValue);
AddAndSetupConverters(_jsonNetConverters, grouped.jsonNetConverters, _useAllJsonNetConverters.boolValue);
serializedObject.ApplyModifiedProperties();
}
public override void OnInspectorGUI()
{
_isDirty = false;
EditorGUILayout.LabelField("Settings for the converters of", Styles.headerStyle);
EditorGUILayout.LabelField("Newtonsoft.Json-for-Unity.Converters", Styles.boldHeaderStyle);
serializedObject.Update();
EditorGUILayout.Space();
ToggleLeft(_useUnityContractResolver, "Custom 'Newtonsoft.Json.Serialization.IContractResolver' defined to" +
" properly handle the 'UnityEngine.SerializeFieldAttribute' attribute and correctly creates" +
" 'UnityEngine.ScriptableObject' via 'ScriptableObject.Create()' instead of the default" +
" 'new ScriptableObject()'.");
EditorGUILayout.Space();
FoldedConverters(_useAllOutsideConverters, _outsideConverters, _outsideConvertersShow,
"Registers all classes outside of the 'Newtonsoft.Json.*' namespace" +
" that derive from 'Newtonsoft.Json.JsonConverter' that has a default constructor.");
EditorGUILayout.Space();
FoldedConverters(_useAllUnityConverters, _unityConverters, _unityConvertersShow,
"Registers all classes inside of the 'Newtonsoft.Json.UnityConverters.*' namespace.");
EditorGUILayout.Space();
FoldedConverters(_useAllJsonNetConverters, _jsonNetConverters, _jsonNetConvertersShow,
"Registers all classes inside of the 'Newtonsoft.Json.UnityConverters.*' namespace.");
EditorGUILayout.Space();
ToggleLeft(_autoSyncConverters,
"Automatic synchronization of JsonConverter types is enabled by default," +
" but can induce a heavy spike on each assembly reload (such as when entering play mode) on bigger projects.");
_autoSyncConvertersShow.target = !_autoSyncConverters.boolValue;
if (EditorGUILayout.BeginFadeGroup(_autoSyncConvertersShow.faded))
{
EditorGUILayout.HelpBox("The Newtonsoft.Json-for-Unity.Converters package will no longer automatically" +
" look for new JsonConverters.\n\n" +
"Having this automatic scan disabled reduces the load spike caused on larger projects every time you enter play mode," +
" but you must instead remember to press the sync button below every time you add a new JsonConverter.",
MessageType.Warning);
if (GUILayout.Button("Manual Converter Sync Now"))
{
var grouped = ConverterGrouping.Create(UnityConverterInitializer.FindConverters());
AddAndSetupConverters(_outsideConverters, grouped.outsideConverters, _useAllOutsideConverters.boolValue);
AddAndSetupConverters(_unityConverters, grouped.unityConverters, _useAllUnityConverters.boolValue);
AddAndSetupConverters(_jsonNetConverters, grouped.jsonNetConverters, _useAllJsonNetConverters.boolValue);
}
}
EditorGUILayout.EndFadeGroup();
serializedObject.ApplyModifiedProperties();
if (_isDirty)
{
UnityConverterInitializer.RefreshSettingsFromConfig();
}
}
private void AddAndSetupConverters(SerializedProperty arrayProperty, IList<Type> converterTypes, bool newAreEnabledByDefault)
{
var elements = EnumerateArrayElements(arrayProperty).ToArray();
var elementTypes = elements
.Select(e => TypeCache.FindType(
name: e.FindPropertyRelative(nameof(ConverterConfig.converterName)).stringValue,
assemblyName: e.FindPropertyRelative(nameof(ConverterConfig.converterAssembly)).stringValue
))
.ToArray();
// Refresh missing fields on existing types
for (int i = 0; i < elements.Length; i++)
{
SerializedProperty elem = elements[i];
Type type = elementTypes[i];
var assemblyNameProp = elem.FindPropertyRelative(nameof(ConverterConfig.converterAssembly));
if (string.IsNullOrEmpty(assemblyNameProp.stringValue))
{
assemblyNameProp.stringValue = type.Assembly.GetName().Name;
}
}
Type[] missingConverters = converterTypes
.Where(type => !elementTypes.Contains(type))
.ToArray();
// Cleanup excess types
for (int i = elementTypes.Length - 1; i >= 0; i--)
{
if (converterTypes.Contains(elementTypes[i]))
{
continue;
}
string typeName = arrayProperty.GetArrayElementAtIndex(i).FindPropertyRelative(nameof(ConverterConfig.converterName)).stringValue;
Debug.Log($"Removed type from JsonConverter list: \"{typeName}\"", target);
arrayProperty.DeleteArrayElementAtIndex(i);
}
foreach (Type converterType in missingConverters)
{
int nextIndex = arrayProperty.arraySize;
arrayProperty.InsertArrayElementAtIndex(nextIndex);
SerializedProperty elemProp = arrayProperty.GetArrayElementAtIndex(nextIndex);
SerializedProperty enabledProp = elemProp.FindPropertyRelative(nameof(ConverterConfig.enabled));
SerializedProperty converterNameProp = elemProp.FindPropertyRelative(nameof(ConverterConfig.converterName));
SerializedProperty assemblyNameProp = elemProp.FindPropertyRelative(nameof(ConverterConfig.converterAssembly));
enabledProp.boolValue = newAreEnabledByDefault;
converterNameProp.stringValue = converterType.FullName;
assemblyNameProp.stringValue = converterType.Assembly.GetName().Name;
}
}
private static IEnumerable<SerializedProperty> EnumerateArrayElements(SerializedProperty arrayProperty)
{
for (int i = 0; i < arrayProperty.arraySize; i++)
{
yield return arrayProperty.GetArrayElementAtIndex(i);
}
}
private void FoldedConverters(
SerializedProperty useAllBoolProperty,
SerializedProperty convertersArrayProperty,
AnimBool foldoutAnim,
string tooltip)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
ToggleLeft(useAllBoolProperty, tooltip);
EditorGUI.BeginDisabledGroup(useAllBoolProperty.boolValue || convertersArrayProperty.arraySize == 0);
FoldoutConvertersList(convertersArrayProperty, foldoutAnim);
EditorGUI.EndDisabledGroup();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
private static void ToggleLeft(SerializedProperty property, string tooltip)
{
var content = new GUIContent {
text = property.displayName,
tooltip = tooltip,
};
property.boolValue = EditorGUILayout.ToggleLeft(content, property.boolValue);
}
private void FoldoutConvertersList(SerializedProperty property, AnimBool fadedAnim)
{
string displayName = $"{property.displayName} ({(property.arraySize == 0 ? "none found" : property.arraySize.ToString())})";
EditorGUI.indentLevel++;
property.isExpanded = EditorGUILayout.Foldout(property.isExpanded, displayName, true);
EditorGUI.indentLevel--;
fadedAnim.target = property.isExpanded;
if (EditorGUILayout.BeginFadeGroup(fadedAnim.faded))
{
EditorGUI.indentLevel++;
var allConfigsWithType = EnumerateArrayElements(property)
.Select(o => (
serializedProperty: o,
type: TypeCache.FindType(
name: o.FindPropertyRelative(nameof(ConverterConfig.converterName)).stringValue,
assemblyName: o.FindPropertyRelative(nameof(ConverterConfig.converterAssembly)).stringValue
)
))
.Where(o => o.type != null)
.OrderBy(o => o.type.FullName);
foreach (var namespaceGroup in allConfigsWithType.GroupBy(o => GetTypeNamespace(o.type)))
{
var groupLabel = new GUIContent {
tooltip = GetNamespaceTooltip(namespaceGroup),
text = GetNamespaceHeader(namespaceGroup),
};
EditorGUILayout.LabelField(groupLabel, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
foreach (var configWithType in namespaceGroup.OrderBy(o => o.type?.Name))
{
SerializedProperty enabledProp = configWithType.serializedProperty.FindPropertyRelative(nameof(ConverterConfig.enabled));
if (configWithType.type != null)
{
var toggleContent = new GUIContent {
text = configWithType.type.Name,
tooltip = configWithType.type.AssemblyQualifiedName,
};
bool oldValue = enabledProp.boolValue;
enabledProp.boolValue = EditorGUILayout.ToggleLeft(toggleContent, enabledProp.boolValue);
if (oldValue != enabledProp.boolValue)
{
_isDirty = true;
}
}
else
{
if (enabledProp.boolValue)
{
enabledProp.boolValue = false;
}
SerializedProperty converterNameProp = configWithType.serializedProperty.FindPropertyRelative(nameof(ConverterConfig.converterName));
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ToggleLeft($"Unknown type: {converterNameProp.stringValue}", false);
EditorGUI.EndDisabledGroup();
}
}
EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
EditorGUI.indentLevel--;
}
EditorGUILayout.EndFadeGroup();
}
private static string GetNamespaceHeader(IGrouping<string, (SerializedProperty serializedProperty, Type type)> namespaceGroup)
{
return $"{namespaceGroup.Key ?? "<Misconfigured converters>"} ({namespaceGroup.Count()})";
}
private static string GetNamespaceTooltip(IGrouping<string, (SerializedProperty serializedProperty, Type type)> namespaceGroup)
{
switch (namespaceGroup.Key)
{
case "global::":
return "Converters found with a default constructor from the global namespace.";
case null:
return "Converters that was found in the configuration but was" +
" unable to map them to existing types. Maybe the type got renamed, or moved to a different" +
" namespace?";
default:
return $"Converters found with a default constructor from the namespace '{namespaceGroup.Key}'.";
}
}
private static string GetTypeNamespace(Type type)
{
return type is null ? null : (type.Namespace ?? "global::");
}
}
}