Added player character and step in/out of dialogue in scene 101

This commit is contained in:
2026-08-15 15:22:47 +02:00
parent a42f25d5fa
commit 38ba2b0eff
2019 changed files with 181227 additions and 265 deletions
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7f90db759702e5046be95dd90d35ba28
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("Unity.ProBuilder")]
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bb4dcd11679b340ee8a7afb51cb0ccfc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,79 @@
namespace UnityEngine.ProBuilder.KdTree
{
struct HyperRect<T>
{
private T[] minPoint;
public T[] MinPoint
{
get
{
return minPoint;
}
set
{
minPoint = new T[value.Length];
value.CopyTo(minPoint, 0);
}
}
private T[] maxPoint;
public T[] MaxPoint
{
get
{
return maxPoint;
}
set
{
maxPoint = new T[value.Length];
value.CopyTo(maxPoint, 0);
}
}
public static HyperRect<T> Infinite(int dimensions, ITypeMath<T> math)
{
var rect = new HyperRect<T>();
rect.MinPoint = new T[dimensions];
rect.MaxPoint = new T[dimensions];
for (var dimension = 0; dimension < dimensions; dimension++)
{
rect.MinPoint[dimension] = math.NegativeInfinity;
rect.MaxPoint[dimension] = math.PositiveInfinity;
}
return rect;
}
public T[] GetClosestPoint(T[] toPoint, ITypeMath<T> math)
{
T[] closest = new T[toPoint.Length];
for (var dimension = 0; dimension < toPoint.Length; dimension++)
{
if (math.Compare(minPoint[dimension], toPoint[dimension]) > 0)
{
closest[dimension] = minPoint[dimension];
}
else if (math.Compare(maxPoint[dimension], toPoint[dimension]) < 0)
{
closest[dimension] = maxPoint[dimension];
}
else
// Point is within rectangle, at least on this dimension
closest[dimension] = toPoint[dimension];
}
return closest;
}
public HyperRect<T> Clone()
{
var rect = new HyperRect<T>();
rect.MinPoint = MinPoint;
rect.MaxPoint = MaxPoint;
return rect;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 518e5a76add435648813be98dd71e2f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,27 @@
using System.Collections.Generic;
namespace UnityEngine.ProBuilder.KdTree
{
interface IKdTree<TKey, TValue> : IEnumerable<KdTreeNode<TKey, TValue>>
{
bool Add(TKey[] point, TValue value);
bool TryFindValueAt(TKey[] point, out TValue value);
TValue FindValueAt(TKey[] point);
bool TryFindValue(TValue value, out TKey[] point);
TKey[] FindValue(TValue value);
KdTreeNode<TKey, TValue>[] RadialSearch(TKey[] center, TKey radius, int count);
void RemoveAt(TKey[] point);
void Clear();
KdTreeNode<TKey, TValue>[] GetNearestNeighbours(TKey[] point, int count = int.MaxValue);
int Count { get; }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e8fa221ea996bd7459f869e6d809a95d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
namespace UnityEngine.ProBuilder.KdTree
{
interface IPriorityQueue<TItem, TPriority>
{
void Enqueue(TItem item, TPriority priority);
TItem Dequeue();
int Count { get; }
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4c7381a66e715734f82749b2e115722c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,669 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
namespace UnityEngine.ProBuilder.KdTree
{
enum AddDuplicateBehavior
{
Skip,
Error,
Update,
Collect
}
class DuplicateNodeError : Exception
{
public DuplicateNodeError()
: base("Cannot Add Node With Duplicate Coordinates")
{
}
}
[Serializable]
[DataContract]
class KdTree<TKey, TValue> : IKdTree<TKey, TValue>
{
public KdTree(int dimensions, ITypeMath<TKey> typeMath)
{
this.dimensions = dimensions;
this.typeMath = typeMath;
Count = 0;
}
public KdTree(int dimensions, ITypeMath<TKey> typeMath, AddDuplicateBehavior addDuplicateBehavior)
: this(dimensions, typeMath)
{
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)
{
var nodeToAdd = new KdTreeNode<TKey, TValue>(point, value);
if (root == null)
{
root = new KdTreeNode<TKey, TValue>(point, value);
}
else
{
int dimension = -1;
KdTreeNode<TKey, TValue> parent = root;
do
{
// Increment the dimension we're searching in
dimension = (dimension + 1) % dimensions;
// Does the node we're adding have the same hyperpoint as this node?
if (typeMath.AreEqual(point, parent.Point))
{
switch (AddDuplicateBehavior)
{
case AddDuplicateBehavior.Skip:
return false;
case AddDuplicateBehavior.Error:
throw new DuplicateNodeError();
case AddDuplicateBehavior.Update:
parent.Value = value;
break;
case AddDuplicateBehavior.Collect:
parent.AddDuplicate(value);
return false;
default:
// Should never happen
throw new Exception("Unexpected AddDuplicateBehavior");
}
}
// Which side does this node sit under in relation to it's parent at this level?
int compare = typeMath.Compare(point[dimension], parent.Point[dimension]);
if (parent[compare] == null)
{
parent[compare] = nodeToAdd;
break;
}
else
{
parent = parent[compare];
}
}
while (true);
}
Count++;
return true;
}
private void ReadChildNodes(KdTreeNode<TKey, TValue> removedNode)
{
if (removedNode.IsLeaf)
return;
// The folllowing code might seem a little redundant but we're using
// 2 queues so we can add the child nodes back in, in (more or less)
// the same order they were added in the first place
var nodesToReadd = new Queue<KdTreeNode<TKey, TValue>>();
var nodesToReaddQueue = new Queue<KdTreeNode<TKey, TValue>>();
if (removedNode.LeftChild != null)
nodesToReaddQueue.Enqueue(removedNode.LeftChild);
if (removedNode.RightChild != null)
nodesToReaddQueue.Enqueue(removedNode.RightChild);
while (nodesToReaddQueue.Count > 0)
{
var nodeToReadd = nodesToReaddQueue.Dequeue();
nodesToReadd.Enqueue(nodeToReadd);
for (int side = -1; side <= 1; side += 2)
{
if (nodeToReadd[side] != null)
{
nodesToReaddQueue.Enqueue(nodeToReadd[side]);
nodeToReadd[side] = null;
}
}
}
while (nodesToReadd.Count > 0)
{
var nodeToReadd = nodesToReadd.Dequeue();
Count--;
Add(nodeToReadd.Point, nodeToReadd.Value);
}
}
public void RemoveAt(TKey[] point)
{
// Is tree empty?
if (root == null)
return;
KdTreeNode<TKey, TValue> node;
if (typeMath.AreEqual(point, root.Point))
{
node = root;
root = null;
Count--;
ReadChildNodes(node);
return;
}
node = root;
int dimension = -1;
do
{
dimension = (dimension + 1) % dimensions;
int compare = typeMath.Compare(point[dimension], node.Point[dimension]);
if (node[compare] == null)
// Can't find node
return;
if (typeMath.AreEqual(point, node[compare].Point))
{
var nodeToRemove = node[compare];
node[compare] = null;
Count--;
ReadChildNodes(nodeToRemove);
}
else
node = node[compare];
}
while (node != null);
}
public KdTreeNode<TKey, TValue>[] GetNearestNeighbours(TKey[] point, int count)
{
if (count > Count)
count = Count;
if (count < 0)
{
throw new ArgumentException("Number of neighbors cannot be negative");
}
if (count == 0)
return new KdTreeNode<TKey, TValue>[0];
var nearestNeighbours = new NearestNeighbourList<KdTreeNode<TKey, TValue>, TKey>(count, typeMath);
var rect = HyperRect<TKey>.Infinite(dimensions, typeMath);
AddNearestNeighbours(root, point, rect, 0, nearestNeighbours, typeMath.MaxValue);
count = nearestNeighbours.Count;
var neighbourArray = new KdTreeNode<TKey, TValue>[count];
for (var index = 0; index < count; index++)
neighbourArray[count - index - 1] = nearestNeighbours.RemoveFurtherest();
return neighbourArray;
}
/*
* 1. Search for the target
*
* 1.1 Start by splitting the specified hyper rect
* on the specified node's point along the current
* dimension so that we end up with 2 sub hyper rects
* (current dimension = depth % dimensions)
*
* 1.2 Check what sub rectangle the the target point resides in
* under the current dimension
*
* 1.3 Set that rect to the nearer rect and also the corresponding
* child node to the nearest rect and node and the other rect
* and child node to the further rect and child node (for use later)
*
* 1.4 Travel into the nearer rect and node by calling function
* recursively with nearer rect and node and incrementing
* the depth
*
* 2. Add leaf to list of nearest neighbours
*
* 3. Walk back up tree and at each level:
*
* 3.1 Add node to nearest neighbours if
* we haven't filled our nearest neighbour
* list yet or if it has a distance to target less
* than any of the distances in our current nearest
* neighbours.
*
* 3.2 If there is any point in the further rectangle that is closer to
* the target than our furtherest nearest neighbour then travel into
* that rect and node
*
* That's it, when it finally finishes traversing the branches
* it needs to we'll have our list!
*/
private void AddNearestNeighbours(
KdTreeNode<TKey, TValue> node,
TKey[] target,
HyperRect<TKey> rect,
int depth,
NearestNeighbourList<KdTreeNode<TKey, TValue>, TKey> nearestNeighbours,
TKey maxSearchRadiusSquared)
{
if (node == null)
return;
// Work out the current dimension
int dimension = depth % dimensions;
// Split our hyper-rect into 2 sub rects along the current
// node's point on the current dimension
var leftRect = rect.Clone();
leftRect.MaxPoint[dimension] = node.Point[dimension];
var rightRect = rect.Clone();
rightRect.MinPoint[dimension] = node.Point[dimension];
// Which side does the target reside in?
int compare = typeMath.Compare(target[dimension], node.Point[dimension]);
var nearerRect = compare <= 0 ? leftRect : rightRect;
var furtherRect = compare <= 0 ? rightRect : leftRect;
var nearerNode = compare <= 0 ? node.LeftChild : node.RightChild;
var furtherNode = compare <= 0 ? node.RightChild : node.LeftChild;
// Let's walk down into the nearer branch
if (nearerNode != null)
{
AddNearestNeighbours(
nearerNode,
target,
nearerRect,
depth + 1,
nearestNeighbours,
maxSearchRadiusSquared);
}
TKey distanceSquaredToTarget;
// Walk down into the further branch but only if our capacity hasn't been reached
// OR if there's a region in the further rect that's closer to the target than our
// current furtherest nearest neighbour
TKey[] closestPointInFurtherRect = furtherRect.GetClosestPoint(target, typeMath);
distanceSquaredToTarget = typeMath.DistanceSquaredBetweenPoints(closestPointInFurtherRect, target);
if (typeMath.Compare(distanceSquaredToTarget, maxSearchRadiusSquared) <= 0)
{
if (nearestNeighbours.IsCapacityReached)
{
if (typeMath.Compare(distanceSquaredToTarget, nearestNeighbours.GetFurtherestDistance()) < 0)
AddNearestNeighbours(
furtherNode,
target,
furtherRect,
depth + 1,
nearestNeighbours,
maxSearchRadiusSquared);
}
else
{
AddNearestNeighbours(
furtherNode,
target,
furtherRect,
depth + 1,
nearestNeighbours,
maxSearchRadiusSquared);
}
}
// Try to add the current node to our nearest neighbours list
distanceSquaredToTarget = typeMath.DistanceSquaredBetweenPoints(node.Point, target);
if (typeMath.Compare(distanceSquaredToTarget, maxSearchRadiusSquared) <= 0)
nearestNeighbours.Add(node, distanceSquaredToTarget);
}
public KdTreeNode<TKey, TValue>[] RadialSearch(TKey[] center, TKey radius, int count)
{
var nearestNeighbours = new NearestNeighbourList<KdTreeNode<TKey, TValue>, TKey>(count, typeMath);
AddNearestNeighbours(
root,
center,
HyperRect<TKey>.Infinite(dimensions, typeMath),
0,
nearestNeighbours,
typeMath.Multiply(radius, radius));
count = nearestNeighbours.Count;
var neighbourArray = new KdTreeNode<TKey, TValue>[count];
for (var index = 0; index < count; index++)
neighbourArray[count - index - 1] = nearestNeighbours.RemoveFurtherest();
return neighbourArray;
}
[DataMember]
public int Count { get; private set; }
public bool TryFindValueAt(TKey[] point, out TValue value)
{
var parent = root;
int dimension = -1;
do
{
if (parent == null)
{
value = default(TValue);
return false;
}
else if (typeMath.AreEqual(point, parent.Point))
{
value = parent.Value;
return true;
}
// Keep searching
dimension = (dimension + 1) % dimensions;
int compare = typeMath.Compare(point[dimension], parent.Point[dimension]);
parent = parent[compare];
}
while (true);
}
public TValue FindValueAt(TKey[] point)
{
TValue value;
if (TryFindValueAt(point, out value))
return value;
else
return default(TValue);
}
public bool TryFindValue(TValue value, out TKey[] point)
{
if (root == null)
{
point = null;
return false;
}
// First-in, First-out list of nodes to search
var nodesToSearch = new Queue<KdTreeNode<TKey, TValue>>();
nodesToSearch.Enqueue(root);
while (nodesToSearch.Count > 0)
{
var nodeToSearch = nodesToSearch.Dequeue();
if (nodeToSearch.Value.Equals(value))
{
point = nodeToSearch.Point;
return true;
}
else
{
for (int side = -1; side <= 1; side += 2)
{
var childNode = nodeToSearch[side];
if (childNode != null)
nodesToSearch.Enqueue(childNode);
}
}
}
point = null;
return false;
}
public TKey[] FindValue(TValue value)
{
TKey[] point;
if (TryFindValue(value, out point))
return point;
else
return null;
}
private void AddNodeToStringBuilder(KdTreeNode<TKey, TValue> node, StringBuilder sb, int depth)
{
sb.AppendLine(node.ToString());
for (var side = -1; side <= 1; side += 2)
{
for (var index = 0; index <= depth; index++)
sb.Append("\t");
sb.Append(side == -1 ? "L " : "R ");
if (node[side] == null)
sb.AppendLine("");
else
AddNodeToStringBuilder(node[side], sb, depth + 1);
}
}
public override string ToString()
{
if (root == null)
return "";
var sb = new StringBuilder();
AddNodeToStringBuilder(root, sb, 0);
return sb.ToString();
}
private void AddNodesToList(KdTreeNode<TKey, TValue> node, List<KdTreeNode<TKey, TValue>> nodes)
{
if (node == null)
return;
nodes.Add(node);
for (var side = -1; side <= 1; side += 2)
{
if (node[side] != null)
{
AddNodesToList(node[side], nodes);
node[side] = null;
}
}
}
private void SortNodesArray(KdTreeNode<TKey, TValue>[] nodes, int byDimension, int fromIndex, int toIndex)
{
for (var index = fromIndex + 1; index <= toIndex; index++)
{
var newIndex = index;
while (true)
{
var a = nodes[newIndex - 1];
var b = nodes[newIndex];
if (typeMath.Compare(b.Point[byDimension], a.Point[byDimension]) < 0)
{
nodes[newIndex - 1] = b;
nodes[newIndex] = a;
}
else
break;
}
}
}
private void AddNodesBalanced(KdTreeNode<TKey, TValue>[] nodes, int byDimension, int fromIndex, int toIndex)
{
if (fromIndex == toIndex)
{
Add(nodes[fromIndex].Point, nodes[fromIndex].Value);
nodes[fromIndex] = null;
return;
}
// Sort the array from the fromIndex to the toIndex
SortNodesArray(nodes, byDimension, fromIndex, toIndex);
// Find the splitting point
int midIndex = fromIndex + (int)System.Math.Round((toIndex + 1 - fromIndex) / 2f) - 1;
// Add the splitting point
Add(nodes[midIndex].Point, nodes[midIndex].Value);
nodes[midIndex] = null;
// Recurse
int nextDimension = (byDimension + 1) % dimensions;
if (fromIndex < midIndex)
AddNodesBalanced(nodes, nextDimension, fromIndex, midIndex - 1);
if (toIndex > midIndex)
AddNodesBalanced(nodes, nextDimension, midIndex + 1, toIndex);
}
public void Balance()
{
var nodeList = new List<KdTreeNode<TKey, TValue>>();
AddNodesToList(root, nodeList);
Clear();
AddNodesBalanced(nodeList.ToArray(), 0, 0, nodeList.Count - 1);
}
private void RemoveChildNodes(KdTreeNode<TKey, TValue> node)
{
for (var side = -1; side <= 1; side += 2)
{
if (node[side] != null)
{
RemoveChildNodes(node[side]);
node[side] = null;
}
}
}
public void Clear()
{
if (root != null)
RemoveChildNodes(root);
}
public void SaveToFile(string filename)
{
var serializer = new DataContractSerializer(typeof(KdTree<TKey, TValue>));
using (FileStream stream = File.Create(filename))
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream))
{
serializer.WriteObject(writer, this);
writer.Flush();
}
}
public static KdTree<TKey, TValue> LoadFromFile(string filename)
{
var serializer = new DataContractSerializer(typeof(KdTree<TKey, TValue>));
using (FileStream stream = File.Open(filename, FileMode.Open))
using (var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
{
return (KdTree<TKey, TValue>)serializer.ReadObject(reader);
}
}
public IEnumerator<KdTreeNode<TKey, TValue>> GetEnumerator()
{
var left = new Stack<KdTreeNode<TKey, TValue>>();
var right = new Stack<KdTreeNode<TKey, TValue>>();
Action<KdTreeNode<TKey, TValue>> addLeft = node =>
{
if (node.LeftChild != null)
{
left.Push(node.LeftChild);
}
};
Action<KdTreeNode<TKey, TValue>> addRight = node =>
{
if (node.RightChild != null)
{
right.Push(node.RightChild);
}
};
if (root != null)
{
yield return root;
addLeft(root);
addRight(root);
while (true)
{
if (left.Any())
{
var item = left.Pop();
addLeft(item);
addRight(item);
yield return item;
}
else if (right.Any())
{
var item = right.Pop();
addLeft(item);
addRight(item);
yield return item;
}
else
{
break;
}
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 13a653f5b84336c45b2c00b570775a87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,86 @@
using System;
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()
{
}
public KdTreeNode(TKey[] point, TValue value)
{
Point = point;
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]
{
get
{
if (compare <= 0)
return LeftChild;
else
return RightChild;
}
set
{
if (compare <= 0)
LeftChild = value;
else
RightChild = value;
}
}
public bool IsLeaf
{
get
{
return (LeftChild == null) && (RightChild == null);
}
}
public void AddDuplicate(TValue value)
{
if (Duplicates == null)
Duplicates = new List<TValue>() { value };
else
Duplicates.Add(value);
}
public override string ToString()
{
var sb = new StringBuilder();
for (var dimension = 0; dimension < Point.Length; dimension++)
{
sb.Append(Point[dimension].ToString());
}
if (Value == null)
sb.Append("null");
else
sb.Append(Value.ToString());
return sb.ToString();
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 908a5a36f516c3048abadede5920d5d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ed05cb2facaa5cc49aab6d1137d15904
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,69 @@
using System;
namespace UnityEngine.ProBuilder.KdTree.Math
{
[Serializable]
class DoubleMath : TypeMath<double>
{
public override int Compare(double a, double b)
{
return a.CompareTo(b);
}
public override bool AreEqual(double a, double b)
{
return a == b;
}
public override double MinValue
{
get { return double.MinValue; }
}
public override double MaxValue
{
get { return double.MaxValue; }
}
public override double Zero
{
get { return 0; }
}
public override double NegativeInfinity { get { return double.NegativeInfinity; } }
public override double PositiveInfinity { get { return double.PositiveInfinity; } }
public override double Add(double a, double b)
{
return a + b;
}
public override double Subtract(double a, double b)
{
return a - b;
}
public override double Multiply(double a, double b)
{
return a * b;
}
public override double DistanceSquaredBetweenPoints(double[] a, double[] b)
{
double distance = Zero;
int dimensions = a.Length;
// Return the absolute distance bewteen 2 hyper points
for (var dimension = 0; dimension < dimensions; dimension++)
{
double distOnThisAxis = Subtract(a[dimension], b[dimension]);
double distOnThisAxisSquared = Multiply(distOnThisAxis, distOnThisAxis);
distance = Add(distance, distOnThisAxisSquared);
}
return distance;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a2c22c8685df2d44b943673a11597711
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,69 @@
using System;
namespace UnityEngine.ProBuilder.KdTree.Math
{
[Serializable]
class FloatMath : TypeMath<float>
{
public override int Compare(float a, float b)
{
return a.CompareTo(b);
}
public override bool AreEqual(float a, float b)
{
return a == b;
}
public override float MinValue
{
get { return float.MinValue; }
}
public override float MaxValue
{
get { return float.MaxValue; }
}
public override float Zero
{
get { return 0; }
}
public override float NegativeInfinity { get { return float.NegativeInfinity; } }
public override float PositiveInfinity { get { return float.PositiveInfinity; } }
public override float Add(float a, float b)
{
return a + b;
}
public override float Subtract(float a, float b)
{
return a - b;
}
public override float Multiply(float a, float b)
{
return a * b;
}
public override float DistanceSquaredBetweenPoints(float[] a, float[] b)
{
float distance = Zero;
int dimensions = a.Length;
// Return the absolute distance bewteen 2 hyper points
for (var dimension = 0; dimension < dimensions; dimension++)
{
float distOnThisAxis = Subtract(a[dimension], b[dimension]);
float distOnThisAxisSquared = Multiply(distOnThisAxis, distOnThisAxis);
distance = Add(distance, distOnThisAxisSquared);
}
return distance;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 483554fdb1324da4ead26f33de2c9990
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,33 @@
namespace UnityEngine.ProBuilder.KdTree
{
interface ITypeMath<T>
{
int Compare(T a, T b);
T MinValue { get; }
T MaxValue { get; }
T Min(T a, T b);
T Max(T a, T b);
bool AreEqual(T a, T b);
bool AreEqual(T[] a, T[] b);
T Add(T a, T b);
T Subtract(T a, T b);
T Multiply(T a, T b);
T Zero { get; }
T NegativeInfinity { get; }
T PositiveInfinity { get; }
T DistanceSquaredBetweenPoints(T[] a, T[] b);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2799d938bc097b0478b150b315487a18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,64 @@
using System;
namespace UnityEngine.ProBuilder.KdTree.Math
{
[Serializable]
abstract class TypeMath<T> : ITypeMath<T>
{
#region ITypeMath<T> members
public abstract int Compare(T a, T b);
public abstract bool AreEqual(T a, T b);
public virtual bool AreEqual(T[] a, T[] b)
{
if (a.Length != b.Length)
return false;
for (var index = 0; index < a.Length; index++)
{
if (!AreEqual(a[index], b[index]))
return false;
}
return true;
}
public abstract T MinValue { get; }
public abstract T MaxValue { get; }
public T Min(T a, T b)
{
if (Compare(a, b) < 0)
return a;
else
return b;
}
public T Max(T a, T b)
{
if (Compare(a, b) > 0)
return a;
else
return b;
}
public abstract T Zero { get; }
public abstract T NegativeInfinity { get; }
public abstract T PositiveInfinity { get; }
public abstract T Add(T a, T b);
public abstract T Subtract(T a, T b);
public abstract T Multiply(T a, T b);
public abstract T DistanceSquaredBetweenPoints(T[] a, T[] b);
#endregion
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4daa0ba8c6e93d54a9b542d76b235c55
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,83 @@
using System;
namespace UnityEngine.ProBuilder.KdTree
{
interface INearestNeighbourList<TItem, TDistance>
{
bool Add(TItem item, TDistance distance);
TItem GetFurtherest();
TItem RemoveFurtherest();
int MaxCapacity { get; }
int Count { get; }
}
class NearestNeighbourList<TItem, TDistance> : INearestNeighbourList<TItem, TDistance>
{
public NearestNeighbourList(int maxCapacity, ITypeMath<TDistance> distanceMath)
{
this.maxCapacity = maxCapacity;
this.distanceMath = distanceMath;
queue = new PriorityQueue<TItem, TDistance>(maxCapacity, distanceMath);
}
private PriorityQueue<TItem, TDistance> queue;
private ITypeMath<TDistance> distanceMath;
private int maxCapacity;
public int MaxCapacity { get { return maxCapacity; } }
public int Count { get { return queue.Count; } }
public bool Add(TItem item, TDistance distance)
{
if (queue.Count >= maxCapacity)
{
// If the distance of this item is less than the distance of the last item
// in our neighbour list then pop that neighbour off and push this one on
// otherwise don't even bother adding this item
if (distanceMath.Compare(distance, queue.GetHighestPriority()) < 0)
{
queue.Dequeue();
queue.Enqueue(item, distance);
return true;
}
else
return false;
}
else
{
queue.Enqueue(item, distance);
return true;
}
}
public TItem GetFurtherest()
{
if (Count == 0)
throw new Exception("List is empty");
else
return queue.GetHighest();
}
public TDistance GetFurtherestDistance()
{
if (Count == 0)
throw new Exception("List is empty");
else
return queue.GetHighestPriority();
}
public TItem RemoveFurtherest()
{
return queue.Dequeue();
}
public bool IsCapacityReached
{
get { return Count == MaxCapacity; }
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 601f62929862ecb48956dc2dca0a2498
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,125 @@
using System;
namespace UnityEngine.ProBuilder.KdTree
{
struct ItemPriority<TItem, TPriority>
{
public TItem Item;
public TPriority Priority;
}
class PriorityQueue<TItem, TPriority> : IPriorityQueue<TItem, TPriority>
{
public PriorityQueue(int capacity, ITypeMath<TPriority> priorityMath)
{
if (capacity <= 0)
throw new ArgumentException("Capacity must be greater than zero");
this.capacity = capacity;
queue = new ItemPriority<TItem, TPriority>[capacity];
this.priorityMath = priorityMath;
}
private ITypeMath<TPriority> priorityMath;
private ItemPriority<TItem, TPriority>[] queue;
private int capacity;
private int count;
public int Count { get { return count; } }
// Try to avoid unnecessary slow memory reallocations by creating your queue with an ample capacity
private void ExpandCapacity()
{
// Double our capacity
capacity *= 2;
// Create a new queue
var newQueue = new ItemPriority<TItem, TPriority>[capacity];
// Copy the contents of the original queue to the new one
Array.Copy(queue, newQueue, queue.Length);
// Copy the new queue over the original one
queue = newQueue;
}
public void Enqueue(TItem item, TPriority priority)
{
if (++count > capacity)
ExpandCapacity();
int newItemIndex = count - 1;
queue[newItemIndex] = new ItemPriority<TItem, TPriority> { Item = item, Priority = priority };
ReorderItem(newItemIndex, -1);
}
public TItem Dequeue()
{
TItem item = queue[0].Item;
queue[0].Item = default(TItem);
queue[0].Priority = priorityMath.MinValue;
ReorderItem(0, 1);
count--;
return item;
}
private void ReorderItem(int index, int direction)
{
if ((direction != -1) && (direction != 1))
throw new ArgumentException("Invalid Direction");
var item = queue[index];
int nextIndex = index + direction;
while ((nextIndex >= 0) && (nextIndex < count))
{
var next = queue[nextIndex];
int compare = priorityMath.Compare(item.Priority, next.Priority);
// If we're moving up and our priority is higher than the next priority then swap
// Or if we're moving down and our priority is lower than the next priority then swap
if (
((direction == -1) && (compare > 0))
||
((direction == 1) && (compare < 0))
)
{
queue[index] = next;
queue[nextIndex] = item;
index += direction;
nextIndex += direction;
}
else
break;
}
}
public TItem GetHighest()
{
if (count == 0)
throw new Exception("Queue is empty");
else
return queue[0].Item;
}
public TPriority GetHighestPriority()
{
if (count == 0)
throw new Exception("Queue is empty");
else
return queue[0].Priority;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d9ed04c4f3db58d488f75533eee62283
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 codeandcats
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 16add6facd81da34caaa1fc21522be87
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,11 @@
KdTree
======
A fast, generic, multi-dimensional Binary Search Tree written in C#
Forked from [codeandcats KdTree](https://github.com/codeandcats/KdTree).
## Changes from KdTree
This branch is modified to compile for .NET Framework 3.5, and removes the non-MIT licensed GeoUtils class.
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 348af47767ff3b44cbd7a045bba8a65c
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,12 @@
{
"name": "Unity.ProBuilder.KdTree",
"references": [],
"optionalUnityReferences": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": false,
"defineConstraints": []
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1c49da3d3671a1748aea5347c1176d2e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: