This commit is contained in:
CortexCore
2024-03-31 23:31:00 +08:00
parent e179d2eb53
commit b7b89ee71a
641 changed files with 31286 additions and 22134 deletions

View File

@@ -0,0 +1,10 @@

using UnityEngine;
namespace Quadtree.Items
{
public abstract class GameObjectItem : GameObjectItemBase<GameObjectItem, Node<GameObjectItem>>
{
protected override GameObjectItem This() => this;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3bb93ae6561edaa49a599f7ccf090da1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,152 @@
using UnityEngine;
namespace Quadtree.Items
{
/// <summary>
/// Custom item interface for GameObject quadtree items.
/// </summary>
public abstract class GameObjectItemBase<TItem, TNode> : MonoBehaviour, IItem<TItem, TNode>
where TItem : IItem<TItem, TNode>
where TNode : INode<TItem, TNode>
{
/// <summary>
/// Game object's bounds from last update call.
/// </summary>
private Bounds _lastBounds;
/// <summary>
/// Game object's bounds from last update call.
/// </summary>
private Bounds _safeBounds;
//==========================================================================dd==
// MonoBehaviour METHODS
//==========================================================================dd==
private void Start()
{
Init();
}
private void OnEnable()
{
Init();
}
private void OnDisable()
{
Root = null;
ItemInitialized = false;
ParentNode.Remove(This());
}
private void LateUpdate()
{
var currentBounds = GetBounds();
if (currentBounds != _lastBounds)
{
// the object has moved or changed size
var forceInsertionEvaluation = false;
if (!currentBounds.Intersects(_safeBounds)
|| (currentBounds.size - _lastBounds.size).magnitude > 0)
{
// ...far enough to force re-insertion
forceInsertionEvaluation = true;
_safeBounds = currentBounds;
}
// current object bounds are not the same as last update
// initiate tree update from currently
ParentNode?.Update(This(), forceInsertionEvaluation);
_lastBounds = currentBounds;
}
}
//==========================================================================dd==
// CORE TREE ITEM METHODS
//==========================================================================dd==
/// <summary>
/// <c>True</c> if the item has been initialized.
/// </summary>
protected internal bool ItemInitialized = false;
public IQuadtreeRoot<TItem, TNode> Root { get; set; }
public TNode ParentNode { get; set; }
public abstract Bounds GetBounds();
public void QuadTree_Root_Initialized(IQuadtreeRoot<TItem, TNode> root)
{
Root = root;
if (ItemInitialized)
{
// the item has been initialized before the tree root
root.Insert(This());
}
}
/// <summary>
/// Returns reference to corresponding game object.
/// </summary>
///
/// <returns>Game object instance.</returns>
public abstract GameObject GetGameObject();
/// <summary>
/// Initializes the item instance.
/// </summary>
/// <remarks>
/// This may be called either before or after the initialization of the tree root.
/// </remarks>
protected virtual void Init()
{
// designate item as initialized
ItemInitialized = true;
// set initial last bounds
_lastBounds = GetBounds();
// set initial safe bounds
_safeBounds = _lastBounds;
if (Root == null)
{
if (TryGetComponent(out GameObjectQuadtreeRoot quadtreeRoot) && quadtreeRoot.Initialized)
{
Root = (IQuadtreeRoot<TItem, TNode>)quadtreeRoot;
}
}
if (Root != null)
{
// the tree root has been initialized before the item
Root.Insert(This());
}
}
/// <summary>
/// Overloaded in sub-classes to return correct instance of the item.
/// </summary>
/// <remarks>
/// This method is necessary due to generic typechecking -- <c>this</c> in context of the abstract generic class does not reference TItem itself.
/// </remarks>
///
/// <returns>Instance of the item</returns>
protected abstract TItem This();
/// <summary>
/// Returns unique identifier of the item.
/// </summary>
/// <remarks>
/// It is extremely important to override this method because nodes are using HashSets to store items and the items are changing during the updates and so are the hash codes which can result in program not working properly.
/// </remarks>
///
/// <returns>Unique identifier</returns>
public override int GetHashCode()
{
return GetInstanceID();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 34e0c8684cc1c224a91b831b8c99c968
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
using UnityEngine;
namespace Quadtree.Items
{
/// <summary>
/// Mandatory interface of any quadtree item.
/// </summary>
public interface IItem<TItem, TNode>
where TItem : IItem<TItem, TNode>
where TNode : INode<TItem, TNode>
{
/// <summary>
/// Returns object bounds.
/// </summary>
///
/// <returns>Object box bounds.</returns>
Bounds GetBounds();
/// <summary>
/// Node which currently contains the item.
/// </summary>
TNode ParentNode { get; set; }
/// <summary>
/// Receiver method for broadcasted tree initialization message.
/// </summary>
void QuadTree_Root_Initialized(IQuadtreeRoot<TItem, TNode> root);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1e6be24bac4fd4a409194655d1cf0665
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using UnityEngine;
namespace Quadtree.Items
{
/// <summary>
/// Boundaries of this quadtree item are determined by present <c>UnityEngine.Renderer</c> component.
/// </summary>
[ExecuteInEditMode]
[DisallowMultipleComponent]
[RequireComponent(typeof(Renderer))]
[AddComponentMenu("Spatial partitioning/Quadtree/Items/Renderer-based Item")]
public class RendererItem : GameObjectItem
{
/// <summary>
/// Determines whether the item should be automatically inserted into the tree upon its initialization.
/// </summary>
///
/// <seealso cref="QuadtreeMonoRoot{TItem}.Insert(TItem)"/>
[SerializeField]
protected bool InsertOnInitialization = true;
private Renderer _renderer;
//==========================================================================dd==
// Quadtree ITEM METHODS
//==========================================================================dd==
/// <summary>
/// Finds and locally stores this <c>GameObject</c>'s <c>Renderer</c> component instance.
/// </summary>
protected override void Init()
{
// load game object renderer component
_renderer = GetComponent<Renderer>();
base.Init();
}
public override Bounds GetBounds()
{
return _renderer.bounds;
}
public override GameObject GetGameObject() => gameObject;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b92b133d7eeb95b4d95b27cf8ef679b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: