Dras.biz Just another WordPress site

May 14, 2012

SaveIt

Filed under: SaveIt — mark @ 12:31

Overview:

Context API Reference:
SaveContext Class
LoadContext Class
TableSerializer Classes

Customizing SaveIt:
Customize Saving/Loading Objects

Customizing Saving/Loading Objects

Filed under: SaveIt,SaveIT API Reference — mark @ 12:27

When saving an object all what the SaveContext of SaveIt does is to store it into an internal TableEntry. The real magic comes when saving a class with a Save method or a class with an associated Serializer, this article describes both:

First, the Save and the Load method.
When saving this class:

1
2
3
4
5
public class Foo
{
	public int myValue;
	public string myOtherValue;
}

SaveIt will use a ClassSerializer which basically serialized/deserializes all members of the class, which means that SaveIt will store the myValue and myOtherValue member. Sometimes this is not what you want, for this there are several possibilities, the first one is the usage of the Load and Save Method, for this we extend our existing class:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Foo
{
	public int myValue;
	public string myOtherValue;
 
	void Save(SaveContext context, ref bool allowAutoSerialization)
	{
	}
 
	void Load(LoadContext context, ref bool allowAutoDeserialization)
	{
	}
}

SaveIt will call those methods when serializing or deserializing an instance of the Foo class and you can now specify what should happen when those are called.
Now we can save everything on our way, for this example we save only our int myValue and ignore the string myOtherValue:

1
2
3
4
void Save(SaveContext context, ref bool allowAutoSerialization)
{
	context.Save(myValue);
}

Thats it, we stored the value myValue, BUT SaveIt will still serialize everything else like it will be done without this Save method.
To change this we can set the bool allowAutoSerialization argument to false. SaveIt will then skip all other automatically performed actions.

1
2
3
4
5
void Save(SaveContext context, ref bool allowAutoSerialization)
{
	allowAutoSerialization = false;
	context.Save(myValue);
}

Loading the data inside the Load method, is equally simple:

1
2
3
4
5
6
void Load(LoadContext context, ref bool allowAutoDeserialization)
{
	allowAutoDeserialization = false;
	myValue = context.Load<int>(myValue);
	// or: context.Load(out myValue);
}

The other option to specify custom serialization is by using a type serializer, type serializers inherit from the interface ITypeSerializer:

1
2
3
4
5
6
public interface ITypeSerializer
{
	bool IsUsable(Type type);
	void Serialize(object what, SaveContext context);
	void Deserialize(Type type, LoadContext context);
}

But in most cases you want to use the SaveIt.TypeSerializer.ClassSerializer class to start with, as it performs most operations needed and allows full control on what to serialize/deserialize. But for the next example we will create a fresh Serializer without using ClassSerializer.

Here an example type serializer for the Foo class which does exactly the same thing we did earlier with the Load/Save methods in our Foo class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class FooSerializer : ITypeSerializer
{
	public bool IsUsable(Type type)
	{
		// We only want that this serializer works for the type Foo
		return type == typeof(Foo);
	}
 
	public void Serialize(object what, SaveContext context)
	{
		// This is needed in case our class we want to serialize can contain the Save method
		if (context.RunObjectSaveMethod())
		{
			return;
		}
 
		Foo instance = (Foo)what;
		context.Save(instance.myValue);
	}
 
	public void Deserialize(Type type, LoadContext context)
	{
		// First we need to create the instance of Foo we want to fill with our data
		Foo instance = new Foo();
 
		// Store the new created instance into the context, so SaveIt knows about the created instance and wont create it anew
		context.CurrentInstance = instance;
 
		// This is needed in case our class we want to deserialize can contain the Load method
		if (context.RunObjectLoadMethod())
		{
			return;
		}
 
		instance.myValue = context.Load<int>(myValue);
	}
}

After the TypeSerializer has been created, you need to store it into a static list of TypeSerializers SaveIt may use:

1
ContextBase.TypeSerializers.Add(new FooSerializer());

ContextBase is the base class from the LoadContext and SaveContext class in the SaveIt namespace.

TableSerializer Classes

Filed under: SaveIt,SaveIT API Reference — mark @ 11:34

Namespace: SaveIt.TableSerializer
Use these to serialize and deserialize the stored data from the Save and LoadContexts.

SaveIt provides some basic TableSerializers, all based upon the BinaryTableSerializer class.
All inhertied classes are able to compress and uncompress the serialized/deserialized data by setting the UseCompression property to true.

Following BinaryTableSerializers exist:

File
Loads and Saves the data to a file specified in the constructor.
Leaving away a file extension delimiter (a simple dot) will add .saveIt as file extension.

PlayerPrefs
Loads and Saves the data to the PlayerPrefs entry with the given name.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using SaveIt;
...
 
// This will load/save the data from/to the file "MySaveGame.dat"
TableSerializer.File tableSerializer = new TableSerializer.File("MySaveGame.dat");
 
// This will load/save the data from/to the PlayerPrefs string entry "SaveData"
TableSerializer.PlayerPrefs tableSerializer = new TableSerializer.PlayerPrefs("SaveData");
...
 
