2020-03-23 02:10:28 +00:00
using System ;
2019-12-05 22:59:55 +00:00
using System.Collections.Generic ;
2020-03-19 22:44:04 +00:00
using System.Runtime.CompilerServices ;
2019-12-05 22:59:55 +00:00
namespace Encompass
{
internal abstract class TypedComponentStore
{
public abstract int Count { get ; }
2019-12-24 02:45:49 +00:00
public abstract bool Has ( int entity ) ;
public abstract bool Remove ( int entity , int priority ) ;
public abstract void ForceRemove ( int entity ) ;
2019-12-05 22:59:55 +00:00
public abstract void Clear ( ) ;
2019-12-30 03:43:05 +00:00
public abstract void ClearPriorities ( ) ;
2019-12-05 22:59:55 +00:00
}
2020-03-22 05:19:31 +00:00
internal class TypedComponentStore < TComponent > : TypedComponentStore where TComponent : struct
2019-12-05 22:59:55 +00:00
{
2020-03-23 00:03:18 +00:00
private int _nextID = 0 ;
private readonly Dictionary < int , int > _entityIDToStorageIndex = new Dictionary < int , int > ( 128 ) ;
private readonly Dictionary < int , int > _priorities = new Dictionary < int , int > ( 128 ) ;
2020-03-23 02:10:28 +00:00
private Entity [ ] _storageIndexToEntities = new Entity [ 128 ] ;
2020-03-23 00:03:18 +00:00
private TComponent [ ] _components = new TComponent [ 128 ] ;
2019-12-05 22:59:55 +00:00
2020-03-23 00:03:18 +00:00
public override int Count { get = > _entityIDToStorageIndex . Count ; }
2019-12-05 22:59:55 +00:00
2020-03-22 05:19:31 +00:00
public ref TComponent Get ( int entityID )
2019-12-05 22:59:55 +00:00
{
2020-03-23 00:03:18 +00:00
if ( ! _entityIDToStorageIndex . ContainsKey ( entityID ) ) { throw new Exceptions . NoComponentOfTypeOnEntityException ( "No component of type {0} exists on Entity with ID {1}" , typeof ( TComponent ) , entityID ) ; }
return ref _components [ _entityIDToStorageIndex [ entityID ] ] ;
2019-12-05 22:59:55 +00:00
}
2020-03-23 02:10:28 +00:00
public ref TComponent Singular ( )
{
return ref _components [ 0 ] ;
}
public ref Entity SingularEntity ( )
{
return ref _storageIndexToEntities [ 0 ] ;
}
2020-03-22 05:19:31 +00:00
public void Set ( int entityID , in TComponent component )
2019-12-05 22:59:55 +00:00
{
2020-03-19 22:44:04 +00:00
InternalSet ( entityID , component ) ;
2019-12-05 22:59:55 +00:00
}
2020-03-22 05:19:31 +00:00
public bool Set ( int entityID , in TComponent component , int priority )
2019-12-05 22:59:55 +00:00
{
2020-03-22 05:53:05 +00:00
if ( ! _priorities . ContainsKey ( entityID ) | | priority < = _priorities [ entityID ] ) // if priorities are equal that means it's the same engine
2019-12-24 02:45:49 +00:00
{
2020-03-19 22:44:04 +00:00
InternalSet ( entityID , component ) ;
2020-03-20 07:09:57 +00:00
_priorities [ entityID ] = priority ;
2019-12-05 22:59:55 +00:00
return true ;
}
return false ;
}
2020-03-22 05:53:05 +00:00
private void InternalSet ( int entityID , in TComponent component )
2020-03-19 22:44:04 +00:00
{
2020-03-23 00:03:18 +00:00
if ( ! _entityIDToStorageIndex . ContainsKey ( entityID ) )
2020-03-20 00:26:22 +00:00
{
2020-03-23 00:03:18 +00:00
var index = _nextID + + ;
if ( index > = _components . Length )
{
System . Array . Resize ( ref _components , _components . Length * 2 ) ;
2020-03-23 02:10:28 +00:00
System . Array . Resize ( ref _storageIndexToEntities , _storageIndexToEntities . Length * 2 ) ;
2020-03-23 00:03:18 +00:00
}
_entityIDToStorageIndex [ entityID ] = index ;
2020-03-23 02:10:28 +00:00
_storageIndexToEntities [ index ] = new Entity ( entityID ) ;
2020-03-20 00:26:22 +00:00
}
2020-03-23 00:03:18 +00:00
_components [ _entityIDToStorageIndex [ entityID ] ] = component ;
2020-03-19 22:44:04 +00:00
}
2019-12-24 02:45:49 +00:00
public override bool Remove ( int entityID , int priority )
2019-12-24 02:01:49 +00:00
{
2020-03-22 05:53:05 +00:00
if ( ! _priorities . ContainsKey ( entityID ) | | priority < = _priorities [ entityID ] ) // if priorities are equal that means it's the same engine
2019-12-24 02:01:49 +00:00
{
2020-03-20 07:09:57 +00:00
_priorities [ entityID ] = priority ;
2020-03-20 09:28:10 +00:00
ForceRemove ( entityID ) ;
2019-12-24 02:01:49 +00:00
return true ;
}
return false ;
}
2019-12-24 02:45:49 +00:00
public override void ForceRemove ( int entityID )
2019-12-24 02:01:49 +00:00
{
2020-03-23 00:03:18 +00:00
if ( _entityIDToStorageIndex . ContainsKey ( entityID ) )
2020-03-22 05:19:31 +00:00
{
2020-03-23 00:03:18 +00:00
var storageIndex = _entityIDToStorageIndex [ entityID ] ;
_entityIDToStorageIndex . Remove ( entityID ) ;
2020-03-22 05:19:31 +00:00
_priorities . Remove ( entityID ) ;
2020-03-23 00:03:18 +00:00
// move a component into the hole to maintain contiguous memory
if ( _nextID > 1 & & storageIndex ! = _nextID - 1 )
{
var lastStorageIndex = _nextID - 1 ;
2020-03-23 02:10:28 +00:00
ref readonly var lastEntity = ref _storageIndexToEntities [ lastStorageIndex ] ;
2020-03-23 00:03:18 +00:00
2020-03-23 02:10:28 +00:00
_entityIDToStorageIndex [ lastEntity . ID ] = storageIndex ;
_storageIndexToEntities [ storageIndex ] = lastEntity ;
2020-03-23 00:03:18 +00:00
_components [ storageIndex ] = _components [ lastStorageIndex ] ;
}
_nextID - - ;
2020-03-22 05:19:31 +00:00
}
2019-12-24 02:01:49 +00:00
}
2019-12-24 02:45:49 +00:00
public override bool Has ( int entityID )
2019-12-05 22:59:55 +00:00
{
2020-03-23 00:03:18 +00:00
return _entityIDToStorageIndex . ContainsKey ( entityID ) ;
2019-12-05 22:59:55 +00:00
}
public override void Clear ( )
{
2020-03-23 00:03:18 +00:00
_nextID = 0 ;
_entityIDToStorageIndex . Clear ( ) ;
2020-03-20 07:09:57 +00:00
_priorities . Clear ( ) ;
2019-12-05 22:59:55 +00:00
}
2019-12-30 03:43:05 +00:00
public override void ClearPriorities ( )
{
2020-03-20 07:09:57 +00:00
_priorities . Clear ( ) ;
2019-12-30 03:43:05 +00:00
}
2020-11-16 07:21:51 +00:00
public ReadOnlySpan < Entity > AllEntities ( )
2019-12-05 22:59:55 +00:00
{
2020-11-16 07:21:51 +00:00
return new ReadOnlySpan < Entity > ( _storageIndexToEntities , 0 , _nextID ) ;
2020-03-23 02:10:28 +00:00
}
2020-11-16 07:21:51 +00:00
public IEnumerable < Entity > AllEntitiesAsEnumerable ( )
2020-03-23 02:10:28 +00:00
{
2020-11-16 07:21:51 +00:00
return new ArraySegment < Entity > ( _storageIndexToEntities , 0 , _nextID ) ;
}
public ReadOnlySpan < TComponent > AllComponents ( )
{
return new ReadOnlySpan < TComponent > ( _components , 0 , _nextID ) ;
}
public IEnumerable < TComponent > AllComponentsAsEnumerable ( )
{
return new ArraySegment < TComponent > ( _components , 0 , _nextID ) ;
2019-12-05 22:59:55 +00:00
}
}
}