Skip to content
Permalink
Browse files
(FINALLY) Fast.Save initial commit!
  • Loading branch information
vexe committed Jul 12, 2015
1 parent 9ee8cfc commit ee20dbed99c71f56d879d002dc6edc4b9da0b82e
Showing 96 changed files with 5,996 additions and 0 deletions.

Some generated files are not rendered by default. Learn more.

Some generated files are not rendered by default. Learn more.

@@ -0,0 +1,63 @@
using System;
using BX20Serializer;
using UnityEngine;
using Vexe.FastSave.Serializers;
using Vexe.Runtime.Serialization;

namespace Vexe.FastSave
{
public static class Common
{
public static readonly BinaryX20 Serializer;

static Common()
{
BinaryX20.Log = Debug.Log;

var logic = new VFWSerializationLogic(
@serializeMemberAttributes: new Type[] { typeof(SaveAttribute) },
@dontSerializeMemberAttributes: new Type[] { typeof(DontSaveAttribute) });

Serializer = new BinaryX20(
logic.IsSerializableField,
logic.IsSerializableProperty);

var ecs = new ExplicitComponentSerializer();
ecs.Add<Transform>("position", "eulerAngles", "localScale")
.Add<Rigidbody>("mass", "drag", "isKinematic", "useGravity", "angularDrag", "constraints", "interpolation", "collisionDetectionMode")
.Add<MeshFilter>("sharedMesh")
.Add<MeshRenderer>("shadowCastingMode", "receiveShadows", "sharedMaterials", "useLightProbes", "reflectionProbeUsage", "probeAnchor")
.Add<SkinnedMeshRenderer>("shadowCastingMode", "receiveShadows", "sharedMaterials", "useLightProbes", "reflectionProbeUsage", "probeAnchor", "rootBone", "quality", "localBounds", "sharedMesh", "updateWhenOffscreen")
.Add<TrailRenderer>("shadowCastingMode", "receiveShadows", "sharedMaterials", "useLightProbes", "reflectionProbeUsage", "probeAnchor", "time", "startWidth", "endWidth", "autodestruct")
.Add<ParticleRenderer>("shadowCastingMode", "receiveShadows", "sharedMaterials", "useLightProbes", "reflectionProbeUsage", "probeAnchor", "cameraVelocityScale", "particleRenderMode", "lengthScale", "velocityScale", "maxParticleSize", "uvAnimationCycles", "uvAnimationXTile", "uvAnimationYTile", "uvTiles")
.Add<ParticleAnimator>("doesAnimateColor", "colorAnimation", "worldRotationAxis", "localRotationAxis", "rndForce", "force", "sizeGrow", "damping", "autodestruct")
.Add<Camera>("fieldOfView", "orthographicSize", "orthographic", "nearClipPlane", "farClipPlane", "backgroundColor", "clearFlags", "rect", "depth", "renderingPath", "hdr", "targetTexture")
.Add<CharacterController>("stepOffset", "radius", "height", "center")
.Add<AudioSource>("clip", "volume", "pitch", "time", "mute", "playOnAwake", "loop")
.Add<Animator>("runtimeAnimatorController", "applyRootMotion")
.Add<BoxCollider>("isTrigger", "center", "size", "sharedMaterial")
.Add<CapsuleCollider>("isTrigger", "center", "radius", "height", "direction", "sharedMaterial")
.Add<MeshCollider>("isTrigger", "convex", "sharedMaterial", "sharedMesh")
.Add<SphereCollider>("isTrigger", "radius", "center", "sharedMaterial")
.Add<BoxCollider2D>("isTrigger", "sharedMaterial", "usedByEffector", "offset", "size")
.Add<CircleCollider2D>("isTrigger", "sharedMaterial", "usedByEffector", "offset", "radius")
.Add<PolygonCollider2D>("isTrigger", "sharedMaterial", "usedByEffector", "offset", "points", "pathCount")
.Add<EdgeCollider2D>("isTrigger", "sharedMaterial", "usedByEffector", "offset", "points")
.Add<Rigidbody2D>("mass", "drag", "angularDrag", "angularVelocity", "gravityScale", "fixedAngle", "isKinematic", "interpolation", "sleepMode", "collisionDetectionMode")
.Add<ConstantForce2D>("force", "relativeForce", "torque")
.Add<AreaEffector2D>("colliderMask", "forceDirection", "forceMagnitude", "forceVariation", "drag", "angularDrag", "forceTarget")
.Add<PlatformEffector2D>("colliderMask", "oneWay", "sideFriction", "sideBounce", "sideAngleVariance")
.Add<PointEffector2D>("colliderMask", "forceMagnitude", "forceVariation", "distanceScale", "drag", "angularDrag", "forceSource", "forceTarget", "forceMode")
.Add<SurfaceEffector2D>("colliderMask", "speed", "speedVariation")
.Add<DistanceJoint2D>("collideConnected", "connectedBody", "connectedAnchor", "anchor", "distance", "maxDistanceOnly")
.Add<HingeJoint2D>("collideConnected", "connectedBody", "connectedAnchor", "anchor", "useMotor", "motor", "useLimits", "limits")
.Add<SliderJoint2D>("collideConnected", "connectedBody", "connectedAnchor", "anchor", "angle", "useMotor", "motor", "useLimits", "limits")
.Add<SpringJoint2D>("collideConnected", "connectedBody", "connectedAnchor", "anchor", "distance", "dampingRatio", "frequency")
.Add<WheelJoint2D>("collideConnected", "connectedBody", "connectedAnchor", "anchor", "suspension", "useMotor", "motor");

Serializer.AddSerializer(new AssetReferenceSerializer())
.AddSerializer(new ReflectiveComponentSerializer())
.AddSerializer(ecs);
}
}
}

