Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions External/KdTree/KdTreeLib/KdTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;

namespace UnityEngine.ProBuilder.KdTree
{
Expand All @@ -25,6 +26,7 @@ public DuplicateNodeError()
}

[Serializable]
[DataContract]
class KdTree<TKey, TValue> : IKdTree<TKey, TValue>
{
public KdTree(int dimensions, ITypeMath<TKey> typeMath)
Expand All @@ -40,12 +42,16 @@ public KdTree(int dimensions, ITypeMath<TKey> typeMath, AddDuplicateBehavior add
AddDuplicateBehavior = addDuplicateBehavior;
}

[DataMember]
private int dimensions;

[DataMember]
private ITypeMath<TKey> typeMath = null;

[DataMember]
private KdTreeNode<TKey, TValue> root = null;

[DataMember]
public AddDuplicateBehavior AddDuplicateBehavior { get; private set; }

public bool Add(TKey[] point, TValue value)
Expand Down Expand Up @@ -370,7 +376,8 @@ public KdTreeNode<TKey, TValue>[] RadialSearch(TKey[] center, TKey radius, int c
return neighbourArray;
}

public int Count { get; private set; }
[DataMember]
public int Count { get; private set; }

public bool TryFindValueAt(TKey[] point, out TValue value)
{
Expand Down Expand Up @@ -578,20 +585,22 @@ public void Clear()

public void SaveToFile(string filename)
{
BinaryFormatter formatter = new BinaryFormatter();
var serializer = new DataContractSerializer(typeof(KdTree<TKey, TValue>));
using (FileStream stream = File.Create(filename))
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
{
formatter.Serialize(stream, this);
stream.Flush();
serializer.WriteObject(writer, this);
writer.Flush();
}
}

public static KdTree<TKey, TValue> LoadFromFile(string filename)
{
BinaryFormatter formatter = new BinaryFormatter();
var serializer = new DataContractSerializer(typeof(KdTree<TKey, TValue>));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just wondering how does this work in terms of backward compatibility? For older projects tha thave saved using the old BinaryFormatter, would using DataContractSerializer work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an excellent question, thanks for asking it!

Replacing the BinaryFormatter is indeed a breaking change, or at least DataContractSerializer cannot correctly read data written by the BinaryFormatter. So old projects that have KdTree data saved using BinaryFormatter.Serialize() will not be able to load those files after this change. There are other packages that are facing the same situation, such as Addressables (you can see some of our discussion here in their PR about it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've discussed this a bit within the team (I'm in Scripting Runtime), and have discussed how each team that uses BinaryFormatter will be most well-versed in the needs of their users and package, and so we leave it absolutely to your discretion how you wish to replace it of course. We need to have BinaryFormatter replaced in all packages before we'd turn on CoreCLR (as it is not compatible with CoreCLR), so it will be a blocker for CoreCLR (just sharing in case it's helpful to take into account)

What are your/your team's thoughts?

using (FileStream stream = File.Open(filename, FileMode.Open))
using (var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
{
return (KdTree<TKey, TValue>)formatter.Deserialize(stream);
return (KdTree<TKey, TValue>)serializer.ReadObject(reader);
}

}
Expand Down
7 changes: 7 additions & 0 deletions External/KdTree/KdTreeLib/KdTreeNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace UnityEngine.ProBuilder.KdTree
{
[Serializable]
[DataContract]
class KdTreeNode<TKey, TValue>
{
public KdTreeNode()
Expand All @@ -18,11 +20,16 @@ public KdTreeNode(TKey[] point, TValue value)
Value = value;
}

[DataMember]
public TKey[] Point;
[DataMember]
public TValue Value = default(TValue);
[DataMember]
public List<TValue> Duplicates = null;

[DataMember]
internal KdTreeNode<TKey, TValue> LeftChild = null;
[DataMember]
internal KdTreeNode<TKey, TValue> RightChild = null;

internal KdTreeNode<TKey, TValue> this[int compare]
Expand Down