SaveContext saveContext = new SaveContext(tableSerializer);
saveContext.Save(currentLevel, "currentLevel");
saveContext.Save(score, "score");
saveContext.Flush(); // NEVER FORGET THIS!
...
 
LoadContext loadContext = new LoadContext(tableSerializer);
currentLevel = loadContext.Load<int>("currentLevel");
score = loadContext.Save<int>("score");

LoadContext Class

Filed under: SaveIt,SaveIT API Reference — mark @ 11:07

Namespace: SaveIt

LoadContext(ITableSerializer tableSerializer = null, ResourceEntry[] resourceEntries = null)
Parameters:

    tableSerializer [optional] – the TableSerializer which loads from a stream
    resourceEntries [optional] – array of precreated resources to use instead to create it on demand

Creates a new LoadContext instance. When no TableSerializer is provided a default one will be used, which loads from the file: “default.saveIt”.

C#:

LoadContext context = new LoadContext();
LoadContext context = new LoadContext(new TableSerializer.File("SaveItData"));
LoadContext context = new LoadContext(new TableSerializer.File("SaveItData"), myResourceEntries);

bool IsDeferredType(Type type)
Parameters:

    type – the Type to test for

Returns:

    true when the object is a deferred type, false otherwise

Returns wether the given type is a type which needs to be loaded with special means, for example all Components are deferred types. these types need
to be loaded with the Load methods who are providing a callbackMethod or with the WaitForLoad methods.
In most cases you know that without using this method.

C#:

if (context.IsDeferredType(typeof(Foo)))
{
	context.WaitForLoad<Foo>("myFooValue", loadedFoo => myFooValue = loadedFoo);
}
else
{
	myFooValue = context.Load<Foo>("myFooValue");
}

bool IsDeferredValue(string name)
Parameters:

    name – the name of the value in the currrently deserializing object to test for

Returns:

    true when the value is a deferred type, false otherwise

Returns wether the value stored at the given name in the currently serializing object is a type which needs to be loaded with special means, for example all Components are deferred types. these types need
to be loaded with the Load methods who are providing a callbackMethod or with the WaitForLoad methods.
In most cases you know that without using this method.

C#:

if (context.IsDeferredValue("myFooValue"))
{
	context.WaitForLoad<Foo>("myFooValue", loadedFoo => myFooValue = loadedFoo);
}
else
{
	myFooValue = context.Load<Foo>("myFooValue");
}

void Load(Action<object> onLoaded)
void Load<T>(Action<T> onLoaded)
Parameters:

    onLoaded – a callBack to call when the value has been loaded

This loads the next available slot with the generated name: “Slot.” + nextSlotIndex + “]” and calls the callBack onLoaded when finished.
This method is usefull when loading values you know not if these types are deferred or not and you didnt provide any name when you stored it with the SaveContext.

C#:

context.Load(loadedObject =>
{
	myComponent = (MyComponent)loadedObject;
});
context.Load<MyComponent>(loadedComponent =>
{
	myComponent = loadedComponent;
});

Load(string name, Action<object> onLoaded)
Load<T>(string name, Action<T> onLoaded)
Parameters:

    name – the name of the value to load
    onLoaded – a callBack to call when the value has been loaded

This loads value stored at the given name and calls the callBack onLoaded when finished.
This method is usefull when loading values you know not if these types are deferred or not.

C#:

context.Load("healthPoints", loadedValue =>
{
	healthPoints = (int)loadedValue;
});
context.Load<int>("healthPoints", loadedInteger =>
{
	healthPoints = loadedInteger;
});

object Load()
T Load()
Parameters:

    none

Returns:

    the loaded value

This loads the next available slot with the generated name: “Slot.” + nextSlotIndex + “]” and returns the loaded result.

C#:

int healtPoints = (int)context.Load();
int healtPoints = context.Load<int>();

object Load(string name)
T Load(string name)
Parameters:

    name – the name of the value to load

Returns:

    the loaded value

This loads value stored at the given name and returns the loaded result.

C#:

int healtPoints = (int)context.Load("healthPoints");
int healtPoints = context.Load<int>("healthPoints");

void Load(out T target)
Parameters:

    target – the target to which the loaded value should be assigned to

This loads the next available slot with the generated name: “Slot.” + nextSlotIndex + “]” and puts the result into the given target.

C#:

int healtPoints;
context.Load(out healthPoints);

void Load(string name, out T target)
Parameters:

    name – the name of the value to load
    target – the target to which the loaded value should be assigned to

This loads value stored at the given name and puts the result into the given target.

C#:

int healtPoints;
context.Load("healthPoints", out healthPoints);

void WaitForLoad(string name, Action<object> onLoaded)
void WaitForLoad(string name, Action< T > onLoaded)
Parameters:

    name – the name of the value to wait for
    onLoaded – a callBack to call when the value has been loaded