Some generated files are not rendered by default. Learn more.

@@ -0,0 +1,233 @@
//#define PROFILE
//#define DBG

using System;
using System.Collections.Generic;
using System.IO;
using BX20Serializer;
using UnityEngine;
using Vexe.FastSave.Serializers;
using Vexe.Runtime.Extensions;
using Vexe.Runtime.Helpers;
using Vexe.Runtime.Types;
using UnityObject = UnityEngine.Object;

namespace Vexe.FastSave
{
public static class Load
{
public static event Action<Dictionary<int, string>> OnBeganLoadingMarked;

public static event Action<Dictionary<int, string>> OnFinishedLoadingMarked;

// Stream
#region
public static bool MarkedFromStream(Stream stream)
{
#if DBG
string status = "Began";
#endif

try
{
if (stream.Length == 0)
{
#if DBG
Log("Save stream is empty");
#endif
return false;
}

var data = Load.ObjectFromStream<Dictionary<int, string>>(stream);
#if DBG
status = "Loaded marked from stream";
#endif
var markers = UnityObject.FindObjectsOfType<FSMarker>();

if (OnBeganLoadingMarked != null)
OnBeganLoadingMarked(data);

for (int i = 0; i < markers.Length; i++)
{
var marked = markers[i];
int id = marked.GetPersistentId();
string serializedState;
if (!data.TryGetValue(id, out serializedState))
continue;
#if DBG
status = "Loading " + marked.name;
#endif
var bytes = serializedState.GetBytes();
using (var memory = new MemoryStream(bytes))
Load.GameObjectFromStream(memory, marked.gameObject);
}

if (OnFinishedLoadingMarked != null)
OnFinishedLoadingMarked(data);

return true;
}
catch (Exception e)
{
#if DBG
Log(string.Format("Error ({0}) {1}", status, e.Message));
#else
Log("Error loading: " + e.Message);
#endif
return false;
}
}

public static void GameObjectFromStream(Stream stream, GameObject into)
{
GameObjectSerializer.Read(stream, into);

int numSavedComponents = stream.ReadInt();
for (int i = 0; i < numSavedComponents; i++)
{
var type = TypeSerializer.Read(stream);
var component = into.GetOrAddComponent(type);
ComponentFromStream(stream, type, component);
}
}

public static void HierarchyFromStream(Stream stream, GameObject root)
{
var numSavedChildren = stream.ReadInt();
var children = root.GetComponentsInChildren<Transform>();
var newHierarchy = numSavedChildren != children.Length;

var list = new List<Tuple<GameObject, int>>(numSavedChildren);

if (newHierarchy)
{
GameObjectFromStream(stream, root);
list.Add(Tuple.Create(root, 0));
for (int i = 0; i < numSavedChildren - 1; i++)
{
var depth = stream.ReadInt();
var go = new GameObject();
GameObjectFromStream(stream, go);
list.Add(Tuple.Create(go, depth));
}
}
else
{
GameObjectFromStream(stream, root);
list.Add(Tuple.Create(root, 0));
for (int i = 0; i < numSavedChildren - 1; i++)
{
var depth = stream.ReadInt();
var go = children[i + 1].gameObject;
GameObjectFromStream(stream, go);
list.Add(Tuple.Create(go, depth));
}
}

// traverse forward
for (int i = 0; i < list.Count; i++)
{
// foreach item going forward, we traverse backwards
// to find the first parent item
var forward = list[i];
for (int j = i - 1; j >= 0; j--)
{
var backward = list[j];
if (forward.Item2 == backward.Item2 + 1)
{
//Debug.Log("parenting: " + forward.Item1 + " to: " + backward.Item1);
forward.Item1.transform.SetParent(backward.Item1.transform, true);
break;
}
}
}
}

public static void ComponentFromStream(Stream stream, Component into)
{
ComponentFromStream(stream, into.GetType(), into);
}

public static void ComponentFromStream(Stream stream, Type type, Component into)
{
Common.Serializer.Deserialize(stream, type, ref into);
}

public static T ObjectFromStream<T>(Stream stream)
{
T instance = default(T);
Common.Serializer.Deserialize(stream, typeof(T), ref instance);
return instance;
}
#endregion

// File
#region
public static bool MarkedFromFile(string path)
{
using(var file = File.OpenRead(path))
return MarkedFromStream(file);
}

public static void GameObjectFromFile(string path, GameObject into)
{
Assert.PathExists(path);
using (var file = File.OpenRead(path))
GameObjectFromStream(file, into);
}

public static void ComponentFromFile(string path, Component into)
{
Assert.PathExists(path);
using (var file = File.OpenRead(path))
ComponentFromStream(file, into);
}

public static void HierarchyFromFile(string path, GameObject root)
{
using(var file = File.OpenRead(path))
HierarchyFromStream(file, root);
}
#endregion

// Memory
#region
public static bool MarkedFromMemory(byte[] bytes)
{
using(var memory = new MemoryStream(bytes))
return MarkedFromStream(memory);
}

public static void GameObjectFromMemory(byte[] bytes, GameObject into)
{
using (var ms = new MemoryStream(bytes))
GameObjectFromStream(ms, into);
}

public static void HierarchyFromMemory(byte[] bytes, GameObject into)
{
using (var ms = new MemoryStream(bytes))
HierarchyFromStream(ms, into);
}

public static void ComponentFromMemory(byte[] bytes, Component into)
{
using (var ms = new MemoryStream(bytes))
ComponentFromStream(ms, into);
}

public static T ObjectFromMemory<T>(byte[] bytes)
{
using (var ms = new MemoryStream(bytes))
return ObjectFromStream<T>(ms);
}
#endregion

static void Log(string msg)
{
#if DBG
Debug.Log(msg);
#endif
}
}
}

Some generated files are not rendered by default. Learn more.

0 comments on commit ee20dbe

Please sign in to comment.