Code/Core/ApexWorldCache.cs
using System.Collections.Generic;
using System.Linq;
using Sandbox.Spawners;
namespace Sandbox.Core;
public class ApexWorldCache : Component, Component.ExecuteInEditor
{
#region Terrain Cache
private List<Terrain> _cachedTerrains = new();
private bool _terrainCacheDirty = true;
public List<Terrain> GetAllTerrains()
{
EnsureTerrainCache();
return _cachedTerrains;
}
public void InvalidateTerrainCache() => _terrainCacheDirty = true;
private void EnsureTerrainCache()
{
if ( !_terrainCacheDirty ) return;
_cachedTerrains.Clear();
foreach ( var terrain in Scene.GetAllComponents<Terrain>() )
{
if ( terrain.Storage == null ) continue;
_cachedTerrains.Add( terrain );
}
_terrainCacheDirty = false;
}
private BBox GetTerrainBounds( Terrain terrain )
{
var origin = terrain.WorldPosition;
float size = terrain.Storage.TerrainSize;
float height = terrain.Storage.TerrainHeight;
return new BBox(
origin,
origin + new Vector3( size, size, height )
);
}
public List<Terrain> GetTerrainsInBounds( BBox bounds )
{
InvalidateTerrainCache();
EnsureTerrainCache();
return _cachedTerrains
.Where( t => t.IsValid() && GetTerrainBounds( t ).Overlaps( bounds ) )
.ToList();
}
#endregion
#region Spawner Drag Tracking
private const float DragSettleDelay = 0.3f;
private readonly Dictionary<BaseSpawner, Vector3> _spawnerLastPositions = new();
private BaseSpawner _pendingSpawner = null;
private RealTimeSince _timeSinceLastMove;
public void RegisterSpawners( IEnumerable<BaseSpawner> spawners )
{
UnregisterSpawners();
if ( spawners == null ) return;
foreach ( var spawner in spawners )
{
if ( spawner == null ) continue;
_spawnerLastPositions[spawner] = spawner.WorldPosition;
spawner.Transform.OnTransformChanged += () => OnSpawnerMoved( spawner );
}
}
public void UnregisterSpawners()
{
foreach ( var spawner in _spawnerLastPositions.Keys )
{
if ( spawner == null ) continue;
spawner.Transform.OnTransformChanged = null;
}
_spawnerLastPositions.Clear();
_pendingSpawner = null;
}
private void OnSpawnerMoved( BaseSpawner spawner )
{
_pendingSpawner = spawner;
_timeSinceLastMove = 0;
}
protected override void OnUpdate()
{
if ( _pendingSpawner == null ) return;
if ( _timeSinceLastMove > DragSettleDelay )
{
OnSpawnerDropped( _pendingSpawner );
_pendingSpawner = null;
}
}
private void OnSpawnerDropped( BaseSpawner spawner )
{
_spawnerLastPositions[spawner] = spawner.WorldPosition;
ApexWorldManager manager = GameObject.GetComponent<ApexWorldManager>();
if ( manager != null )
{
if ( manager.SmartRebuild )
{
manager.ResetAllTerrainsTextures();
manager.RegenerateAllSpawners();
}
}
}
protected override void OnDisabled()
{
UnregisterSpawners();
}
#endregion
}