Added Unity project files

This commit is contained in:
2026-06-07 16:58:24 +01:00
parent 3cc05d260b
commit 23bbcab156
3942 changed files with 453676 additions and 0 deletions

View File

@ -0,0 +1,766 @@
//-----------------------------------------------------------------------
// <copyright file="AOTSupportScanner.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Core;
#if UNITY_EDITOR
namespace VRC.Udon.Serialization.OdinSerializer.Editor
{
using Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using System.Reflection;
using UnityEngine.SceneManagement;
using System.Collections;
public sealed class AOTSupportScanner : IDisposable
{
private bool scanning;
private bool allowRegisteringScannedTypes;
private HashSet<Type> seenSerializedTypes = new HashSet<Type>();
private HashSet<string> scannedPathsNoDependencies = new HashSet<string>();
private HashSet<string> scannedPathsWithDependencies = new HashSet<string>();
private static System.Diagnostics.Stopwatch smartProgressBarWatch = System.Diagnostics.Stopwatch.StartNew();
private static int smartProgressBarDisplaysSinceLastUpdate = 0;
private static readonly MethodInfo PlayerSettings_GetPreloadedAssets_Method = typeof(PlayerSettings).GetMethod("GetPreloadedAssets", BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null);
private static readonly PropertyInfo Debug_Logger_Property = typeof(Debug).GetProperty("unityLogger") ?? typeof(Debug).GetProperty("logger");
public void BeginScan()
{
this.scanning = true;
allowRegisteringScannedTypes = false;
this.seenSerializedTypes.Clear();
this.scannedPathsNoDependencies.Clear();
this.scannedPathsWithDependencies.Clear();
FormatterLocator.OnLocatedEmittableFormatterForType += this.OnLocatedEmitType;
FormatterLocator.OnLocatedFormatter += this.OnLocatedFormatter;
Serializer.OnSerializedType += this.OnSerializedType;
}
public bool ScanPreloadedAssets(bool showProgressBar)
{
// The API does not exist in this version of Unity
if (PlayerSettings_GetPreloadedAssets_Method == null) return true;
UnityEngine.Object[] assets = (UnityEngine.Object[])PlayerSettings_GetPreloadedAssets_Method.Invoke(null, null);
if (assets == null) return true;
try
{
for (int i = 0; i < assets.Length; i++)
{
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning preloaded assets for AOT support", (i + 1) + " / " + assets.Length, (float)i / assets.Length))
{
return false;
}
var asset = assets[i];
if (asset == null) continue;
if (AssetDatabase.Contains(asset))
{
// Scan the asset and all its dependencies
var path = AssetDatabase.GetAssetPath(asset);
this.ScanAsset(path, true);
}
else
{
// Just scan the asset
this.ScanObject(asset);
}
}
}
finally
{
if (showProgressBar)
{
EditorUtility.ClearProgressBar();
}
}
return true;
}
public bool ScanAssetBundle(string bundle)
{
string[] assets = AssetDatabase.GetAssetPathsFromAssetBundle(bundle);
foreach (var asset in assets)
{
this.ScanAsset(asset, true);
}
return true;
}
public bool ScanAllAssetBundles(bool showProgressBar)
{
try
{
string[] bundles = AssetDatabase.GetAllAssetBundleNames();
for (int i = 0; i < bundles.Length; i++)
{
var bundle = bundles[i];
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning asset bundles for AOT support", bundle, (float)i / bundles.Length))
{
return false;
}
this.ScanAssetBundle(bundle);
}
}
finally
{
if (showProgressBar)
{
EditorUtility.ClearProgressBar();
}
}
return true;
}
public bool ScanAllAddressables(bool includeAssetDependencies, bool showProgressBar)
{
// We don't know whether the addressables package is installed or not. So... needs must.
// Our only real choice is to utilize reflection that's stocked to the brim with failsafes
// and error logging.
//
// Truly, the code below should not have needed to be written.
// The following section is the code as it would be without reflection. Please modify this
// code reference to be accurate if the reflection code is changed.
/*
var settings = UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject.Settings;
if (settings != null && settings.groups != null)
{
foreach (AddressableAssetGroup group in settings.groups)
{
if (group.HasSchema(typeof(PlayerDataGroupSchema))) continue;
List<AddressableAssetEntry> results = new List<AddressableAssetEntry>();
group.GatherAllAssets(results, true, true, true, null);
foreach (var result in results)
{
this.ScanAsset(result.AssetPath, includeAssetDependencies);
}
}
}
*/
bool progressBarWasDisplayed = false;
try
{
Type AddressableAssetSettingsDefaultObject_Type = TwoWaySerializationBinder.Default.BindToType("UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject");
if (AddressableAssetSettingsDefaultObject_Type == null) return true;
PropertyInfo AddressableAssetSettingsDefaultObject_Settings = AddressableAssetSettingsDefaultObject_Type.GetProperty("Settings");
if (AddressableAssetSettingsDefaultObject_Settings == null) throw new NotSupportedException("AddressableAssetSettingsDefaultObject.Settings property not found");
ScriptableObject settings = (ScriptableObject)AddressableAssetSettingsDefaultObject_Settings.GetValue(null, null);
if (settings == null) return true;
Type AddressableAssetSettings_Type = settings.GetType();
PropertyInfo AddressableAssetSettings_groups = AddressableAssetSettings_Type.GetProperty("groups");
if (AddressableAssetSettings_groups == null) throw new NotSupportedException("AddressableAssetSettings.groups property not found");
IList groups = (IList)AddressableAssetSettings_groups.GetValue(settings, null);
if (groups == null) return true;
Type PlayerDataGroupSchema_Type = TwoWaySerializationBinder.Default.BindToType("UnityEditor.AddressableAssets.Settings.GroupSchemas.PlayerDataGroupSchema");
if (PlayerDataGroupSchema_Type == null) throw new NotSupportedException("PlayerDataGroupSchema type not found");
Type AddressableAssetGroup_Type = null;
MethodInfo AddressableAssetGroup_HasSchema = null;
MethodInfo AddressableAssetGroup_GatherAllAssets = null;
Type AddressableAssetEntry_Type = TwoWaySerializationBinder.Default.BindToType("UnityEditor.AddressableAssets.Settings.AddressableAssetEntry");
if (AddressableAssetEntry_Type == null) throw new NotSupportedException("AddressableAssetEntry type not found");
Type List_AddressableAssetEntry_Type = typeof(List<>).MakeGenericType(AddressableAssetEntry_Type);
Type Func_AddressableAssetEntry_bool_Type = typeof(Func<,>).MakeGenericType(AddressableAssetEntry_Type, typeof(bool));
PropertyInfo AddressableAssetEntry_AssetPath = AddressableAssetEntry_Type.GetProperty("AssetPath");
if (AddressableAssetEntry_AssetPath == null) throw new NotSupportedException("AddressableAssetEntry.AssetPath property not found");
foreach (object groupObj in groups)
{
ScriptableObject group = (ScriptableObject)groupObj;
if (group == null) continue;
string groupName = group.name;
if (AddressableAssetGroup_Type == null)
{
AddressableAssetGroup_Type = group.GetType();
AddressableAssetGroup_HasSchema = AddressableAssetGroup_Type.GetMethod("HasSchema", Flags.InstancePublic, null, new Type[] { typeof(Type) }, null);
if (AddressableAssetGroup_HasSchema == null) throw new NotSupportedException("AddressableAssetGroup.HasSchema(Type type) method not found");
AddressableAssetGroup_GatherAllAssets = AddressableAssetGroup_Type.GetMethod("GatherAllAssets", Flags.InstancePublic, null, new Type[] { List_AddressableAssetEntry_Type, typeof(bool), typeof(bool), typeof(bool), Func_AddressableAssetEntry_bool_Type }, null);
if (AddressableAssetGroup_GatherAllAssets == null) throw new NotSupportedException("AddressableAssetGroup.GatherAllAssets(List<AddressableAssetEntry> results, bool includeSelf, bool recurseAll, bool includeSubObjects, Func<AddressableAssetEntry, bool> entryFilter) method not found");
}
bool hasPlayerDataGroupSchema = (bool)AddressableAssetGroup_HasSchema.Invoke(group, new object[] { PlayerDataGroupSchema_Type });
if (hasPlayerDataGroupSchema) continue; // Skip this group, since it contains all the player data such as resources and build scenes, and we're scanning that separately
IList results = (IList)Activator.CreateInstance(List_AddressableAssetEntry_Type);
AddressableAssetGroup_GatherAllAssets.Invoke(group, new object[] { results, true, true, true, null });
for (int i = 0; i < results.Count; i++)
{
object entry = (object)results[i];
if (entry == null) continue;
string assetPath = (string)AddressableAssetEntry_AssetPath.GetValue(entry, null);
if (showProgressBar)
{
progressBarWasDisplayed = true;
if (DisplaySmartUpdatingCancellableProgressBar("Scanning addressables for AOT support", groupName + ": " + assetPath, (float)i / results.Count))
{
return false;
}
}
// Finally!
this.ScanAsset(assetPath, includeAssetDependencies);
}
}
}
catch (NotSupportedException ex)
{
Debug.LogWarning("Could not AOT scan Addressables assets due to missing APIs: " + ex.Message);
}
catch (Exception ex)
{
Debug.LogError("Scanning addressables failed with the following exception...");
Debug.LogException(ex);
}
finally
{
if (progressBarWasDisplayed)
{
EditorUtility.ClearProgressBar();
}
}
return true;
}
public bool ScanAllResources(bool includeResourceDependencies, bool showProgressBar, List<string> resourcesPaths = null)
{
if (resourcesPaths == null)
{
resourcesPaths = new List<string>() {""};
}
try
{
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning resources for AOT support", "Loading resource assets", 0f))
{
return false;
}
var resourcesPathsSet = new HashSet<string>();
for (int i = 0; i < resourcesPaths.Count; i++)
{
var resourcesPath = resourcesPaths[i];
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Listing resources for AOT support", resourcesPath, (float)i / resourcesPaths.Count))
{
return false;
}
var resources = Resources.LoadAll(resourcesPath);
foreach (var resource in resources)
{
try
{
var assetPath = AssetDatabase.GetAssetPath(resource);
if (assetPath != null)
{
resourcesPathsSet.Add(assetPath);
}
}
catch (MissingReferenceException ex)
{
Debug.LogError("A resource threw a missing reference exception when scanning. Skipping resource and continuing scan.", resource);
Debug.LogException(ex, resource);
continue;
}
}
}
string[] resourcePaths = resourcesPathsSet.ToArray();
for (int i = 0; i < resourcePaths.Length; i++)
{
if (resourcePaths[i] == null) continue;
try
{
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning resource " + i + " for AOT support", resourcePaths[i], (float)i / resourcePaths.Length))
{
return false;
}
var assetPath = resourcePaths[i];
// Exclude editor-only resources
if (assetPath.ToLower().Contains("/editor/")) continue;
this.ScanAsset(assetPath, includeAssetDependencies: includeResourceDependencies);
}
catch (MissingReferenceException ex)
{
Debug.LogError("A resource '" + resourcePaths[i] + "' threw a missing reference exception when scanning. Skipping resource and continuing scan.");
Debug.LogException(ex);
continue;
}
}
return true;
}
finally
{
if (showProgressBar)
{
EditorUtility.ClearProgressBar();
}
}
}
public bool ScanBuildScenes(bool includeSceneDependencies, bool showProgressBar)
{
var scenePaths = EditorBuildSettings.scenes
.Where(n => n.enabled)
.Select(n => n.path)
.ToArray();
return this.ScanScenes(scenePaths, includeSceneDependencies, showProgressBar);
}
public bool ScanScenes(string[] scenePaths, bool includeSceneDependencies, bool showProgressBar)
{
if (scenePaths.Length == 0) return true;
bool formerForceEditorModeSerialization = UnitySerializationUtility.ForceEditorModeSerialization;
try
{
UnitySerializationUtility.ForceEditorModeSerialization = true;
bool hasDirtyScenes = false;
for (int i = 0; i < EditorSceneManager.sceneCount; i++)
{
if (EditorSceneManager.GetSceneAt(i).isDirty)
{
hasDirtyScenes = true;
break;
}
}
if (hasDirtyScenes && !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
return false;
}
var oldSceneSetup = EditorSceneManager.GetSceneManagerSetup();
try
{
for (int i = 0; i < scenePaths.Length; i++)
{
var scenePath = scenePaths[i];
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning scenes for AOT support", "Scene " + (i + 1) + "/" + scenePaths.Length + " - " + scenePath, (float)i / scenePaths.Length))
{
return false;
}
if (!System.IO.File.Exists(scenePath))
{
Debug.LogWarning("Skipped AOT scanning scene '" + scenePath + "' for a file not existing at the scene path.");
continue;
}
Scene openScene = default(Scene);
try
{
openScene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
}
catch
{
Debug.LogWarning("Skipped AOT scanning scene '" + scenePath + "' for throwing exceptions when trying to load it.");
continue;
}
var sceneGOs = Resources.FindObjectsOfTypeAll<GameObject>();
foreach (var go in sceneGOs)
{
if (go.scene != openScene) continue;
if ((go.hideFlags & HideFlags.DontSaveInBuild) == 0)
{
#if VRC_CLIENT
using (go.GetComponentsPooled(out List<ISerializationCallbackReceiver> components))
#else
ISerializationCallbackReceiver[] components = go.GetComponents<ISerializationCallbackReceiver>();
#endif
{
foreach (var component in components)
{
try
{
this.allowRegisteringScannedTypes = true;
component.OnBeforeSerialize();
var prefabSupporter = component as ISupportsPrefabSerialization;
if (prefabSupporter != null)
{
// Also force a serialization of the object's prefab modifications, in case there are unknown types in there
List<UnityEngine.Object> objs = null;
var mods = UnitySerializationUtility.DeserializePrefabModifications(prefabSupporter.SerializationData.PrefabModifications, prefabSupporter.SerializationData.PrefabModificationsReferencedUnityObjects);
UnitySerializationUtility.SerializePrefabModifications(mods, ref objs);
}
}
finally
{
this.allowRegisteringScannedTypes = false;
}
}
}
}
}
}
// Load a new empty scene that will be unloaded immediately, just to be sure we completely clear all changes made by the scan
// Sometimes this fails for unknown reasons. In that case, swallow any exceptions, and just soldier on and hope for the best!
// Additionally, also eat any debug logs that happen here, because logged errors can stop the build process, and we don't want
// that to happen.
UnityEngine.ILogger logger = null;
if (Debug_Logger_Property != null)
{
logger = (UnityEngine.ILogger)Debug_Logger_Property.GetValue(null, null);
}
bool previous = true;
try
{
if (logger != null)
{
previous = logger.logEnabled;
logger.logEnabled = false;
}
EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Single);
}
catch { }
finally
{
if (logger != null)
{
logger.logEnabled = previous;
}
}
}
finally
{
if (oldSceneSetup != null && oldSceneSetup.Length > 0)
{
if (showProgressBar)
{
EditorUtility.DisplayProgressBar("Restoring scene setup", "", 1.0f);
}
EditorSceneManager.RestoreSceneManagerSetup(oldSceneSetup);
}
}
if (includeSceneDependencies)
{
for (int i = 0; i < scenePaths.Length; i++)
{
var scenePath = scenePaths[i];
if (showProgressBar && DisplaySmartUpdatingCancellableProgressBar("Scanning scene dependencies for AOT support", "Scene " + (i + 1) + "/" + scenePaths.Length + " - " + scenePath, (float)i / scenePaths.Length))
{
return false;
}
string[] dependencies = AssetDatabase.GetDependencies(scenePath, recursive: true);
foreach (var dependency in dependencies)
{
this.ScanAsset(dependency, includeAssetDependencies: false); // All dependencies of this asset were already included recursively by Unity
}
}
}
return true;
}
finally
{
if (showProgressBar)
{
EditorUtility.ClearProgressBar();
}
UnitySerializationUtility.ForceEditorModeSerialization = formerForceEditorModeSerialization;
}
}
public bool ScanAsset(string assetPath, bool includeAssetDependencies)
{
if (includeAssetDependencies)
{
if (this.scannedPathsWithDependencies.Contains(assetPath)) return true; // Already scanned this asset
this.scannedPathsWithDependencies.Add(assetPath);
this.scannedPathsNoDependencies.Add(assetPath);
}
else
{
if (this.scannedPathsNoDependencies.Contains(assetPath)) return true; // Already scanned this asset
this.scannedPathsNoDependencies.Add(assetPath);
}
if (assetPath.EndsWith(".unity"))
{
return this.ScanScenes(new string[] { assetPath }, includeAssetDependencies, false);
}
if (!(assetPath.EndsWith(".asset") || assetPath.EndsWith(".prefab")))
{
// ScanAsset can only scan .unity, .asset and .prefab assets.
return false;
}
bool formerForceEditorModeSerialization = UnitySerializationUtility.ForceEditorModeSerialization;
try
{
UnitySerializationUtility.ForceEditorModeSerialization = true;
var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
if (assets == null || assets.Length == 0)
{
return false;
}
foreach (var asset in assets)
{
if (asset == null) continue;
this.ScanObject(asset);
}
if (includeAssetDependencies)
{
string[] dependencies = AssetDatabase.GetDependencies(assetPath, recursive: true);
foreach (var dependency in dependencies)
{
this.ScanAsset(dependency, includeAssetDependencies: false); // All dependencies were already included recursively by Unity
}
}
return true;
}
finally
{
UnitySerializationUtility.ForceEditorModeSerialization = formerForceEditorModeSerialization;
}
}
public void ScanObject(UnityEngine.Object obj)
{
if (obj is ISerializationCallbackReceiver)
{
bool formerForceEditorModeSerialization = UnitySerializationUtility.ForceEditorModeSerialization;
try
{
UnitySerializationUtility.ForceEditorModeSerialization = true;
this.allowRegisteringScannedTypes = true;
(obj as ISerializationCallbackReceiver).OnBeforeSerialize();
}
finally
{
this.allowRegisteringScannedTypes = false;
UnitySerializationUtility.ForceEditorModeSerialization = formerForceEditorModeSerialization;
}
}
}
public List<Type> EndScan()
{
if (!this.scanning) throw new InvalidOperationException("Cannot end a scan when scanning has not begun.");
var result = this.seenSerializedTypes.ToList();
this.Dispose();
return result;
}
public void Dispose()
{
if (this.scanning)
{
FormatterLocator.OnLocatedEmittableFormatterForType -= this.OnLocatedEmitType;
FormatterLocator.OnLocatedFormatter -= this.OnLocatedFormatter;
Serializer.OnSerializedType -= this.OnSerializedType;
this.scanning = false;
this.seenSerializedTypes.Clear();
this.allowRegisteringScannedTypes = false;
}
}
private void OnLocatedEmitType(Type type)
{
if (!AllowRegisterType(type)) return;
this.RegisterType(type);
}
private void OnSerializedType(Type type)
{
if (!AllowRegisterType(type)) return;
this.RegisterType(type);
}
private void OnLocatedFormatter(IFormatter formatter)
{
var type = formatter.SerializedType;
if (type == null) return;
if (!AllowRegisterType(type)) return;
this.RegisterType(type);
}
public static bool AllowRegisterType(Type type)
{
if (IsEditorOnlyAssembly(type.Assembly))
return false;
if (type.IsGenericType)
{
foreach (var parameter in type.GetGenericArguments())
{
if (!AllowRegisterType(parameter)) return false;
}
}
return true;
}
private static bool IsEditorOnlyAssembly(Assembly assembly)
{
return EditorAssemblyNames.Contains(assembly.GetName().Name);
}
private static HashSet<string> EditorAssemblyNames = new HashSet<string>()
{
"Assembly-CSharp-Editor",
"Assembly-UnityScript-Editor",
"Assembly-Boo-Editor",
"Assembly-CSharp-Editor-firstpass",
"Assembly-UnityScript-Editor-firstpass",
"Assembly-Boo-Editor-firstpass",
typeof(Editor).Assembly.GetName().Name
};
private void RegisterType(Type type)
{
if (!this.allowRegisteringScannedTypes) return;
//if (type.IsAbstract || type.IsInterface) return;
if (type.IsGenericType && (type.IsGenericTypeDefinition || !type.IsFullyConstructedGenericType())) return;
//if (this.seenSerializedTypes.Add(type))
//{
// Debug.Log("Added " + type.GetNiceFullName());
//}
this.seenSerializedTypes.Add(type);
if (type.IsGenericType)
{
foreach (var arg in type.GetGenericArguments())
{
this.RegisterType(arg);
}
}
}
private static bool DisplaySmartUpdatingCancellableProgressBar(string title, string details, float progress, int updateIntervalByMS = 200, int updateIntervalByCall = 50)
{
bool updateProgressBar =
smartProgressBarWatch.ElapsedMilliseconds >= updateIntervalByMS
|| ++smartProgressBarDisplaysSinceLastUpdate >= updateIntervalByCall;
if (updateProgressBar)
{
smartProgressBarWatch.Stop();
smartProgressBarWatch.Reset();
smartProgressBarWatch.Start();
smartProgressBarDisplaysSinceLastUpdate = 0;
if (EditorUtility.DisplayCancelableProgressBar(title, details, progress))
{
return true;
}
}
return false;
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 94a6cc2044fcd2cb317b1cdb1e8fcdaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,418 @@
//-----------------------------------------------------------------------
// <copyright file="AOTSupportUtilities.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
#if UNITY_EDITOR
namespace VRC.Udon.Serialization.OdinSerializer.Editor
{
using VRC.Udon.Serialization.OdinSerializer.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.Scripting;
public static class AOTSupportUtilities
{
/// <summary>
/// Scans the project's build scenes and resources, plus their dependencies, for serialized types to support. Progress bars are shown during the scan.
/// </summary>
/// <param name="serializedTypes">The serialized types to support.</param>
/// <param name="scanBuildScenes">Whether to scan the project's build scenes.</param>
/// <param name="scanAllAssetBundles">Whether to scan all the project's asset bundles.</param>
/// <param name="scanPreloadedAssets">Whether to scan the project's preloaded assets.</param>
/// <param name="scanResources">Whether to scan the project's resources.</param>
/// <param name="resourcesToScan">An optional list of the resource paths to scan. Only has an effect if the scanResources argument is true. All the resources will be scanned if null.</param>
/// <returns>true if the scan succeeded, false if the scan failed or was cancelled</returns>
public static bool ScanProjectForSerializedTypes(out List<Type> serializedTypes, bool scanBuildScenes = true, bool scanAllAssetBundles = true, bool scanPreloadedAssets = true, bool scanResources = true, List<string> resourcesToScan = null, bool scanAddressables = true)
{
using (var scanner = new AOTSupportScanner())
{
scanner.BeginScan();
if (scanBuildScenes && !scanner.ScanBuildScenes(includeSceneDependencies: true, showProgressBar: true))
{
Debug.Log("Project scan canceled while scanning scenes and their dependencies.");
serializedTypes = null;
return false;
}
if (scanResources && !scanner.ScanAllResources(includeResourceDependencies: true, showProgressBar: true, resourcesPaths: resourcesToScan))
{
Debug.Log("Project scan canceled while scanning resources and their dependencies.");
serializedTypes = null;
return false;
}
if (scanAllAssetBundles && !scanner.ScanAllAssetBundles(showProgressBar: true))
{
Debug.Log("Project scan canceled while scanning asset bundles and their dependencies.");
serializedTypes = null;
return false;
}
if (scanPreloadedAssets && !scanner.ScanPreloadedAssets(showProgressBar: true))
{
Debug.Log("Project scan canceled while scanning preloaded assets and their dependencies.");
serializedTypes = null;
return false;
}
if (scanAddressables && !scanner.ScanAllAddressables(includeAssetDependencies: true, showProgressBar: true))
{
Debug.Log("Project scan canceled while scanning addressable assets and their dependencies.");
serializedTypes = null;
return false;
}
serializedTypes = scanner.EndScan();
}
return true;
}
/// <summary>
/// Generates an AOT DLL, using the given parameters.
/// </summary>
public static void GenerateDLL(string dirPath, string assemblyName, List<Type> supportSerializedTypes, bool generateLinkXml = true)
{
#if UNITY_EDITOR && NET_4_6
if (!dirPath.EndsWith("/")) dirPath += "/";
var newDllPath = dirPath + assemblyName;
var fullDllPath = newDllPath + ".dll";
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName() { Name = assemblyName }, AssemblyBuilderAccess.Save, dirPath);
var module = assembly.DefineDynamicModule(assemblyName);
assembly.SetCustomAttribute(new CustomAttributeBuilder(typeof(EmittedAssemblyAttribute).GetConstructor(new Type[0]), new object[0]));
// VRChat Edit: Add the UnityAPICompatibilityVersion Attribute for the current version of Unity to skip API Updating.
#if UNITY_2019
assembly.SetCustomAttribute(new CustomAttributeBuilder(
typeof(UnityAPICompatibilityVersionAttribute).GetConstructor(new[]{typeof(string), typeof(bool)}),
new object[]{Application.unityVersion, true})
);
#else
assembly.SetCustomAttribute(new CustomAttributeBuilder(
typeof(UnityAPICompatibilityVersionAttribute).GetConstructor(new[]{typeof(string)}),
new object[]{Application.unityVersion})
);
#endif
// The following is a fix for Unity's crappy Mono runtime that doesn't know how to do this sort
// of stuff properly
//
// We must manually remove the "Default Dynamic Assembly" module that is automatically defined,
// otherwise a reference to that non-existent module will be saved into the assembly's IL, and
// that will cause a multitude of issues.
//
// We do this by forcing there to be only one module - the one we just defined, and we set the
// manifest module to be that module as well.
{
var modulesField = assembly.GetType().GetField("modules", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var manifestModuleField = assembly.GetType().GetField("manifest_module", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (modulesField != null)
{
modulesField.SetValue(assembly, new ModuleBuilder[] { module });
}
if (manifestModuleField != null)
{
manifestModuleField.SetValue(assembly, module);
}
}
const int serializedTypesPerType = 100;
for(int typeIndex = 0; typeIndex < Mathf.CeilToInt(supportSerializedTypes.Count / (float)serializedTypesPerType); typeIndex++)
{
var type = module.DefineType($"{assemblyName}.PreventCodeStrippingViaReferences{typeIndex:D4}", TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.NotPublic);
CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(typeof(PreserveAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
type.SetCustomAttribute(attributeBuilder);
var staticConstructor = type.DefineTypeInitializer();
var il = staticConstructor.GetILGenerator();
var falseLocal = il.DeclareLocal(typeof(bool));
il.Emit(OpCodes.Ldc_I4_0); // Load false
il.Emit(OpCodes.Stloc, falseLocal); // Set to falseLocal
HashSet<Type> seenTypes = new HashSet<Type>();
if(UnityVersion.Major == 2019 && UnityVersion.Minor == 2)
{
// This here is a hack that fixes Unity's assembly updater triggering faultily in Unity 2019.2
// (and in early 2019.3 alphas/betas, but we're not handling those). When it triggers, it edits
// the generated AOT assembly such that it immediately causes Unity to hard crash. Having this
// type reference present in the assembly prevents that from happening. (Any concrete type in
// the serialization assembly would work, this one is just a random pick.)
//
// Unity should have fixed this in 2019.3, but said that a backport to 2019.2 is not guaranteed
// to occur, though it might.
supportSerializedTypes.Add(typeof(DateTimeFormatter));
}
//var endPoint = il.DefineLabel();
//il.Emit(OpCodes.Br, endPoint);
for(int offset = 0; offset < serializedTypesPerType && offset + typeIndex * serializedTypesPerType < supportSerializedTypes.Count; offset++)
{
var serializedType = supportSerializedTypes[offset + typeIndex * serializedTypesPerType];
if(serializedType == null) continue;
bool isAbstract = serializedType.IsAbstract || serializedType.IsInterface;
if(serializedType.IsGenericType && (serializedType.IsGenericTypeDefinition || !serializedType.IsFullyConstructedGenericType()))
{
Debug.LogError(
"Skipping type '" + serializedType.GetNiceFullName() +
"'! Type is a generic type definition, or its arguments contain generic parameters; type must be a fully constructed generic type.");
continue;
}
if(seenTypes.Contains(serializedType)) continue;
seenTypes.Add(serializedType);
// Reference serialized type
{
if(serializedType.IsValueType)
{
var local = il.DeclareLocal(serializedType);
il.Emit(OpCodes.Ldloca, local);
il.Emit(OpCodes.Initobj, serializedType);
}
else if(!isAbstract)
{
var constructor = serializedType.GetConstructor(Type.EmptyTypes);
if(constructor != null)
{
il.Emit(OpCodes.Newobj, constructor);
il.Emit(OpCodes.Pop);
}
}
}
// Reference and/or create formatter type
if(!FormatterUtilities.IsPrimitiveType(serializedType) && !typeof(UnityEngine.Object).IsAssignableFrom(serializedType) && !isAbstract)
{
var actualFormatter = FormatterLocator.GetFormatter(serializedType, SerializationPolicies.Unity);
if(actualFormatter.GetType().IsDefined<EmittedFormatterAttribute>())
{
//TODO: Make emitted formatter code compatible with IL2CPP
//// Emit an actual AOT formatter into the generated assembly
//if (this.emitAOTFormatters)
//{
// var emittedFormatter = FormatterEmitter.EmitAOTFormatter(typeEntry.Type, module, SerializationPolicies.Unity);
// var emittedFormatterConstructor = emittedFormatter.GetConstructor(Type.EmptyTypes);
// il.Emit(OpCodes.Newobj, emittedFormatterConstructor);
// il.Emit(OpCodes.Pop);
//}
}
var formatters = FormatterLocator.GetAllCompatiblePredefinedFormatters(serializedType, SerializationPolicies.Unity);
foreach(var formatter in formatters)
{
// Reference the pre-existing formatter
var formatterConstructor = formatter.GetType().GetConstructor(Type.EmptyTypes);
if(formatterConstructor != null)
{
il.Emit(OpCodes.Newobj, formatterConstructor);
il.Emit(OpCodes.Pop);
}
}
//// Make sure we have a proper reflection formatter variant if all else goes wrong
//il.Emit(OpCodes.Newobj, typeof(ReflectionFormatter<>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes));
//il.Emit(OpCodes.Pop);
}
ConstructorInfo serializerConstructor;
// Reference serializer variant
if(serializedType.IsValueType)
{
serializerConstructor = Serializer.Get(serializedType).GetType().GetConstructor(Type.EmptyTypes);
il.Emit(OpCodes.Newobj, serializerConstructor);
// The following section is a fix for an issue on IL2CPP for PS4, where sometimes bytecode isn't
// generated for methods in base types of needed types - FX, Serializer<T>.ReadValueWeak()
// may be missing. This only seems to happen in a relevant way for value types.
{
var endLabel = il.DefineLabel();
// Load a false local value, then jump to the end of this segment of code due to that
// false value. This is an attempt to trick any potential code flow analysis made
// by IL2CPP that checks whether this segment of code is actually run.
//
// We don't run the code because if we did, that would actually throw a bunch of
// exceptions from invalid calls to ReadValueWeak and WriteValueWeak.
il.Emit(OpCodes.Ldloc, falseLocal);
il.Emit(OpCodes.Brfalse, endLabel);
var baseSerializerType = typeof(Serializer<>).MakeGenericType(serializedType);
var readValueWeakMethod = baseSerializerType.GetMethod(
"ReadValueWeak",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
null,
new Type[] { typeof(IDataReader) },
null);
var writeValueWeakMethod = baseSerializerType.GetMethod(
"WriteValueWeak",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
null,
new Type[] { typeof(string), typeof(object), typeof(IDataWriter) },
null);
il.Emit(OpCodes.Dup); // Duplicate serializer instance
il.Emit(OpCodes.Ldnull); // Load null argument for IDataReader reader
il.Emit(OpCodes.Callvirt, readValueWeakMethod); // Call ReadValueWeak on serializer instance
il.Emit(OpCodes.Pop); // Pop result of ReadValueWeak
il.Emit(OpCodes.Dup); // Duplicate serializer instance
il.Emit(OpCodes.Ldnull); // Load null argument for string name
il.Emit(OpCodes.Ldnull); // Load null argument for object value
il.Emit(OpCodes.Ldnull); // Load null argument for IDataWriter writer
il.Emit(OpCodes.Callvirt, writeValueWeakMethod); // Call WriteValueWeak on serializer instance
il.MarkLabel(endLabel); // This is where the code always jumps to, skipping the above
}
il.Emit(OpCodes.Pop); // Pop the serializer instance
}
else
{
serializerConstructor = typeof(ComplexTypeSerializer<>).MakeGenericType(serializedType).GetConstructor(Type.EmptyTypes);
il.Emit(OpCodes.Newobj, serializerConstructor);
il.Emit(OpCodes.Pop);
}
}
//il.MarkLabel(endPoint);
il.Emit(OpCodes.Ret);
type.CreateType();
}
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}
if (File.Exists(fullDllPath))
{
File.Delete(fullDllPath);
}
if (File.Exists(fullDllPath + ".meta"))
{
File.Delete(fullDllPath + ".meta");
}
try
{
AssetDatabase.Refresh();
}
catch (Exception)
{
// Sigh, Unity 5.3.0
}
assembly.Save(assemblyName);
File.Move(newDllPath, fullDllPath);
if (generateLinkXml)
{
File.WriteAllText(dirPath + "link.xml",
@"<linker>
<assembly fullname=""" + assemblyName + @""" preserve=""all""/>
</linker>");
}
try
{
AssetDatabase.Refresh();
}
catch (Exception)
{
// Sigh, Unity 5.3.0
}
var pluginImporter = PluginImporter.GetAtPath(fullDllPath) as PluginImporter;
if (pluginImporter != null)
{
//pluginImporter.ClearSettings();
pluginImporter.SetCompatibleWithEditor(false);
pluginImporter.SetCompatibleWithAnyPlatform(true);
// Disable for all standalones
pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false);
if (!UnityVersion.IsVersionOrGreater(2019, 2))
{
pluginImporter.SetCompatibleWithPlatform((BuildTarget)17, false); // StandaloneLinux
pluginImporter.SetCompatibleWithPlatform((BuildTarget)25, false); // StandaloneLinuxUniversal
}
// StandaloneOSXUniversal (<= 2017.2) / StandaloneOSX (>= 2017.3)
pluginImporter.SetCompatibleWithPlatform((BuildTarget)2, false);
if (!UnityVersion.IsVersionOrGreater(2017, 3))
{
pluginImporter.SetCompatibleWithPlatform((BuildTarget)4, false); // StandaloneOSXIntel
pluginImporter.SetCompatibleWithPlatform((BuildTarget)27, false); // StandaloneOSXIntel64
}
pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false);
//pluginImporter.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false);
//pluginImporter.SetCompatibleWithPlatform(BuildTarget.Android, false);
pluginImporter.SaveAndReimport();
}
AssetDatabase.SaveAssets();
#endif
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5fe153775edbadfa2b659e0e35dc881
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 55ffebf7dee93e24a93effecc78ad42e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,70 @@
//-----------------------------------------------------------------------
// <copyright file="BaseDictionaryKeyPathProvider.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System.Collections.Generic;
/// <summary>
/// Not yet documented.
/// </summary>
/// <typeparam name="T">Not yet documented.</typeparam>
public abstract class BaseDictionaryKeyPathProvider<T> : IDictionaryKeyPathProvider<T>, IComparer<T>
{
/// <summary>
/// Not yet documented.
/// </summary>
public abstract string ProviderID { get; }
/// <summary>
/// Not yet documented.
/// </summary>
/// <param name="pathStr">Not yet documented.</param>
/// <returns>Not yet documented.</returns>
public abstract T GetKeyFromPathString(string pathStr);
/// <summary>
/// Not yet documented.
/// </summary>
/// <param name="key">Not yet documented.</param>
/// <returns>Not yet documented.</returns>
public abstract string GetPathStringFromKey(T key);
/// <summary>
/// Not yet documented.
/// </summary>
/// <param name="x">Not yet documented.</param>
/// <param name="y">Not yet documented.</param>
/// <returns>Not yet documented.</returns>
public abstract int Compare(T x, T y);
int IDictionaryKeyPathProvider.Compare(object x, object y)
{
return this.Compare((T)x, (T)y);
}
object IDictionaryKeyPathProvider.GetKeyFromPathString(string pathStr)
{
return this.GetKeyFromPathString(pathStr);
}
string IDictionaryKeyPathProvider.GetPathStringFromKey(object key)
{
return this.GetPathStringFromKey((T)key);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 864fb1c011715f9df2998d71ac8716f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,467 @@
//-----------------------------------------------------------------------
// <copyright file="DictionaryKeyUtility.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System.Globalization;
using System;
using System.Collections.Generic;
using Utilities;
using System.Linq;
using UnityEngine;
using System.Reflection;
/// <summary>
/// Provides utility methods for handling dictionary keys in the prefab modification system.
/// </summary>
public static class DictionaryKeyUtility
{
private static readonly Dictionary<Type, bool> GetSupportedDictionaryKeyTypesResults = new Dictionary<Type, bool>();
private static readonly HashSet<Type> BaseSupportedDictionaryKeyTypes = new HashSet<Type>()
{
typeof(string),
typeof(char),
typeof(byte),
typeof(sbyte),
typeof(ushort),
typeof(short),
typeof(uint),
typeof(int),
typeof(ulong),
typeof(long),
typeof(float),
typeof(double),
typeof(decimal),
typeof(Guid)
};
private static readonly HashSet<char> AllowedSpecialKeyStrChars = new HashSet<char>()
{
',', '(', ')', '\\', '|', '-', '+'
};
private static readonly Dictionary<Type, IDictionaryKeyPathProvider> TypeToKeyPathProviders = new Dictionary<Type, IDictionaryKeyPathProvider>();
private static readonly Dictionary<string, IDictionaryKeyPathProvider> IDToKeyPathProviders = new Dictionary<string, IDictionaryKeyPathProvider>();
private static readonly Dictionary<IDictionaryKeyPathProvider, string> ProviderToID = new Dictionary<IDictionaryKeyPathProvider, string>();
private static readonly Dictionary<object, string> ObjectsToTempKeys = new Dictionary<object, string>();
private static readonly Dictionary<string, object> TempKeysToObjects = new Dictionary<string, object>();
private static long tempKeyCounter = 0;
private class UnityObjectKeyComparer<T> : IComparer<T>
{
public int Compare(T x, T y)
{
var a = (UnityEngine.Object)(object)x;
var b = (UnityEngine.Object)(object)y;
if (a == null && b == null) return 0;
if (a == null) return 1;
if (b == null) return -1;
return a.name.CompareTo(b.name);
}
}
private class FallbackKeyComparer<T> : IComparer<T>
{
public int Compare(T x, T y)
{
return GetDictionaryKeyString(x).CompareTo(GetDictionaryKeyString(y));
}
}
/// <summary>
/// A smart comparer for dictionary keys, that uses the most appropriate available comparison method for the given key types.
/// </summary>
public class KeyComparer<T> : IComparer<T>
{
public readonly static KeyComparer<T> Default = new KeyComparer<T>();
private readonly IComparer<T> actualComparer;
public KeyComparer()
{
IDictionaryKeyPathProvider provider;
if (TypeToKeyPathProviders.TryGetValue(typeof(T), out provider))
{
this.actualComparer = (IComparer<T>)provider;
}
else if (typeof(IComparable).IsAssignableFrom(typeof(T)) || typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
{
this.actualComparer = Comparer<T>.Default;
}
else if (typeof(UnityEngine.Object).IsAssignableFrom(typeof(T)))
{
this.actualComparer = new UnityObjectKeyComparer<T>();
}
else
{
this.actualComparer = new FallbackKeyComparer<T>();
}
}
/// <summary>
/// Not yet documented.
/// </summary>
/// <param name="x">Not yet documented.</param>
/// <param name="y">Not yet documented.</param>
/// <returns>Not yet documented.</returns>
public int Compare(T x, T y)
{
return this.actualComparer.Compare(x, y);
}
}
static DictionaryKeyUtility()
{
var attributes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(ass =>
{
return ass.SafeGetCustomAttributes(typeof(RegisterDictionaryKeyPathProviderAttribute), false)
.Select(attr => new { Assembly = ass, Attribute = (RegisterDictionaryKeyPathProviderAttribute)attr });
})
.Where(n => n.Attribute.ProviderType != null);
foreach (var entry in attributes)
{
var assembly = entry.Assembly;
var providerType = entry.Attribute.ProviderType;
if (providerType.IsAbstract)
{
LogInvalidKeyPathProvider(providerType, assembly, "Type cannot be abstract");
continue;
}
if (providerType.IsInterface)
{
LogInvalidKeyPathProvider(providerType, assembly, "Type cannot be an interface");
continue;
}
if (!providerType.ImplementsOpenGenericInterface(typeof(IDictionaryKeyPathProvider<>)))
{
LogInvalidKeyPathProvider(providerType, assembly, "Type must implement the " + typeof(IDictionaryKeyPathProvider<>).GetNiceName() + " interface");
continue;
}
if (providerType.IsGenericType)
{
LogInvalidKeyPathProvider(providerType, assembly, "Type cannot be generic");
continue;
}
if (providerType.GetConstructor(Type.EmptyTypes) == null)
{
LogInvalidKeyPathProvider(providerType, assembly, "Type must have a public parameterless constructor");
continue;
}
var keyType = providerType.GetArgumentsOfInheritedOpenGenericInterface(typeof(IDictionaryKeyPathProvider<>))[0];
if (!keyType.IsValueType)
{
LogInvalidKeyPathProvider(providerType, assembly, "Key type to support '" + keyType.GetNiceFullName() + "' must be a value type - support for extending dictionaries with reference type keys may come at a later time");
continue;
}
if (TypeToKeyPathProviders.ContainsKey(keyType))
{
Debug.LogWarning("Ignoring dictionary key path provider '" + providerType.GetNiceFullName() + "' registered on assembly '" + assembly.GetName().Name + "': A previous provider '" + TypeToKeyPathProviders[keyType].GetType().GetNiceFullName() + "' was already registered for the key type '" + keyType.GetNiceFullName() + "'.");
continue;
}
IDictionaryKeyPathProvider provider;
string id;
try
{
provider = (IDictionaryKeyPathProvider)Activator.CreateInstance(providerType);
}
catch (Exception ex)
{
Debug.LogException(ex);
Debug.LogWarning("Ignoring dictionary key path provider '" + providerType.GetNiceFullName() + "' registered on assembly '" + assembly.GetName().Name + "': An exception of type '" + ex.GetType() + "' was thrown when trying to instantiate a provider instance.");
continue;
}
try
{
id = provider.ProviderID;
}
catch (Exception ex)
{
Debug.LogException(ex);
Debug.LogWarning("Ignoring dictionary key path provider '" + providerType.GetNiceFullName() + "' registered on assembly '" + assembly.GetName().Name + "': An exception of type '" + ex.GetType() + "' was thrown when trying to get the provider ID string.");
continue;
}
if (id == null)
{
LogInvalidKeyPathProvider(providerType, assembly, "Provider ID is null");
continue;
}
if (id.Length == 0)
{
LogInvalidKeyPathProvider(providerType, assembly, "Provider ID is an empty string");
continue;
}
for (int i = 0; i < id.Length; i++)
{
if (!char.IsLetterOrDigit(id[i]))
{
LogInvalidKeyPathProvider(providerType, assembly, "Provider ID '" + id + "' cannot contain characters which are not letters or digits");
continue;
}
}
if (IDToKeyPathProviders.ContainsKey(id))
{
LogInvalidKeyPathProvider(providerType, assembly, "Provider ID '" + id + "' is already in use for the provider '" + IDToKeyPathProviders[id].GetType().GetNiceFullName() + "'");
continue;
}
TypeToKeyPathProviders[keyType] = provider;
IDToKeyPathProviders[id] = provider;
ProviderToID[provider] = id;
}
}
private static void LogInvalidKeyPathProvider(Type type, Assembly assembly, string reason)
{
Debug.LogError("Invalid dictionary key path provider '" + type.GetNiceFullName() + "' registered on assembly '" + assembly.GetName().Name + "': " + reason);
}
/// <summary>
/// Not yet documented.
/// </summary>
public static IEnumerable<Type> GetPersistentPathKeyTypes()
{
foreach (var type in BaseSupportedDictionaryKeyTypes)
{
yield return type;
}
foreach (var type in TypeToKeyPathProviders.Keys)
{
yield return type;
}
}
/// <summary>
/// Not yet documented.
/// </summary>
public static bool KeyTypeSupportsPersistentPaths(Type type)
{
bool result;
if (!GetSupportedDictionaryKeyTypesResults.TryGetValue(type, out result))
{
result = PrivateIsSupportedDictionaryKeyType(type);
GetSupportedDictionaryKeyTypesResults.Add(type, result);
}
return result;
}
private static bool PrivateIsSupportedDictionaryKeyType(Type type)
{
return type.IsEnum || BaseSupportedDictionaryKeyTypes.Contains(type) || TypeToKeyPathProviders.ContainsKey(type);
}
/// <summary>
/// Not yet documented.
/// </summary>
public static string GetDictionaryKeyString(object key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
Type type = key.GetType();
if (!KeyTypeSupportsPersistentPaths(type))
{
string keyString;
if (!ObjectsToTempKeys.TryGetValue(key, out keyString))
{
keyString = (tempKeyCounter++).ToString();
var str = "{temp:" + keyString + "}";
ObjectsToTempKeys[key] = str;
TempKeysToObjects[str] = key;
}
return keyString;
}
IDictionaryKeyPathProvider keyPathProvider;
if (TypeToKeyPathProviders.TryGetValue(type, out keyPathProvider))
{
var keyStr = keyPathProvider.GetPathStringFromKey(key);
string error = null;
bool validPath = true;
if (keyStr == null || keyStr.Length == 0)
{
validPath = false;
error = "String is null or empty";
}
if (validPath)
{
for (int i = 0; i < keyStr.Length; i++)
{
var c = keyStr[i];
if (char.IsLetterOrDigit(c) || AllowedSpecialKeyStrChars.Contains(c)) continue;
validPath = false;
error = "Invalid character '" + c + "' at index " + i;
break;
}
}
if (!validPath)
{
throw new ArgumentException("Invalid key path '" + keyStr + "' given by provider '" + keyPathProvider.GetType().GetNiceFullName() + "': " + error);
}
return "{id:" + ProviderToID[keyPathProvider] + ":" + keyStr + "}";
}
if (type.IsEnum)
{
Type backingType = Enum.GetUnderlyingType(type);
if (backingType == typeof(ulong))
{
ulong value = Convert.ToUInt64(key);
return "{" + value.ToString("D", CultureInfo.InvariantCulture) + "eu}";
}
else
{
long value = Convert.ToInt64(key);
return "{" + value.ToString("D", CultureInfo.InvariantCulture) + "es}";
}
}
if (type == typeof(string)) return "{\"" + key + "\"}";
if (type == typeof(char)) return "{'" + ((char)key).ToString(CultureInfo.InvariantCulture) + "'}";
if (type == typeof(byte)) return "{" + ((byte)key).ToString("D", CultureInfo.InvariantCulture) + "ub}";
if (type == typeof(sbyte)) return "{" + ((sbyte)key).ToString("D", CultureInfo.InvariantCulture) + "sb}";
if (type == typeof(ushort)) return "{" + ((ushort)key).ToString("D", CultureInfo.InvariantCulture) + "us}";
if (type == typeof(short)) return "{" + ((short)key).ToString("D", CultureInfo.InvariantCulture) + "ss}";
if (type == typeof(uint)) return "{" + ((uint)key).ToString("D", CultureInfo.InvariantCulture) + "ui}";
if (type == typeof(int)) return "{" + ((int)key).ToString("D", CultureInfo.InvariantCulture) + "si}";
if (type == typeof(ulong)) return "{" + ((ulong)key).ToString("D", CultureInfo.InvariantCulture) + "ul}";
if (type == typeof(long)) return "{" + ((long)key).ToString("D", CultureInfo.InvariantCulture) + "sl}";
if (type == typeof(float)) return "{" + ((float)key).ToString("R", CultureInfo.InvariantCulture) + "fl}";
if (type == typeof(double)) return "{" + ((double)key).ToString("R", CultureInfo.InvariantCulture) + "dl}";
if (type == typeof(decimal)) return "{" + ((decimal)key).ToString("G", CultureInfo.InvariantCulture) + "dc}";
if (type == typeof(Guid)) return "{" + ((Guid)key).ToString("N", CultureInfo.InvariantCulture) + "gu}";
throw new NotImplementedException("Support has not been implemented for the supported dictionary key type '" + type.GetNiceName() + "'.");
}
/// <summary>
/// Not yet documented.
/// </summary>
public static object GetDictionaryKeyValue(string keyStr, Type expectedType)
{
const string InvalidKeyString = "Invalid key string: ";
if (keyStr == null) throw new ArgumentNullException("keyStr");
if (keyStr.Length < 4 || keyStr[0] != '{' || keyStr[keyStr.Length - 1] != '}') throw new ArgumentException(InvalidKeyString + keyStr);
if (keyStr[1] == '"')
{
if (keyStr[keyStr.Length - 2] != '"') throw new ArgumentException(InvalidKeyString + keyStr);
return keyStr.Substring(2, keyStr.Length - 4);
}
if (keyStr[1] == '\'')
{
if (keyStr.Length != 5 || keyStr[keyStr.Length - 2] != '\'') throw new ArgumentException(InvalidKeyString + keyStr);
return keyStr[2];
}
if (keyStr.StartsWith("{temp:"))
{
object key;
if (!TempKeysToObjects.TryGetValue(keyStr, out key))
{
throw new ArgumentException("The temp dictionary key '" + keyStr + "' has not been allocated yet.");
}
return key;
}
if (keyStr.StartsWith("{id:"))
{
int secondColon = keyStr.IndexOf(':', 4);
if (secondColon == -1 || secondColon > keyStr.Length - 3) throw new ArgumentException(InvalidKeyString + keyStr);
string id = keyStr.FromTo(4, secondColon);
string key = keyStr.FromTo(secondColon + 1, keyStr.Length - 1);
IDictionaryKeyPathProvider provider;
if (!IDToKeyPathProviders.TryGetValue(id, out provider))
{
throw new ArgumentException("No provider found for provider ID '" + id + "' in key string '" + keyStr + "'.");
}
return provider.GetKeyFromPathString(key);
}
// Handle enums
if (keyStr.EndsWith("ub}")) return byte.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("sb}")) return sbyte.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("us}")) return ushort.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("ss}")) return short.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("ui}")) return uint.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("si}")) return int.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("ul}")) return ulong.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("sl}")) return long.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("fl}")) return float.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("dl}")) return double.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("dc}")) return decimal.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any);
if (keyStr.EndsWith("gu}")) return new Guid(keyStr.Substring(1, keyStr.Length - 4));
if (keyStr.EndsWith("es}")) return Enum.ToObject(expectedType, long.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any));
if (keyStr.EndsWith("eu}")) return Enum.ToObject(expectedType, ulong.Parse(keyStr.Substring(1, keyStr.Length - 4), NumberStyles.Any));
throw new ArgumentException(InvalidKeyString + keyStr);
}
private static string FromTo(this string str, int from, int to)
{
return str.Substring(from, to - from);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ef6f699f176c2dfdea788982526f989a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,75 @@
//-----------------------------------------------------------------------
// <copyright file="IDictionaryKeyPathProvider.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Not yet documented.
/// </summary>
public interface IDictionaryKeyPathProvider
{
/// <summary>
/// Gets the provider identifier.
/// </summary>
string ProviderID { get; }
/// <summary>
/// Gets the path string from key.
/// </summary>
/// <param name="key">The key.</param>
string GetPathStringFromKey(object key);
/// <summary>
/// Gets the key from path string.
/// </summary>
/// <param name="pathStr">The path string.</param>
object GetKeyFromPathString(string pathStr);
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
int Compare(object x, object y);
}
/// <summary>
/// Not yet documented.
/// </summary>
public interface IDictionaryKeyPathProvider<T> : IDictionaryKeyPathProvider
{
/// <summary>
/// Gets the path string from key.
/// </summary>
/// <param name="key">The key.</param>
string GetPathStringFromKey(T key);
/// <summary>
/// Gets the key from path string.
/// </summary>
/// <param name="pathStr">The path string.</param>
new T GetKeyFromPathString(string pathStr);
/// <summary>
/// Compares the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
int Compare(T x, T y);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b513c156933d8b833ccd40d717bf7e2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
//-----------------------------------------------------------------------
// <copyright file="RegisterDictionaryKeyPathProviderAttribute.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class RegisterDictionaryKeyPathProviderAttribute : Attribute
{
public readonly Type ProviderType;
public RegisterDictionaryKeyPathProviderAttribute(Type providerType)
{
this.ProviderType = providerType;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 54f653ed4a4e15c07057283c11dce4d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,76 @@
//-----------------------------------------------------------------------
// <copyright file="Vector2DictionaryKeyPathProvider.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterDictionaryKeyPathProvider(typeof(Vector2DictionaryKeyPathProvider))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System.Globalization;
using UnityEngine;
/// <summary>
/// Not yet documented.
/// </summary>
public sealed class Vector2DictionaryKeyPathProvider : BaseDictionaryKeyPathProvider<Vector2>
{
/// <summary>
/// Not yet documented.
/// </summary>
public override string ProviderID { get { return "v2"; } }
/// <summary>
/// Not yet documented.
/// </summary>
public override int Compare(Vector2 x, Vector2 y)
{
int result = x.x.CompareTo(y.x);
if (result == 0)
{
result = x.y.CompareTo(y.y);
}
return result;
}
/// <summary>
/// Not yet documented.
/// </summary>
public override Vector2 GetKeyFromPathString(string pathStr)
{
int sep = pathStr.IndexOf('|');
string x = pathStr.Substring(1, sep - 1).Trim();
string y = pathStr.Substring(sep + 1, pathStr.Length - (sep + 2)).Trim();
return new Vector2(float.Parse(x), float.Parse(y));
}
/// <summary>
/// Not yet documented.
/// </summary>
public override string GetPathStringFromKey(Vector2 key)
{
var x = key.x.ToString("R", CultureInfo.InvariantCulture);
var y = key.y.ToString("R", CultureInfo.InvariantCulture);
return ("(" + x + "|" + y + ")").Replace('.', ',');
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0405ef103432161dff609e75f71f3f55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,72 @@
//-----------------------------------------------------------------------
// <copyright file="Vector3DictionaryKeyPathProvider.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterDictionaryKeyPathProvider(typeof(Vector3DictionaryKeyPathProvider))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System.Globalization;
using UnityEngine;
/// <summary>
/// Dictionary key path provider for <see cref="UnityEngine.Vector3"/>
/// </summary>
public sealed class Vector3DictionaryKeyPathProvider : BaseDictionaryKeyPathProvider<Vector3>
{
public override string ProviderID { get { return "v3"; } }
public override int Compare(Vector3 x, Vector3 y)
{
int result = x.x.CompareTo(y.x);
if (result == 0)
{
result = x.y.CompareTo(y.y);
}
if (result == 0)
{
result = x.z.CompareTo(y.z);
}
return result;
}
public override Vector3 GetKeyFromPathString(string pathStr)
{
int sep1 = pathStr.IndexOf('|');
int sep2 = pathStr.IndexOf('|', sep1 + 1);
string x = pathStr.Substring(1, sep1 - 1).Trim();
string y = pathStr.Substring(sep1 + 1, sep2 - (sep1 + 1)).Trim();
string z = pathStr.Substring(sep2 + 1, pathStr.Length - (sep2 + 2)).Trim();
return new Vector3(float.Parse(x), float.Parse(y), float.Parse(z));
}
public override string GetPathStringFromKey(Vector3 key)
{
var x = key.x.ToString("R", CultureInfo.InvariantCulture);
var y = key.y.ToString("R", CultureInfo.InvariantCulture);
var z = key.z.ToString("R", CultureInfo.InvariantCulture);
return ("(" + x + "|" + y + "|" + z + ")").Replace('.', ',');
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d61e235c606c1c9d7269f7e68471e38
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,78 @@
//-----------------------------------------------------------------------
// <copyright file="Vector4DictionaryKeyPathProvider.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterDictionaryKeyPathProvider(typeof(Vector4DictionaryKeyPathProvider))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System.Globalization;
using UnityEngine;
public sealed class Vector4DictionaryKeyPathProvider : BaseDictionaryKeyPathProvider<Vector4>
{
public override string ProviderID { get { return "v4"; } }
public override int Compare(Vector4 x, Vector4 y)
{
int result = x.x.CompareTo(y.x);
if (result == 0)
{
result = x.y.CompareTo(y.y);
}
if (result == 0)
{
result = x.z.CompareTo(y.z);
}
if (result == 0)
{
result = x.w.CompareTo(y.w);
}
return result;
}
public override Vector4 GetKeyFromPathString(string pathStr)
{
int sep1 = pathStr.IndexOf('|');
int sep2 = pathStr.IndexOf('|', sep1 + 1);
int sep3 = pathStr.IndexOf('|', sep2 + 1);
string x = pathStr.Substring(1, sep1 - 1).Trim();
string y = pathStr.Substring(sep1 + 1, sep2 - (sep1 + 1)).Trim();
string z = pathStr.Substring(sep2 + 1, sep3 - (sep2 + 1)).Trim();
string w = pathStr.Substring(sep3 + 1, pathStr.Length - (sep3 + 2)).Trim();
return new Vector4(float.Parse(x), float.Parse(y), float.Parse(z), float.Parse(w));
}
public override string GetPathStringFromKey(Vector4 key)
{
var x = key.x.ToString("R", CultureInfo.InvariantCulture);
var y = key.y.ToString("R", CultureInfo.InvariantCulture);
var z = key.z.ToString("R", CultureInfo.InvariantCulture);
var w = key.w.ToString("R", CultureInfo.InvariantCulture);
return ("(" + x + "|" + y + "|" + z + "|" + w + ")").Replace('.', ',');
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 51bb2cf369b5ea90948a20e4f2ebae48
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a7dcf20a0423fd046ad1bd854676dc1c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,73 @@
//-----------------------------------------------------------------------
// <copyright file="AnimationCurveFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(AnimationCurveFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="AnimationCurve"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.AnimationCurve}" />
public class AnimationCurveFormatter : MinimalBaseFormatter<AnimationCurve>
{
private static readonly Serializer<Keyframe[]> KeyframeSerializer = Serializer.Get<Keyframe[]>();
private static readonly Serializer<WrapMode> WrapModeSerializer = Serializer.Get<WrapMode>();
/// <summary>
/// Returns null.
/// </summary>
/// <returns>
/// A null value.
/// </returns>
protected override AnimationCurve GetUninitializedObject()
{
return null;
}
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref AnimationCurve value, IDataReader reader)
{
var keys = KeyframeSerializer.ReadValue(reader);
value = new AnimationCurve(keys);
value.preWrapMode = WrapModeSerializer.ReadValue(reader);
value.postWrapMode = WrapModeSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref AnimationCurve value, IDataWriter writer)
{
KeyframeSerializer.WriteValue(value.keys, writer);
WrapModeSerializer.WriteValue(value.preWrapMode, writer);
WrapModeSerializer.WriteValue(value.postWrapMode, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d2976bd61cccf62b11b4d3f02762465
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,57 @@
//-----------------------------------------------------------------------
// <copyright file="BoundsFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(BoundsFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Bounds"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Bounds}" />
public class BoundsFormatter : MinimalBaseFormatter<Bounds>
{
private static readonly Serializer<Vector3> Vector3Serializer = Serializer.Get<Vector3>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Bounds value, IDataReader reader)
{
value.center = Vector3Serializer.ReadValue(reader);
value.size = Vector3Serializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Bounds value, IDataWriter writer)
{
Vector3Serializer.WriteValue(value.center, writer);
Vector3Serializer.WriteValue(value.size, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ff1b29d64402a15d020739becd8661e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------
// <copyright file="Color32Formatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(Color32Formatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Color32"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Color32}" />
public class Color32Formatter : MinimalBaseFormatter<Color32>
{
private static readonly Serializer<byte> ByteSerializer = Serializer.Get<byte>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Color32 value, IDataReader reader)
{
value.r = Color32Formatter.ByteSerializer.ReadValue(reader);
value.g = Color32Formatter.ByteSerializer.ReadValue(reader);
value.b = Color32Formatter.ByteSerializer.ReadValue(reader);
value.a = Color32Formatter.ByteSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Color32 value, IDataWriter writer)
{
Color32Formatter.ByteSerializer.WriteValue(value.r, writer);
Color32Formatter.ByteSerializer.WriteValue(value.g, writer);
Color32Formatter.ByteSerializer.WriteValue(value.b, writer);
Color32Formatter.ByteSerializer.WriteValue(value.a, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0878ec68b6ab3c9ebc365b6d139e4840
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,161 @@
//-----------------------------------------------------------------------
// <copyright file="ColorBlockFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatterLocator(typeof(ColorBlockFormatterLocator))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using System.Reflection;
using UnityEngine;
public class ColorBlockFormatterLocator : IFormatterLocator
{
#if false
public bool TryGetFormatter(Type type, FormatterLocationStep step, ISerializationPolicy policy, bool allowWeakFallbackFormatters, out IFormatter formatter)
#else
public bool TryGetFormatter(Type type, FormatterLocationStep step, ISerializationPolicy policy, out IFormatter formatter)
#endif
{
if (step == FormatterLocationStep.BeforeRegisteredFormatters && type.FullName == "UnityEngine.UI.ColorBlock")
{
#if false
try
{
formatter = (IFormatter)Activator.CreateInstance(typeof(ColorBlockFormatter<>).MakeGenericType(type));
}
catch (Exception ex)
{
#pragma warning disable CS0618 // Type or member is obsolete
if (allowWeakFallbackFormatters && (ex is ExecutionEngineException || ex.GetBaseException() is ExecutionEngineException))
#pragma warning restore CS0618 // Type or member is obsolete
{
formatter = new WeakColorBlockFormatter(type);
}
else throw;
}
#else
formatter = (IFormatter)Activator.CreateInstance(typeof(ColorBlockFormatter<>).MakeGenericType(type));
#endif
return true;
}
formatter = null;
return false;
}
}
/// <summary>
/// Custom formatter for the <see cref="ColorBlock"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.UI.ColorBlock}" />
public class ColorBlockFormatter<T> : MinimalBaseFormatter<T>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
private static readonly Serializer<Color> ColorSerializer = Serializer.Get<Color>();
private static readonly PropertyInfo normalColor = typeof(T).GetProperty("normalColor");
private static readonly PropertyInfo highlightedColor = typeof(T).GetProperty("highlightedColor");
private static readonly PropertyInfo pressedColor = typeof(T).GetProperty("pressedColor");
private static readonly PropertyInfo disabledColor = typeof(T).GetProperty("disabledColor");
private static readonly PropertyInfo colorMultiplier = typeof(T).GetProperty("colorMultiplier");
private static readonly PropertyInfo fadeDuration = typeof(T).GetProperty("fadeDuration");
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref T value, IDataReader reader)
{
object boxed = value;
normalColor.SetValue(boxed, ColorSerializer.ReadValue(reader), null);
highlightedColor.SetValue(boxed, ColorSerializer.ReadValue(reader), null);
pressedColor.SetValue(boxed, ColorSerializer.ReadValue(reader), null);
disabledColor.SetValue(boxed, ColorSerializer.ReadValue(reader), null);
colorMultiplier.SetValue(boxed, FloatSerializer.ReadValue(reader), null);
fadeDuration.SetValue(boxed, FloatSerializer.ReadValue(reader), null);
value = (T)boxed;
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref T value, IDataWriter writer)
{
ColorSerializer.WriteValue((Color)normalColor.GetValue(value, null), writer);
ColorSerializer.WriteValue((Color)highlightedColor.GetValue(value, null), writer);
ColorSerializer.WriteValue((Color)pressedColor.GetValue(value, null), writer);
ColorSerializer.WriteValue((Color)disabledColor.GetValue(value, null), writer);
FloatSerializer.WriteValue((float)colorMultiplier.GetValue(value, null), writer);
FloatSerializer.WriteValue((float)fadeDuration.GetValue(value, null), writer);
}
}
#if false
public class WeakColorBlockFormatter : WeakBaseFormatter
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
private static readonly Serializer<Color> ColorSerializer = Serializer.Get<Color>();
private readonly PropertyInfo normalColor;
private readonly PropertyInfo highlightedColor;
private readonly PropertyInfo pressedColor;
private readonly PropertyInfo disabledColor;
private readonly PropertyInfo colorMultiplier;
private readonly PropertyInfo fadeDuration;
public WeakColorBlockFormatter(Type colorBlockType)
: base(colorBlockType)
{
normalColor = colorBlockType.GetProperty("normalColor");
highlightedColor = colorBlockType.GetProperty("highlightedColor");
pressedColor = colorBlockType.GetProperty("pressedColor");
disabledColor = colorBlockType.GetProperty("disabledColor");
colorMultiplier = colorBlockType.GetProperty("colorMultiplier");
fadeDuration = colorBlockType.GetProperty("fadeDuration");
}
protected override void DeserializeImplementation(ref object value, IDataReader reader)
{
normalColor.SetValue(value, ColorSerializer.ReadValue(reader), null);
highlightedColor.SetValue(value, ColorSerializer.ReadValue(reader), null);
pressedColor.SetValue(value, ColorSerializer.ReadValue(reader), null);
disabledColor.SetValue(value, ColorSerializer.ReadValue(reader), null);
colorMultiplier.SetValue(value, FloatSerializer.ReadValue(reader), null);
fadeDuration.SetValue(value, FloatSerializer.ReadValue(reader), null);
}
protected override void SerializeImplementation(ref object value, IDataWriter writer)
{
ColorSerializer.WriteValue((Color)normalColor.GetValue(value, null), writer);
ColorSerializer.WriteValue((Color)highlightedColor.GetValue(value, null), writer);
ColorSerializer.WriteValue((Color)pressedColor.GetValue(value, null), writer);
ColorSerializer.WriteValue((Color)disabledColor.GetValue(value, null), writer);
FloatSerializer.WriteValue((float)colorMultiplier.GetValue(value, null), writer);
FloatSerializer.WriteValue((float)fadeDuration.GetValue(value, null), writer);
}
}
#endif
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25e35581ce6d1febd9ac41864a76ecdb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------
// <copyright file="ColorFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(ColorFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Color"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Color}" />
public class ColorFormatter : MinimalBaseFormatter<Color>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Color value, IDataReader reader)
{
value.r = ColorFormatter.FloatSerializer.ReadValue(reader);
value.g = ColorFormatter.FloatSerializer.ReadValue(reader);
value.b = ColorFormatter.FloatSerializer.ReadValue(reader);
value.a = ColorFormatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Color value, IDataWriter writer)
{
ColorFormatter.FloatSerializer.WriteValue(value.r, writer);
ColorFormatter.FloatSerializer.WriteValue(value.g, writer);
ColorFormatter.FloatSerializer.WriteValue(value.b, writer);
ColorFormatter.FloatSerializer.WriteValue(value.a, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 484768ba343a6a05522c29d81a4ce61d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,81 @@
//-----------------------------------------------------------------------
// <copyright file="CoroutineFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(CoroutineFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using UnityEngine;
/// <summary>
/// <para>
/// Custom formatter for the <see cref="Coroutine"/> type.
/// This serializes nothing and always deserializes null,
/// and only exists to ensure that no coroutine instances
/// are ever created by the serialization system, since they
/// will in almost all cases be invalid instances.
/// </para>
/// <para>
/// Invalid coroutine instances crash Unity instantly when
/// they are garbage collected.
/// </para>
/// </summary>
public sealed class CoroutineFormatter : IFormatter<Coroutine>
{
/// <summary>
/// Gets the type that the formatter can serialize.
/// </summary>
/// <value>
/// The type that the formatter can serialize.
/// </value>
public Type SerializedType { get { return typeof(Coroutine); } }
/// <summary>
/// Returns null.
/// </summary>
object IFormatter.Deserialize(IDataReader reader)
{
return null;
}
/// <summary>
/// Returns null.
/// </summary>
public Coroutine Deserialize(IDataReader reader)
{
return null;
}
/// <summary>
/// Does nothing.
/// </summary>
public void Serialize(object value, IDataWriter writer)
{
}
/// <summary>
/// Does nothing.
/// </summary>
public void Serialize(Coroutine value, IDataWriter writer)
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3968bef792c5668478ac01be7645b30
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,57 @@
//-----------------------------------------------------------------------
// <copyright file="GradientAlphaKeyFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(GradientAlphaKeyFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="GradientAlphaKey"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.GradientAlphaKey}" />
public class GradientAlphaKeyFormatter : MinimalBaseFormatter<GradientAlphaKey>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref GradientAlphaKey value, IDataReader reader)
{
value.alpha = GradientAlphaKeyFormatter.FloatSerializer.ReadValue(reader);
value.time = GradientAlphaKeyFormatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref GradientAlphaKey value, IDataWriter writer)
{
GradientAlphaKeyFormatter.FloatSerializer.WriteValue(value.alpha, writer);
GradientAlphaKeyFormatter.FloatSerializer.WriteValue(value.time, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5b415c00da8157ac50b8f5543f0b1d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,58 @@
//-----------------------------------------------------------------------
// <copyright file="GradientColorKeyFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(GradientColorKeyFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="GradientColorKey"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.GradientColorKey}" />
public class GradientColorKeyFormatter : MinimalBaseFormatter<GradientColorKey>
{
private static readonly Serializer<Color> ColorSerializer = Serializer.Get<Color>();
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref GradientColorKey value, IDataReader reader)
{
value.color = GradientColorKeyFormatter.ColorSerializer.ReadValue(reader);
value.time = GradientColorKeyFormatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref GradientColorKey value, IDataWriter writer)
{
GradientColorKeyFormatter.ColorSerializer.WriteValue(value.color, writer);
GradientColorKeyFormatter.FloatSerializer.WriteValue(value.time, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8936a3e43078251682f18923139f7aee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,106 @@
//-----------------------------------------------------------------------
// <copyright file="GradientFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(GradientFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using System.Reflection;
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Gradient"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Gradient}" />
public class GradientFormatter : MinimalBaseFormatter<Gradient>
{
private static readonly Serializer<GradientAlphaKey[]> AlphaKeysSerializer = Serializer.Get<GradientAlphaKey[]>();
private static readonly Serializer<GradientColorKey[]> ColorKeysSerializer = Serializer.Get<GradientColorKey[]>();
// The Gradient.mode member of type UnityEngine.GradientMode was added in a later version of Unity
// Therefore we need to handle it using reflection, as it might not be there if Odin is running in an early version
private static readonly PropertyInfo ModeProperty = typeof(Gradient).GetProperty("mode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
private static readonly Serializer<object> EnumSerializer = ModeProperty != null ? Serializer.Get<object>() : null;
protected override Gradient GetUninitializedObject()
{
return new Gradient();
}
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Gradient value, IDataReader reader)
{
value.alphaKeys = GradientFormatter.AlphaKeysSerializer.ReadValue(reader);
value.colorKeys = GradientFormatter.ColorKeysSerializer.ReadValue(reader);
string name;
reader.PeekEntry(out name);
if (name == "mode")
{
try
{
if (ModeProperty != null)
{
ModeProperty.SetValue(value, EnumSerializer.ReadValue(reader), null);
}
else
{
reader.SkipEntry();
}
}
catch (Exception)
{
reader.Context.Config.DebugContext.LogWarning("Failed to read Gradient.mode, due to Unity's API disallowing setting of this member on other threads than the main thread. Gradient.mode value will have been lost.");
}
}
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Gradient value, IDataWriter writer)
{
GradientFormatter.AlphaKeysSerializer.WriteValue(value.alphaKeys, writer);
GradientFormatter.ColorKeysSerializer.WriteValue(value.colorKeys, writer);
if (ModeProperty != null)
{
try
{
EnumSerializer.WriteValue("mode", ModeProperty.GetValue(value, null), writer);
}
catch (Exception)
{
writer.Context.Config.DebugContext.LogWarning("Failed to write Gradient.mode, due to Unity's API disallowing setting of this member on other threads than the main thread. Gradient.mode will have been lost upon deserialization.");
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d5b54660d5342fd45e2e43775538879d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,121 @@
//-----------------------------------------------------------------------
// <copyright file="KeyframeFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(KeyframeFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using VRC.Udon.Serialization.OdinSerializer.Utilities;
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Keyframe"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Keyframe}" />
public class KeyframeFormatter : MinimalBaseFormatter<Keyframe>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
private static readonly Serializer<int> IntSerializer = Serializer.Get<int>();
private static readonly bool Is_In_2018_1_Or_Above;
private static IFormatter<Keyframe> Formatter;
static KeyframeFormatter()
{
Is_In_2018_1_Or_Above = typeof(Keyframe).GetProperty("weightedMode") != null;
if (Is_In_2018_1_Or_Above)
{
if (EmitUtilities.CanEmit)
{
Formatter = (IFormatter<Keyframe>)FormatterEmitter.GetEmittedFormatter(typeof(Keyframe), SerializationPolicies.Everything);
}
else
{
Formatter = new ReflectionFormatter<Keyframe>(SerializationPolicies.Everything);
}
}
}
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Keyframe value, IDataReader reader)
{
string name;
EntryType first = reader.PeekEntry(out name);
if (first == EntryType.Integer && name == "ver")
{
if (Formatter == null)
{
// We're deserializing 2018.1+ data in a lower version of Unity - so just give it a go
Formatter = new ReflectionFormatter<Keyframe>(SerializationPolicies.Everything);
}
int version;
reader.ReadInt32(out version);
// Only one version so far, so ignore it for now
value = Formatter.Deserialize(reader);
}
else
{
// Legacy Keyframe deserialization code
value.inTangent = KeyframeFormatter.FloatSerializer.ReadValue(reader);
value.outTangent = KeyframeFormatter.FloatSerializer.ReadValue(reader);
value.time = KeyframeFormatter.FloatSerializer.ReadValue(reader);
value.value = KeyframeFormatter.FloatSerializer.ReadValue(reader);
#pragma warning disable 0618
value.tangentMode = KeyframeFormatter.IntSerializer.ReadValue(reader);
#pragma warning restore 0618
}
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Keyframe value, IDataWriter writer)
{
if (Is_In_2018_1_Or_Above)
{
writer.WriteInt32("ver", 1);
Formatter.Serialize(value, writer);
}
else
{
// Legacy Keyframe serialization code
KeyframeFormatter.FloatSerializer.WriteValue(value.inTangent, writer);
KeyframeFormatter.FloatSerializer.WriteValue(value.outTangent, writer);
KeyframeFormatter.FloatSerializer.WriteValue(value.time, writer);
KeyframeFormatter.FloatSerializer.WriteValue(value.value, writer);
#pragma warning disable 0618
KeyframeFormatter.IntSerializer.WriteValue(value.tangentMode, writer);
#pragma warning restore 0618
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68ac0b27f571616d3ed26c23eef40c8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,55 @@
//-----------------------------------------------------------------------
// <copyright file="LayerMaskFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(LayerMaskFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="LayerMask"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.LayerMask}" />
public class LayerMaskFormatter : MinimalBaseFormatter<LayerMask>
{
private static readonly Serializer<int> IntSerializer = Serializer.Get<int>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref LayerMask value, IDataReader reader)
{
value.value = LayerMaskFormatter.IntSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref LayerMask value, IDataWriter writer)
{
LayerMaskFormatter.IntSerializer.WriteValue(value.value, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: afc596cd95a1ac316024d16f6fec6536
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------
// <copyright file="QuaternionFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(QuaternionFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Quaternion"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Quaternion}" />
public class QuaternionFormatter : MinimalBaseFormatter<Quaternion>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Quaternion value, IDataReader reader)
{
value.x = QuaternionFormatter.FloatSerializer.ReadValue(reader);
value.y = QuaternionFormatter.FloatSerializer.ReadValue(reader);
value.z = QuaternionFormatter.FloatSerializer.ReadValue(reader);
value.w = QuaternionFormatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Quaternion value, IDataWriter writer)
{
QuaternionFormatter.FloatSerializer.WriteValue(value.x, writer);
QuaternionFormatter.FloatSerializer.WriteValue(value.y, writer);
QuaternionFormatter.FloatSerializer.WriteValue(value.z, writer);
QuaternionFormatter.FloatSerializer.WriteValue(value.w, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 558323987bf9b75943382a5faa093ee3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------
// <copyright file="RectFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(RectFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Rect"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Rect}" />
public class RectFormatter : MinimalBaseFormatter<Rect>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Rect value, IDataReader reader)
{
value.x = RectFormatter.FloatSerializer.ReadValue(reader);
value.y = RectFormatter.FloatSerializer.ReadValue(reader);
value.width = RectFormatter.FloatSerializer.ReadValue(reader);
value.height = RectFormatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Rect value, IDataWriter writer)
{
RectFormatter.FloatSerializer.WriteValue(value.x, writer);
RectFormatter.FloatSerializer.WriteValue(value.y, writer);
RectFormatter.FloatSerializer.WriteValue(value.width, writer);
RectFormatter.FloatSerializer.WriteValue(value.height, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 196809b991e565a48e3d4ad08cb30b5e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
//VRC TCL: Disabled for security
//-----------------------------------------------------------------------
// <copyright file="UnityEventFormatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
#if false
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(UnityEventFormatter<>), weakFallback: typeof(WeakUnityEventFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using UnityEngine.Events;
/// <summary>
/// Custom generic formatter for the <see cref="UnityEvent{T0}"/>, <see cref="UnityEvent{T0, T1}"/>, <see cref="UnityEvent{T0, T1, T2}"/> and <see cref="UnityEvent{T0, T1, T2, T3}"/> types.
/// </summary>
/// <typeparam name="T">The type of UnityEvent that this formatter can serialize and deserialize.</typeparam>
/// <seealso cref="ReflectionFormatter{UnityEngine.Events.UnityEvent}" />
public class UnityEventFormatter<T> : ReflectionFormatter<T> where T : UnityEventBase, new()
{
/// <summary>
/// Get an uninitialized object of type <see cref="T" />.
/// </summary>
/// <returns>
/// An uninitialized object of type <see cref="T" />.
/// </returns>
protected override T GetUninitializedObject()
{
return new T();
}
}
public class WeakUnityEventFormatter : WeakReflectionFormatter
{
public WeakUnityEventFormatter(Type serializedType) : base(serializedType)
{
}
protected override object GetUninitializedObject()
{
return Activator.CreateInstance(this.SerializedType);
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c934302874ac3315ed322feefefa1f9c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,57 @@
//-----------------------------------------------------------------------
// <copyright file="Vector2Formatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(Vector2Formatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Vector2"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Vector2}" />
public class Vector2Formatter : MinimalBaseFormatter<Vector2>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Vector2 value, IDataReader reader)
{
value.x = Vector2Formatter.FloatSerializer.ReadValue(reader);
value.y = Vector2Formatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Vector2 value, IDataWriter writer)
{
Vector2Formatter.FloatSerializer.WriteValue(value.x, writer);
Vector2Formatter.FloatSerializer.WriteValue(value.y, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 70c675a7b4c71c685ee39d745ccb058b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,59 @@
//-----------------------------------------------------------------------
// <copyright file="Vector3Formatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(Vector3Formatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Vector3"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Vector3}" />
public class Vector3Formatter : MinimalBaseFormatter<Vector3>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Vector3 value, IDataReader reader)
{
value.x = Vector3Formatter.FloatSerializer.ReadValue(reader);
value.y = Vector3Formatter.FloatSerializer.ReadValue(reader);
value.z = Vector3Formatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Vector3 value, IDataWriter writer)
{
Vector3Formatter.FloatSerializer.WriteValue(value.x, writer);
Vector3Formatter.FloatSerializer.WriteValue(value.y, writer);
Vector3Formatter.FloatSerializer.WriteValue(value.z, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da2644647af1368176103aa87de1dbaf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
//-----------------------------------------------------------------------
// <copyright file="Vector4Formatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(Vector4Formatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Vector4"/> type.
/// </summary>
/// <seealso cref="MinimalBaseFormatter{UnityEngine.Vector4}" />
public class Vector4Formatter : MinimalBaseFormatter<Vector4>
{
private static readonly Serializer<float> FloatSerializer = Serializer.Get<float>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Vector4 value, IDataReader reader)
{
value.x = Vector4Formatter.FloatSerializer.ReadValue(reader);
value.y = Vector4Formatter.FloatSerializer.ReadValue(reader);
value.z = Vector4Formatter.FloatSerializer.ReadValue(reader);
value.w = Vector4Formatter.FloatSerializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Vector4 value, IDataWriter writer)
{
Vector4Formatter.FloatSerializer.WriteValue(value.x, writer);
Vector4Formatter.FloatSerializer.WriteValue(value.y, writer);
Vector4Formatter.FloatSerializer.WriteValue(value.z, writer);
Vector4Formatter.FloatSerializer.WriteValue(value.w, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 60afa8ede3981c383782a01ddc55e943
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,91 @@
//-----------------------------------------------------------------------
// <copyright file="Vector4Formatter.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
using VRC.Udon.Serialization.OdinSerializer;
[assembly: RegisterFormatter(typeof(Vector2IntFormatter))]
[assembly: RegisterFormatter(typeof(Vector3IntFormatter))]
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Custom formatter for the <see cref="Vector2Int"/> type.
/// </summary>
/// <seealso cref="Sirenix.Serialization.MinimalBaseFormatter{UnityEngine.Vector2Int}" />
public class Vector2IntFormatter : MinimalBaseFormatter<Vector2Int>
{
private static readonly Serializer<int> Serializer = OdinSerializer.Serializer.Get<int>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Vector2Int value, IDataReader reader)
{
value.x = Vector2IntFormatter.Serializer.ReadValue(reader);
value.y = Vector2IntFormatter.Serializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Vector2Int value, IDataWriter writer)
{
Vector2IntFormatter.Serializer.WriteValue(value.x, writer);
Vector2IntFormatter.Serializer.WriteValue(value.y, writer);
}
}
/// <summary>
/// Custom formatter for the <see cref="Vector3Int"/> type.
/// </summary>
/// <seealso cref="Sirenix.Serialization.MinimalBaseFormatter{UnityEngine.Vector3Int}" />
public class Vector3IntFormatter : MinimalBaseFormatter<Vector3Int>
{
private static readonly Serializer<int> Serializer = OdinSerializer.Serializer.Get<int>();
/// <summary>
/// Reads into the specified value using the specified reader.
/// </summary>
/// <param name="value">The value to read into.</param>
/// <param name="reader">The reader to use.</param>
protected override void Read(ref Vector3Int value, IDataReader reader)
{
value.x = Vector3IntFormatter.Serializer.ReadValue(reader);
value.y = Vector3IntFormatter.Serializer.ReadValue(reader);
value.z = Vector3IntFormatter.Serializer.ReadValue(reader);
}
/// <summary>
/// Writes from the specified value using the specified writer.
/// </summary>
/// <param name="value">The value to write from.</param>
/// <param name="writer">The writer to use.</param>
protected override void Write(ref Vector3Int value, IDataWriter writer)
{
Vector3IntFormatter.Serializer.WriteValue(value.x, writer);
Vector3IntFormatter.Serializer.WriteValue(value.y, writer);
Vector3IntFormatter.Serializer.WriteValue(value.z, writer);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93c15c193841b7f45871c38815e37589
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,156 @@
//-----------------------------------------------------------------------
// <copyright file="OdinPrefabSerializationEditorUtility.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
//#define PREFAB_DEBUG
#if UNITY_EDITOR
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
public static class OdinPrefabSerializationEditorUtility
{
private static bool? hasNewPrefabWorkflow;
private static MethodInfo PrefabUtility_GetPrefabAssetType_Method = typeof(PrefabUtility).GetMethod("GetPrefabAssetType", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(UnityEngine.Object) }, null);
private static MethodInfo PrefabUtility_GetPrefabParent_Method = typeof(PrefabUtility).GetMethod("GetPrefabParent", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(UnityEngine.Object) }, null);
private static MethodInfo PrefabUtility_GetCorrespondingObjectFromSource_Method = typeof(PrefabUtility).GetMethod("GetCorrespondingObjectFromSource", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(UnityEngine.Object) }, null);
private static MethodInfo PrefabUtility_GetPrefabType_Method = typeof(PrefabUtility).GetMethod("GetPrefabType", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(UnityEngine.Object) }, null);
private static MethodInfo PrefabUtility_ApplyPropertyOverride_Method;
static OdinPrefabSerializationEditorUtility()
{
Type interactionModeEnum = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.InteractionMode");
if (interactionModeEnum != null)
{
PrefabUtility_ApplyPropertyOverride_Method = typeof(PrefabUtility).GetMethod("ApplyPropertyOverride", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(SerializedProperty), typeof(string), interactionModeEnum }, null);
}
}
public static bool HasNewPrefabWorkflow
{
get
{
if (hasNewPrefabWorkflow == null)
{
hasNewPrefabWorkflow = DetectNewPrefabWorkflow();
}
return hasNewPrefabWorkflow.Value;
}
}
public static bool HasApplyPropertyOverride
{
get
{
return PrefabUtility_ApplyPropertyOverride_Method != null;
}
}
private static bool DetectNewPrefabWorkflow()
{
try
{
var method = typeof(PrefabUtility).GetMethod("GetPrefabType", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(UnityEngine.Object) }, null);
if (method == null) return true;
if (method.IsDefined(typeof(ObsoleteAttribute), false))
{
return true;
}
return false;
}
catch
{
return false;
}
}
public static void ApplyPropertyOverride(SerializedProperty instanceProperty, string assetPath)
{
//PrefabUtility.ApplyPropertyOverride(instanceProperty, assetPath, InteractionMode.AutomatedAction);
if (!HasApplyPropertyOverride) throw new NotSupportedException("PrefabUtility.ApplyPropertyOverride doesn't exist in this version of Unity");
PrefabUtility_ApplyPropertyOverride_Method.Invoke(null, new object[] { instanceProperty, assetPath, 0 });
}
public static bool ObjectIsPrefabInstance(UnityEngine.Object unityObject)
{
if (PrefabUtility_GetPrefabType_Method != null)
{
try
{
int prefabType = Convert.ToInt32((Enum)PrefabUtility_GetPrefabType_Method.Invoke(null, new object[] { unityObject }));
// PrefabType.PrefabInstance == 3
if (prefabType == 3) return true;
}
catch (Exception) { }
}
if (PrefabUtility_GetPrefabAssetType_Method != null)
{
int prefabAssetType = Convert.ToInt32((Enum)PrefabUtility_GetPrefabAssetType_Method.Invoke(null, new object[] { unityObject }));
// 1 = PrefabAssetType.Regular
// 3 = PrefabAssetType.Variant
return prefabAssetType == 1 || prefabAssetType == 3;
}
if (PrefabUtility_GetPrefabType_Method == null && PrefabUtility_GetPrefabAssetType_Method == null)
{
Debug.LogError("Neither PrefabUtility.GetPrefabType or PrefabUtility.GetPrefabAssetType methods could be located. Prefab functionality will likely be broken in this build of Odin.");
}
return GetCorrespondingObjectFromSource(unityObject) != null;
}
public static bool ObjectHasNestedOdinPrefabData(UnityEngine.Object unityObject)
{
if (!HasNewPrefabWorkflow) return false;
if (!(unityObject is ISupportsPrefabSerialization)) return false;
var prefab = GetCorrespondingObjectFromSource(unityObject);
return IsOdinSerializedPrefabInstance(prefab);
}
private static bool IsOdinSerializedPrefabInstance(UnityEngine.Object unityObject)
{
if (!(unityObject is ISupportsPrefabSerialization)) return false;
return GetCorrespondingObjectFromSource(unityObject) != null;
}
public static UnityEngine.Object GetCorrespondingObjectFromSource(UnityEngine.Object unityObject)
{
if (PrefabUtility_GetCorrespondingObjectFromSource_Method != null)
{
return (UnityEngine.Object)PrefabUtility_GetCorrespondingObjectFromSource_Method.Invoke(null, new object[] { unityObject });
}
if (PrefabUtility_GetPrefabParent_Method != null)
{
return (UnityEngine.Object)PrefabUtility_GetPrefabParent_Method.Invoke(null, new object[] { unityObject });
}
Debug.LogError("Neither PrefabUtility.GetCorrespondingObjectFromSource or PrefabUtility.GetPrefabParent methods could be located. Prefab functionality will be broken in this build of Odin.");
return null;
}
}
}
#endif

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aaf2f90207414827b53b85dae0eae82e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e281f95be0fe014489e2c46801dce8cc
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
//-----------------------------------------------------------------------
// <copyright file="IOverridesSerializationFormat.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Indicates that an Odin-serialized Unity object controls its own serialization format. Every time it is serialized, it will be asked which format to use.
/// </summary>
public interface IOverridesSerializationFormat
{
/// <summary>
/// Gets the format to use for serialization.
/// </summary>
DataFormat GetFormatToSerializeAs(bool isPlayer);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ff1ca109149d83b03b39644f8045275e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,31 @@
//-----------------------------------------------------------------------
// <copyright file="IOverridesSerializationPolicy.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Indicates that an Odin-serialized Unity object provides its own serialization policy rather than using the default policy.
/// <para/>
/// Note that THE VALUES RETURNED BY THIS INTERFACE WILL OVERRIDE THE PARAMETERS PASSED TO <see cref="UnitySerializationUtility.SerializeUnityObject(UnityEngine.Object, ref SerializationData, bool, SerializationContext)"/> and <see cref="UnitySerializationUtility.DeserializeUnityObject(UnityEngine.Object, ref SerializationData, DeserializationContext)"/>.
/// </summary>
public interface IOverridesSerializationPolicy
{
ISerializationPolicy SerializationPolicy { get; }
bool OdinSerializesUnityFields { get; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8942002e9ac41c2bfd27c4fbedf93f09
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,30 @@
//-----------------------------------------------------------------------
// <copyright file="ISupportsPrefabSerialization.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
/// <summary>
/// Indicates that an Odin-serialized Unity object supports prefab serialization.
/// </summary>
public interface ISupportsPrefabSerialization
{
/// <summary>
/// Gets or sets the serialization data of the object.
/// </summary>
SerializationData SerializationData { get; set; }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7279ec8ad7837f13ec833193ab4282cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,176 @@
//-----------------------------------------------------------------------
// <copyright file="SerializationData.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System;
using System.Collections.Generic;
using UnityEngine;
using Utilities;
/// <summary>
/// Unity serialized data struct that contains all data needed by Odin serialization.
/// </summary>
[Serializable]
public struct SerializationData
{
/// <summary>
/// The name of the <see cref="PrefabModificationsReferencedUnityObjects"/> field.
/// </summary>
public const string PrefabModificationsReferencedUnityObjectsFieldName = "PrefabModificationsReferencedUnityObjects";
/// <summary>
/// The name of the <see cref="PrefabModifications"/> field.
/// </summary>
public const string PrefabModificationsFieldName = "PrefabModifications";
/// <summary>
/// The name of the <see cref="Prefab"/> field.
/// </summary>
public const string PrefabFieldName = "Prefab";
/// <summary>
/// The data format used by the serializer. This field will be automatically set to the format specified in the global serialization config
/// when the Unity object gets serialized, unless the Unity object implements the <see cref="IOverridesSerializationFormat"/> interface.
/// </summary>
[SerializeField]
public DataFormat SerializedFormat;
/// <summary>
/// The serialized data when serializing with the Binray format.
/// </summary>
[SerializeField]
public byte[] SerializedBytes;
/// <summary>
/// All serialized Unity references.
/// </summary>
[SerializeField]
public List<UnityEngine.Object> ReferencedUnityObjects;
/// <summary>
/// Whether the object contains any serialized data.
/// </summary>
[Obsolete("Use ContainsData instead")]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public bool HasEditorData
{
get
{
switch (this.SerializedFormat)
{
case DataFormat.Binary:
case DataFormat.JSON:
return !(this.SerializedBytesString.IsNullOrWhitespace() && (this.SerializedBytes == null || this.SerializedBytes.Length == 0));
case DataFormat.Nodes:
return !(this.SerializationNodes == null || this.SerializationNodes.Count == 0);
default:
throw new NotImplementedException(this.SerializedFormat.ToString());
}
}
}
/// <summary>
/// Gets a value indicating whether the struct contains any data.
/// If this is false, then it could mean that Unity has not yet deserialized the struct.
/// </summary>
public bool ContainsData
{
get
{
return
// this.SerializedBytesString != null && // Unity serialized strings remains null when an object is created until it's deserialized.
this.SerializedBytes != null &&
this.SerializationNodes != null &&
this.PrefabModifications != null &&
this.ReferencedUnityObjects != null;
}
}
/// <summary>
/// The serialized data when serializing with the JSON format.
/// </summary>
[SerializeField]
public string SerializedBytesString;
/// <summary>
/// The reference to the prefab this is only populated in prefab scene instances.
/// </summary>
[SerializeField]
public UnityEngine.Object Prefab;
/// <summary>
/// All serialized Unity references.
/// </summary>
[SerializeField]
public List<UnityEngine.Object> PrefabModificationsReferencedUnityObjects;
/// <summary>
/// All Odin serialized prefab modifications.
/// </summary>
[SerializeField]
public List<string> PrefabModifications;
/// <summary>
/// The serialized data when serializing with the Nodes format.
/// </summary>
[SerializeField]
public List<SerializationNode> SerializationNodes;
/// <summary>
/// Resets all data.
/// </summary>
public void Reset()
{
this.SerializedFormat = DataFormat.Binary;
if (this.SerializedBytes != null && this.SerializedBytes.Length > 0)
{
this.SerializedBytes = new byte[0];
}
if (this.ReferencedUnityObjects != null && this.ReferencedUnityObjects.Count > 0)
{
this.ReferencedUnityObjects.Clear();
}
this.Prefab = null;
if (this.SerializationNodes != null && this.SerializationNodes.Count > 0)
{
this.SerializationNodes.Clear();
}
if (this.SerializedBytesString != null && this.SerializedBytesString.Length > 0)
{
this.SerializedBytesString = string.Empty;
}
if (this.PrefabModificationsReferencedUnityObjects != null && this.PrefabModificationsReferencedUnityObjects.Count > 0)
{
this.PrefabModificationsReferencedUnityObjects.Clear();
}
if (this.PrefabModifications != null && this.PrefabModifications.Count > 0)
{
this.PrefabModifications.Clear();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ea095023abd05a7af0da4166dcefdee8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,62 @@
//-----------------------------------------------------------------------
// <copyright file="SerializedBehaviour.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// A Unity Behaviour which is serialized by the Sirenix serialization system.
/// </summary>
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowOdinSerializedPropertiesInInspector]
#endif
public abstract class SerializedBehaviour : Behaviour, ISerializationCallbackReceiver, ISupportsPrefabSerialization
{
[SerializeField, HideInInspector]
private SerializationData serializationData;
SerializationData ISupportsPrefabSerialization.SerializationData { get { return this.serializationData; } set { this.serializationData = value; } }
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
this.OnAfterDeserialize();
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
this.OnBeforeSerialize();
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
}
/// <summary>
/// Invoked after deserialization has taken place.
/// </summary>
protected virtual void OnAfterDeserialize()
{
}
/// <summary>
/// Invoked before serialization has taken place.
/// </summary>
protected virtual void OnBeforeSerialize()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3cecb461cebbc940ede3b5ddb72382e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,62 @@
//-----------------------------------------------------------------------
// <copyright file="SerializedComponent.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// A Unity Component which is serialized by the Sirenix serialization system.
/// </summary>
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowOdinSerializedPropertiesInInspector]
#endif
public abstract class SerializedComponent : Component, ISerializationCallbackReceiver, ISupportsPrefabSerialization
{
[SerializeField, HideInInspector]
private SerializationData serializationData;
SerializationData ISupportsPrefabSerialization.SerializationData { get { return this.serializationData; } set { this.serializationData = value; } }
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
this.OnAfterDeserialize();
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
this.OnBeforeSerialize();
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
}
/// <summary>
/// Invoked after deserialization has taken place.
/// </summary>
protected virtual void OnAfterDeserialize()
{
}
/// <summary>
/// Invoked before serialization has taken place.
/// </summary>
protected virtual void OnBeforeSerialize()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 56b88cfe9935184fe250bda018144f26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,63 @@
//-----------------------------------------------------------------------
// <copyright file="SerializedMonoBehaviour.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// A Unity MonoBehaviour which is serialized by the Sirenix serialization system.
/// </summary>
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowOdinSerializedPropertiesInInspector]
#endif
public abstract class SerializedMonoBehaviour : MonoBehaviour, ISerializationCallbackReceiver, ISupportsPrefabSerialization
{
[SerializeField, HideInInspector]
private SerializationData serializationData;
SerializationData ISupportsPrefabSerialization.SerializationData { get { return this.serializationData; } set { this.serializationData = value; } }
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
this.OnAfterDeserialize();
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
this.OnBeforeSerialize();
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
}
/// <summary>
/// Invoked after deserialization has taken place.
/// </summary>
protected virtual void OnAfterDeserialize()
{
}
/// <summary>
/// Invoked before serialization has taken place.
/// </summary>
protected virtual void OnBeforeSerialize()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d1b9fa6342beb9fdfc2c4bc1d8e5e971
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,60 @@
//-----------------------------------------------------------------------
// <copyright file="SerializedScriptableObject.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// A Unity ScriptableObject which is serialized by the Sirenix serialization system.
/// </summary>
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowOdinSerializedPropertiesInInspector]
#endif
public abstract class SerializedScriptableObject : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
private SerializationData serializationData;
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
this.OnAfterDeserialize();
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
this.OnBeforeSerialize();
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
}
/// <summary>
/// Invoked after deserialization has taken place.
/// </summary>
protected virtual void OnAfterDeserialize()
{
}
/// <summary>
/// Invoked before serialization has taken place.
/// </summary>
protected virtual void OnBeforeSerialize()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6cb9325ffffee5d6ed94d71590b4049a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,60 @@
//-----------------------------------------------------------------------
// <copyright file="SerializedStateMachineBehaviour.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// A Unity StateMachineBehaviour which is serialized by the Sirenix serialization system.
/// </summary>
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowOdinSerializedPropertiesInInspector]
#endif
public abstract class SerializedStateMachineBehaviour : StateMachineBehaviour, ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
private SerializationData serializationData;
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
this.OnAfterDeserialize();
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
this.OnBeforeSerialize();
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
}
/// <summary>
/// Invoked after deserialization has taken place.
/// </summary>
protected virtual void OnAfterDeserialize()
{
}
/// <summary>
/// Invoked before serialization has taken place.
/// </summary>
protected virtual void OnBeforeSerialize()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eefcd68a84ee7903b08c6254c17fafe3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,60 @@
//-----------------------------------------------------------------------
// <copyright file="SerializedUnityObject.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// A Unity ScriptableObject which is serialized by the Sirenix serialization system.
/// </summary>
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowOdinSerializedPropertiesInInspector]
#endif
public abstract class SerializedUnityObject : UnityEngine.Object, ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
private SerializationData serializationData;
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
UnitySerializationUtility.DeserializeUnityObject(this, ref this.serializationData);
this.OnAfterDeserialize();
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
this.OnBeforeSerialize();
UnitySerializationUtility.SerializeUnityObject(this, ref this.serializationData);
}
/// <summary>
/// Invoked after deserialization has taken place.
/// </summary>
protected virtual void OnAfterDeserialize()
{
}
/// <summary>
/// Invoked before serialization has taken place.
/// </summary>
protected virtual void OnBeforeSerialize()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d62f7ab4e5aa075b819d6c71e929686b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,160 @@
//-----------------------------------------------------------------------
// <copyright file="UnityReferenceResolver.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using System.Collections.Generic;
using Utilities;
/// <summary>
/// Resolves external index references to Unity objects.
/// </summary>
/// <seealso cref="IExternalIndexReferenceResolver" />
/// <seealso cref="ICacheNotificationReceiver" />
public sealed class UnityReferenceResolver : IExternalIndexReferenceResolver, ICacheNotificationReceiver
{
private Dictionary<UnityEngine.Object, int> referenceIndexMapping = new Dictionary<UnityEngine.Object, int>(32, ReferenceEqualityComparer<UnityEngine.Object>.Default);
private List<UnityEngine.Object> referencedUnityObjects;
/// <summary>
/// Initializes a new instance of the <see cref="UnityReferenceResolver"/> class.
/// </summary>
public UnityReferenceResolver()
{
this.referencedUnityObjects = new List<UnityEngine.Object>();
}
/// <summary>
/// Initializes a new instance of the <see cref="UnityReferenceResolver"/> class with a list of Unity objects.
/// </summary>
/// <param name="referencedUnityObjects">The referenced Unity objects.</param>
public UnityReferenceResolver(List<UnityEngine.Object> referencedUnityObjects)
{
this.SetReferencedUnityObjects(referencedUnityObjects);
}
/// <summary>
/// Gets the currently referenced Unity objects.
/// </summary>
/// <returns>A list of the currently referenced Unity objects.</returns>
public List<UnityEngine.Object> GetReferencedUnityObjects()
{
return this.referencedUnityObjects;
}
/// <summary>
/// Sets the referenced Unity objects of the resolver to a given list, or a new list if the value is null.
/// </summary>
/// <param name="referencedUnityObjects">The referenced Unity objects to set, or null if a new list is required.</param>
public void SetReferencedUnityObjects(List<UnityEngine.Object> referencedUnityObjects)
{
if (referencedUnityObjects == null)
{
referencedUnityObjects = new List<UnityEngine.Object>();
}
this.referencedUnityObjects = referencedUnityObjects;
this.referenceIndexMapping.Clear();
for (int i = 0; i < this.referencedUnityObjects.Count; i++)
{
if (object.ReferenceEquals(this.referencedUnityObjects[i], null) == false)
{
if (!this.referenceIndexMapping.ContainsKey(this.referencedUnityObjects[i]))
{
this.referenceIndexMapping.Add(this.referencedUnityObjects[i], i);
}
}
}
}
/// <summary>
/// Determines whether the specified value can be referenced externally via this resolver.
/// </summary>
/// <param name="value">The value to reference.</param>
/// <param name="index">The index of the resolved value, if it can be referenced.</param>
/// <returns>
/// <c>true</c> if the reference can be resolved, otherwise <c>false</c>.
/// </returns>
public bool CanReference(object value, out int index)
{
if (this.referencedUnityObjects == null)
{
this.referencedUnityObjects = new List<UnityEngine.Object>(32);
}
var obj = value as UnityEngine.Object;
if (object.ReferenceEquals(null, obj) == false)
{
if (this.referenceIndexMapping.TryGetValue(obj, out index) == false)
{
index = this.referencedUnityObjects.Count;
this.referenceIndexMapping.Add(obj, index);
this.referencedUnityObjects.Add(obj);
}
return true;
}
index = -1;
return false;
}
/// <summary>
/// Tries to resolve the given reference index to a reference value.
/// </summary>
/// <param name="index">The index to resolve.</param>
/// <param name="value">The resolved value.</param>
/// <returns>
/// <c>true</c> if the index could be resolved to a value, otherwise <c>false</c>.
/// </returns>
public bool TryResolveReference(int index, out object value)
{
if (this.referencedUnityObjects == null || index < 0 || index >= this.referencedUnityObjects.Count)
{
// Sometimes something has destroyed the list of references in between serialization and deserialization
// (Unity prefab instances are especially bad at preserving such data), and in these cases we still don't
// want the system to fall back to a formatter, so we give out a null value.
value = null;
return true;
}
value = this.referencedUnityObjects[index];
return true;
}
/// <summary>
/// Resets this instance.
/// </summary>
public void Reset()
{
this.referencedUnityObjects = null;
this.referenceIndexMapping.Clear();
}
void ICacheNotificationReceiver.OnFreed()
{
this.Reset();
}
void ICacheNotificationReceiver.OnClaimed()
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: de5584f66ccc5e072681a310c5987b8c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,100 @@
//-----------------------------------------------------------------------
// <copyright file="UnitySerializationInitializer.cs" company="Sirenix IVS">
// Copyright (c) 2018 Sirenix IVS
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>
//-----------------------------------------------------------------------
namespace VRC.Udon.Serialization.OdinSerializer
{
using UnityEngine;
/// <summary>
/// Utility class which initializes the Sirenix serialization system to be compatible with Unity.
/// </summary>
public static class UnitySerializationInitializer
{
private static readonly object LOCK = new object();
private static bool initialized = false;
public static bool Initialized { get { return initialized; } }
public static RuntimePlatform CurrentPlatform { get; private set; }
/// <summary>
/// Initializes the Sirenix serialization system to be compatible with Unity.
/// </summary>
public static void Initialize()
{
if (!initialized)
{
lock (LOCK)
{
if (!initialized)
{
try
{
// Ensure that the config instance is loaded before deserialization of anything occurs.
// If we try to load it during deserialization, Unity will throw exceptions, as a lot of
// the Unity API is disallowed during serialization and deserialization.
GlobalSerializationConfig.LoadInstanceIfAssetExists();
CurrentPlatform = Application.platform;
if (Application.isEditor) return;
ArchitectureInfo.SetRuntimePlatform(CurrentPlatform);
//if (CurrentPlatform == RuntimePlatform.Android)
//{
// //using (var system = new AndroidJavaClass("java.lang.System"))
// //{
// // string architecture = system.CallStatic<string>("getProperty", "os.arch");
// // ArchitectureInfo.SetIsOnAndroid(architecture);
// //}
//}
//else if (CurrentPlatform == RuntimePlatform.IPhonePlayer)
//{
// ArchitectureInfo.SetIsOnIPhone();
//}
//else
//{
// ArchitectureInfo.SetIsNotOnMobile();
//}
}
finally
{
initialized = true;
}
}
}
}
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void InitializeRuntime()
{
Initialize();
}
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoadMethod]
private static void InitializeEditor()
{
Initialize();
}
#endif
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f670c1f9aa9ab0c5988e81802c005767
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9eb15f2339819bb651c7872d73c89776
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: