Custom type?

Discussion and help for Easy Save 3
outofspace
Posts: 36
Joined: Wed Jul 03, 2013 7:28 am

Custom type?

Post by outofspace »

Hi Joel,

I am using New UIwidget from the asset store and trying to serialize and deserialize a Tree component.

/// <summary>
/// Test Easy Save 3 saving.
/// </summary>
public void TestES3Save()
{
var raw_data = TreeNode<TNT_PlaylistLine>.Serialize(Tree.Nodes);
ES3.Save<List<TreeNodeSerialized<TNT_PlaylistLine>>>("playlists", raw_data, "TntPlaylist.es3");
}

/// <summary>
/// Test Easy Save 3 loading.
/// </summary>
public void TestES3Load()
{
var raw_data = ES3.Load<List<TreeNodeSerialized<TNT_PlaylistLine>>>("playlist","TntPlaylist.es3");
Tree.Nodes = TreeNode<TNT_PlaylistLine>.Deserialize(raw_data);
}

I get these errors:

ES3Type.type is null when trying to create an ES3Type for System.Collections.Generic.List`1[UIWidgets.TreeNodeSerialized`1[UIWidgetsSamples.Shops.TNT_PlaylistLine]].
UnityEngine.Debug:Log(Object)
ES3Internal.ES3TypeMgr:CreateES3Type(Type, Boolean) (at Assets/Plugins/Easy Save 3/Scripts/Types/ES3TypeMgr.cs:99)
ES3Internal.ES3TypeMgr:GetOrCreateES3Type(Type, Boolean) (at Assets/Plugins/Easy Save 3/Scripts/Types/ES3TypeMgr.cs:23)
ES3Writer:Write(String, Object) (at Assets/Plugins/Easy Save 3/Scripts/Writers/ES3Writer.cs:87)
ES3:Save(String, Object, ES3Settings) (at Assets/Plugins/Easy Save 3/Scripts/ES3.cs:40)
ES3:Save(String, Object, String) (at Assets/Plugins/Easy Save 3/Scripts/ES3.cs:51)

---------------
I created UIWidgetsSamples.Shops.TNT_PlaylistLine ES3 type and then then tried to create a TreeNodeSerialized ES3type using your custom type creator but this type was not in the list.

Do you know where I am going wrong?

Cheers
outofspace
Posts: 36
Joined: Wed Jul 03, 2013 7:28 am

Re: Custom type?

Post by outofspace »

Here is the code for the TreeNodeSerialized.

