Added player character and step in/out of dialogue in scene 101
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f90db759702e5046be95dd90d35ba28
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Unity.ProBuilder")]
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb4dcd11679b340ee8a7afb51cb0ccfc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+79
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 518e5a76add435648813be98dd71e2f8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+27
@@ -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; }
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8fa221ea996bd7459f869e6d809a95d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
namespace UnityEngine.ProBuilder.KdTree
|
||||
{
|
||||
interface IPriorityQueue<TItem, TPriority>
|
||||
{
|
||||
void Enqueue(TItem item, TPriority priority);
|
||||
|
||||
TItem Dequeue();
|
||||
|
||||
int Count { get; }
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4c7381a66e715734f82749b2e115722c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+669
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13a653f5b84336c45b2c00b570775a87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+86
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 908a5a36f516c3048abadede5920d5d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed05cb2facaa5cc49aab6d1137d15904
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Vendored
+69
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2c22c8685df2d44b943673a11597711
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+69
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 483554fdb1324da4ead26f33de2c9990
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+33
@@ -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);
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2799d938bc097b0478b150b315487a18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+64
@@ -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
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4daa0ba8c6e93d54a9b542d76b235c55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Vendored
+83
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 601f62929862ecb48956dc2dca0a2498
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+125
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+11
@@ -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.
|
||||
+7
@@ -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:
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Unity.ProBuilder.KdTree",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c49da3d3671a1748aea5347c1176d2e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user