This waits unto the next available slot with the generated name: “Slot.” + nextSlotIndex + “]” has been loaded and calls the callBack onLoaded when finished.
This method is usefull when somwhere else is a Load call and you only want to know when this call has been finished. You want to use it for all deferred types which cant be constructed with a normal new call.

C#:

context.WaitForLoad("someComponent", loadedObject =>
{
	myComponent = (MyComponent)loadedObject;
});
context.WaitForLoad<MyComponent>("someComponent", myBehaviour =>
{
	myComponent = myBehaviour;
});

object LoadToInstance(object instance)
T LoadToInstance(T instance)
Parameters:

    instance – the target instance to load the data to

Returns:

    the instance provided in the parameters

This loads the next available slot with the generated name: “Slot.” + nextSlotIndex + “]” into the given instance. Use this when you already created an instance and want it to be filled with stored data. This is usefull when loading componants, as these are not creatable without using a GameObject.

C#:

context.LoadToInstance(gameObject.transform);

object LoadToInstance(string name, object instance)
T LoadToInstance(string name, T instance)
Parameters:

    name – the name of the value to load
    instance – the target instance to load the data to

Returns:

    the instance provided in the parameters

This loads the value with the given name into the given instance. Use this when you already created an instance and want it to be filled with stored data. This is usefull when loading componants, as these are not creatable without using a GameObject.

C#:

context.LoadToInstance("myTransform", gameObject.transform);

bool Exists(string name)
Parameters:

    name – the name of the value to check for existance

Returns:

    true when the value with the given name exists and false otherwise

This method will check wether a value with the given name exists.

C#:

if (context.Exists("MagicNumber"))
{
	int magicNumber = context.Load("MagicNumber");
}

bool MemberExists(string memberName)
Parameters:

    memberName- the memberName of the value to check for existance

Returns:

    true when the value with the given memberName exists and false otherwise

This method will check wether a value with the given memberName exists.

C#:

if (context.MemberExists("mainTexture"))
{
	context.LoadMember("mainTexture");
}

SaveContext Class

Filed under: SaveIt,SaveIT API Reference — mark @ 08:07

Namespace: SaveIt

SaveContext(ITableSerializer tableSerializer = null, ResourceEntry[] resourceEntries = null)
Parameters:

    tableSerializer [optional] – the TableSerializer which loads and saves from/to a stream
    resourceEntries [optional] – array of precreated resources to use instead to create it on demand

Creates a new SaveContext instance. When no TableSerializer is provided a default one will be used, which saves to the file: “default.saveIt”.

C#:

1
SaveContext context = new SaveContext();
1
SaveContext context = new SaveContext(new TableSerializer.File("SaveItData"));
1
SaveContext context = new SaveContext(new TableSerializer.File("SaveItData"), myResourceEntries);

void SaveMember(string memberName, string name = null)
Parameters:

    memberName- the name of the member of the current serializing object
    name [optional]- the name to store the member

Stores the value of the given member memberName of the currently serializing object at the given name, when no name is provided
a name will be generated: “[member:" + memberName + "]“.
You can only use this method when serializing an object (Custom serializer or Load/Save methods inside the objects class layout).

C#:

1
context.SaveMember("localPosition");
1
context.SaveMember("localPosition", "myPosition");

void Save(T what, string name = null)
Parameters:

    what – the object to save
    name [optional] – the name to store the value what

Stores the given object what with with the given name. When no name is given a name is generated: “[Slot." + currentSlot + "]”
This enables the ability to write Save and Load calls which mirrors themself without worrying about the names.

C#:

1
2
3
context.Save(name); // Name is: [Slot.0]
context.Save(active, "isActive"); // Name is: isActive
context.Save(healthPoints); // Name is: [Slot.1]

void Flush()
Parameters:

    none

Saves all stored objects to the TableSerializer (for example to a File).
You must call this after you stored all your objects!

C#:

1
2
3
context.Save(gameObject.name, "name");
context.Save(42, "magicNumber");
context.Flush();

May 1, 2012

Manapotion

Filed under: Random — mark @ 15:50

Instead of buying a gift for the birthday of my beautiful wife I decided to create one with my bare hands. As inspiration I used a post in reddit, you can look it up here.

 

Here are the results..

 

The whole thing without special effects.

Click

 

A closer lookup to the flakon, a little note here, the image does not reflect the original appearance, the reality is more shiny.

Click

 

Now some images with the first special effect, a red glow (I searched for a blue or white, which appears as light blue due to the blue fluid, but coukld not find any, but I think it works really good as a nice contrast).

Click

Click

Click

The images where taken in a really dark environment so, some details are blurry or too dark in the pictures.

 

Finally an image with a very long exposure time (30 seconds) as the last special effect is only visible in really dark areas. So imagine this image in total darkness with only the light bluish elements in the picture glowing (they glow blue/lightblue).

Click

 

I realized the last glow effect with night active color, NightTec-something, a phosphorescent color which glows blue in the dark (when charged with enough light). My first try was to dissolve the color in water, but the problem with it is that the color will drop to the ground as little particles, looks like fairydust (not the drug) but the water remains muddy.

The first glow effect is a simple red LED.

 

Powered by WordPress