/// <summary>
/// Serialized TreeNode.
/// </summary>
[Serializable]
public class TreeNodeSerialized<TItem>
{
/// <summary>
/// The pause observation.
/// </summary>
[SerializeField]
public bool c;

/// <summary>
/// Is node visible?
/// </summary>
[SerializeField]
public bool IsVisible;

/// <summary>
/// Is node expanded?
/// </summary>
[SerializeField]
public bool IsExpanded;

/// <summary>
/// The item.
/// </summary>
[SerializeField]
public TItem Item;

/// <summary>
/// The sub nodes count.
/// </summary>
public int SubNodesCount;

/// <summary>
/// The index of the first sub node.
/// </summary>
public int FirstSubNodeIndex;

/// <summary>
/// The depth.
/// </summary>
public int Depth;

/// <summary>
/// Initializes a new instance of the class.
/// </summary>
/// <param name="node">Node.</param>
/// <param name="firstSubNodeIndex">Index of first subnode.</param>
public TreeNodeSerialized(TreeNode<TItem> node, int firstSubNodeIndex, int depth)
{
PauseObservation = node.PauseObservation;
IsVisible = node.IsVisible;
IsExpanded = node.IsExpanded;
Item = node.Item;

SubNodesCount = node.Nodes==null ? 0 : node.Nodes.Count;
FirstSubNodeIndex = firstSubNodeIndex;
Depth = depth;
}
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Custom type?

Post by Joel »

Hi there,

The problem is that you're using an external serialiser to get your class as a byte array (or possibly a string?), but then you're still trying to save this byte array to the file with the type List<TreeNodeSerialized<TNT_PlaylistLine>>.

If you change your ES3 lines to use byte[] as the generic parameter instead, this should fix your issue. i.e.
ES3.Save<byte[]>("playlists", raw_data, "TntPlaylist.es3");

var raw_data = ES3.Load<byte[]>("playlist","TntPlaylist.es3");
All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
outofspace
Posts: 36
Joined: Wed Jul 03, 2013 7:28 am

Re: Custom type?

Post by outofspace »

I found the code that does the serializing:

/// <summary>
/// Serialize the specified nodes.
/// </summary>
/// <param name="nodes">Nodes.</param>
public static List<TreeNodeSerialized<TItem>> Serialize(ObservableList<TreeNode<TItem>> nodes)
{
if (nodes==null)
{
return null;
}

var serializedNodes = new List<TreeNodeSerialized<TItem>>();
Serialize(nodes, serializedNodes, 0);

return serializedNodes;
}

protected static List<TreeNodeSerialized<TItem>> Serialize(ObservableList<TreeNode<TItem>> nodes, List<TreeNodeSerialized<TItem>> serializedNodes, int depth)
{
foreach (var node in nodes)
{
serializedNodes.Add(new TreeNodeSerialized<TItem>(node, serializedNodes.Count + 1, depth));
if (node.Nodes!=null)
{
Serialize(node.Nodes, serializedNodes, depth + 1);
}
}
return serializedNodes;
}
outofspace
Posts: 36
Joined: Wed Jul 03, 2013 7:28 am

Re: Custom type?

Post by outofspace »

He has an example of using BinaryFormatter:

/// <summary>
/// The filename.
/// </summary>
[SerializeField]
protected string Filename = "TNTPlaylist.binary";

/// <summary>
/// Test saving with binary serialization.
/// </summary>
public void TestSave()
{
var raw_data = TreeNode<TNT_PlaylistLine>.Serialize(Tree.Nodes);

var stream = File.Create(Filename);
var serializer = new BinaryFormatter();
serializer.Serialize(stream, raw_data);
stream.Close();
}

/// <summary>
/// Test loading with binary serialization.
/// </summary>
public void TestLoad()
{
if (File.Exists(Filename))
{
// binary save
var stream = File.OpenRead(Filename);
var deserializer = new BinaryFormatter();
var raw_data = (List<TreeNodeSerialized<TNT_PlaylistLine>>)deserializer.Deserialize(stream);
stream.Close();

Tree.Nodes = TreeNode<TNT_PlaylistLine>.Deserialize(raw_data);
}
}
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Custom type?

Post by Joel »

Ahh I see, it's strange that they've created a serialise method which doesn't actually serialise the data.

Generic classes aren't currently supported in the Easy Save 3 beta as we're only testing core functionality at the moment. You can however manually add support for them by creating a non-generic sub-class of your generic class, adding support for it in the Types window, and then making two small modifications to the ES3Type it generates.

Here's detailed instructions on how you would do this in your case:

1. Create a non-generic sub-class of TreeNodeSerialized<TNT_PlaylistLine>. This will simply look like this:
public TreeNodeSerializedWrapper : TreeNodeSerialized<TNT_PlaylistLine>
{
    public TreeNodeSerializedWrapper(){}
}
2. Go to Window > Easy Save 3 > Types, find the TreeNodeSerializedWrapper type in the Type list, and then press Select All. This will generate an ES3Type for the class.

3. Open up the ES3Type_TreeNodeSerializedWrapper.cs file created in Assets/Easy Save 3/Types/.

4. Do a Find-and-Replace, replacing (TreeNodeSerliazedWrapper with (TreeNodeSerialized<TNT_PlaylistLine>. Note that it's important that you include the opening bracket I've included in the above terms.

5. You're done. Now your original code should work.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
outofspace
Posts: 36
Joined: Wed Jul 03, 2013 7:28 am

Re: Custom type?

Post by outofspace »

1. Create a non-generic sub-class of TreeNodeSerialized<TNT_PlaylistLine>. This will simply look like this:
public TreeNodeSerializedWrapper : TreeNodeSerialized<TNT_PlaylistLine>
{
public TreeNodeSerializedWrapper(){}
}

Would you create a new unity .cs file with only this class?
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Custom type?

Post by Joel »

You can create a new .cs file, or you can add the class to an existing .cs file, whichever is easiest for you.

Once you've carried out all of the steps you should be able to delete it anyway. It's only used so that we can generate an ES3Type with the correct fields.
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
outofspace
Posts: 36
Joined: Wed Jul 03, 2013 7:28 am

Re: Custom type?

Post by outofspace »

I did this:

public class TreeNodeSerializedWrapper : TreeNodeSerialized<TNT_PlaylistLine>
{
public void TreeNodeSerializedWrapper() { }
}

and got this error:
TreeNodeSerializedWrapper.TreeNodeSerializedWrapper()': member names cannot be the same as their enclosing type
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Custom type?

Post by Joel »

The method inside the class is meant to be:
public TreeNodeSerializedWrapper() { }
Not:
public void TreeNodeSerializedWrapper() { }
.. as it's meant to be the constructor.
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Post Reply