Skip to content
Branch: master
Find file Copy path
Find file Copy path
2 contributors

Users who have contributed to this file

@rikimaru0345 @NFMynster
222 lines (178 sloc) 6.43 KB
using System;
namespace Ceras
using Formatters;
using Resolvers;
using System.Collections.Generic;
using UnityEngine;
public static class CerasUnityFormatters
static Type[] _blittableTypes = new Type[]
// Primitives
// Extended primitives
// Gradient data
// Misc
typeof(Keyframe), // Warning: Keyframe has changed from 2017.x to 2018.1. It has gained 3 items describing "weighted mode"
#if UNITY_2017_2_OR_NEWER
static Dictionary<Type, Type> _typeToFormatterType = new Dictionary<Type, Type>
// New
{ typeof(AnimationCurve), typeof(AnimationCurveFormatter) },
{ typeof(RectOffset), typeof(RectOffsetFormatter) },
{ typeof(Gradient), typeof(GradientFormatter) },
{ typeof(LayerMask), typeof(LayerMaskFormatter) },
public static void ApplyToConfig(SerializerConfig config)
// Force usage of the reinterpret formatter for simple types
foreach (var t in _blittableTypes)
config.ConfigType(t).CustomResolver = ForceReinterpret;
// Same for arrays of those types
foreach (var t in _blittableTypes)
var arType = t.MakeArrayType();
config.ConfigType(arType).CustomResolver = ForceReinterpretArray;
// Add our resolver method for all types that need a custom formatter
static IFormatter GetFormatter(CerasSerializer ceras, Type typeToBeFormatted)
Type formatterType;
if (_typeToFormatterType.TryGetValue(typeToBeFormatted, out formatterType))
return (IFormatter)Activator.CreateInstance(formatterType);
return null;
static IFormatter ForceReinterpret(CerasSerializer ceras, Type typeToBeFormatted)
var formatterType = typeof(ReinterpretFormatter<>).MakeGenericType(typeToBeFormatted);
return (IFormatter) Activator.CreateInstance(formatterType);
static IFormatter ForceReinterpretArray(CerasSerializer ceras, Type typeToBeFormatted)
var itemType = typeToBeFormatted.GetElementType();
var maxCount = itemType == typeof(byte)
? ceras.GetConfig().Advanced.SizeLimits.MaxByteArraySize
: ceras.GetConfig().Advanced.SizeLimits.MaxArraySize;
var formatterType = typeof(ReinterpretArrayFormatter<>).MakeGenericType(itemType);
return (IFormatter)Activator.CreateInstance(formatterType, maxCount);
#region "New" Types
class AnimationCurveFormatter : IFormatter<AnimationCurve>
// Auto-injected by Ceras
IFormatter<Keyframe> _keyframeFormatter = default;
EnumFormatter<WrapMode> _wrapModeFormatter = default;
public void Serialize(ref byte[] buffer, ref int offset, AnimationCurve value)
var keys = value.keys;
// Length
SerializerBinary.WriteInt32(ref buffer, ref offset, keys.Length);
// Keyframes
for (int i = 0; i < keys.Length; i++)
_keyframeFormatter.Serialize(ref buffer, ref offset, keys[i]);
_wrapModeFormatter.Serialize(ref buffer, ref offset, value.preWrapMode);
_wrapModeFormatter.Serialize(ref buffer, ref offset, value.postWrapMode);
public void Deserialize(byte[] buffer, ref int offset, ref AnimationCurve value)
// Read length
var length = SerializerBinary.ReadInt32(buffer, ref offset);
// Deserialize individual keyframes again
var keys = new Keyframe[length];
for (int i = 0; i < length; i++)
_keyframeFormatter.Deserialize(buffer, ref offset, ref keys[i]);
// Create or update the given AnimationCurve
if (value == null)
value = new AnimationCurve(keys);
value.keys = keys;
// Set the wrap modes
var wrap = default(WrapMode);
_wrapModeFormatter.Deserialize(buffer, ref offset, ref wrap);
value.preWrapMode = wrap;
_wrapModeFormatter.Deserialize(buffer, ref offset, ref wrap);
value.postWrapMode = wrap;
// RectOffset is a class, it can't be blitted.
class RectOffsetFormatter : IFormatter<RectOffset>
public void Serialize(ref byte[] buffer, ref int offset, RectOffset value)
SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.left);
SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.right);
SerializerBinary.WriteInt32Fixed(ref buffer, ref offset,;
SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.bottom);
public void Deserialize(byte[] buffer, ref int offset, ref RectOffset value)
value.left = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
value.right = SerializerBinary.ReadInt32Fixed(buffer, ref offset); = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
value.bottom = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
class GradientFormatter : IFormatter<Gradient>
// Auto-injected by Ceras
IFormatter<GradientAlphaKey[]> _alphaKeysFormatter = default;
IFormatter<GradientColorKey[]> _colorKeysFormatter = default;
EnumFormatter<GradientMode> _gradientModeFormatter = default;
public void Serialize(ref byte[] buffer, ref int offset, Gradient value)
_alphaKeysFormatter.Serialize(ref buffer, ref offset, value.alphaKeys);
_colorKeysFormatter.Serialize(ref buffer, ref offset, value.colorKeys);
_gradientModeFormatter.Serialize(ref buffer, ref offset, value.mode);
public void Deserialize(byte[] buffer, ref int offset, ref Gradient value)
GradientAlphaKey[] alphaKeys = value.alphaKeys;
_alphaKeysFormatter.Deserialize(buffer, ref offset, ref alphaKeys);
value.alphaKeys = alphaKeys;
GradientColorKey[] colorKeys = value.colorKeys;
_colorKeysFormatter.Deserialize(buffer, ref offset, ref colorKeys);
value.colorKeys = colorKeys;
var mode = value.mode;
_gradientModeFormatter.Deserialize(buffer, ref offset, ref mode);
value.mode = mode;
class LayerMaskFormatter : IFormatter<LayerMask>
public void Serialize(ref byte[] buffer, ref int offset, LayerMask value)
SerializerBinary.WriteInt32Fixed(ref buffer, ref offset, value.value);
public void Deserialize(byte[] buffer, ref int offset, ref LayerMask value)
value.value = SerializerBinary.ReadInt32Fixed(buffer, ref offset);
You can’t perform that action at this time.