@@ -108,7 +108,7 @@ namespace Svelto.ECS.Internal | |||
if (toGroup != null) | |||
{ | |||
var toGroupCasted = (toGroup as TypeSafeDictionary<TValue>); | |||
var toGroupCasted = toGroup as TypeSafeDictionary<TValue>; | |||
fasterValuesBuffer[valueIndex].ID = new EGID(fromEntityGid.entityID, toGroupID); | |||
toGroupCasted.Add(fromEntityGid.entityID, ref fasterValuesBuffer[valueIndex]); | |||
@@ -0,0 +1,14 @@ | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
public struct EGIDMapper<T> where T : IEntityStruct | |||
{ | |||
internal TypeSafeDictionary<T> map; | |||
public uint this[EGID index] | |||
{ | |||
get { return map.FindElementIndex(index.entityID); } | |||
} | |||
} | |||
} |
@@ -142,11 +142,11 @@ namespace Svelto.ECS | |||
{ | |||
var entityType = entityBuilders[i].GetEntityType(); | |||
MoveEntity<T>(entityGID, toGroupID, toGroup, entityType); | |||
MoveEntity(entityGID, toGroupID, toGroup, entityType); | |||
} | |||
} | |||
void MoveEntity<T>(EGID fromEntityGID, int toGroupID, Dictionary<Type, ITypeSafeDictionary> toGroup, Type entityType) where T:IEntityDescriptor, new () | |||
void MoveEntity(EGID fromEntityGID, int toGroupID, Dictionary<Type, ITypeSafeDictionary> toGroup, Type entityType) | |||
{ | |||
var fromGroup = _groupEntityDB[fromEntityGID.groupID]; | |||
@@ -169,7 +169,7 @@ namespace Svelto.ECS | |||
if (fromTypeSafeDictionary.Count == 0) //clean up | |||
{ | |||
_groupedGroups[entityType].Remove(toGroupID); | |||
_groupedGroups[entityType].Remove(fromEntityGID.groupID); | |||
//it's probably better to not remove this, but the dictionary should be trimmed? | |||
//fromGroup.Remove(entityType); | |||
@@ -189,7 +189,7 @@ namespace Svelto.ECS | |||
///-------------------------------------------- | |||
void SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID) where T:IEntityDescriptor, new () | |||
EGID SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID) where T:IEntityDescriptor, new () | |||
{ | |||
DBC.ECS.Check.Require(fromGroupID != toGroupID, | |||
"can't move an entity to the same fromGroup where it already belongs to"); | |||
@@ -200,6 +200,8 @@ namespace Svelto.ECS | |||
toGroup = _groupEntityDB[toGroupID] = new Dictionary<Type, ITypeSafeDictionary>(); | |||
MoveEntity<T>(new EGID(entityID, fromGroupID), toGroupID, toGroup); | |||
return new EGID(entityID, toGroupID); | |||
} | |||
EGID SwapFirstEntityInGroup<T>(int fromGroupID, int toGroupId) where T:IEntityDescriptor, new() | |||
@@ -37,19 +37,19 @@ namespace Svelto.ECS | |||
_weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID); | |||
} | |||
public void SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() | |||
public EGID SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() | |||
{ | |||
_weakReference.Target.SwapEntityGroup<T>(entityID, fromGroupID, toGroupID); | |||
return _weakReference.Target.SwapEntityGroup<T>(entityID, fromGroupID, toGroupID); | |||
} | |||
public void SwapEntityGroup<T>(EGID id, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new() | |||
public EGID SwapEntityGroup<T>(EGID id, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new() | |||
{ | |||
_weakReference.Target.SwapEntityGroup<T>(id.entityID, id.groupID, toGroupID); | |||
return _weakReference.Target.SwapEntityGroup<T>(id.entityID, id.groupID, toGroupID); | |||
} | |||
public void SwapEntityGroup<T>(int entityID, int toGroupID) where T : IEntityDescriptor, new() | |||
public EGID SwapEntityGroup<T>(int entityID, int toGroupID) where T : IEntityDescriptor, new() | |||
{ | |||
_weakReference.Target.SwapEntityGroup<T>(entityID, ExclusiveGroup.StandardEntitiesGroup, toGroupID); | |||
return _weakReference.Target.SwapEntityGroup<T>(entityID, ExclusiveGroup.StandardEntitiesGroup, toGroupID); | |||
} | |||
public EGID SwapFirstEntityGroup<T>(int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() | |||
@@ -55,6 +55,20 @@ namespace Svelto.ECS.Internal | |||
return ((TypeSafeDictionary<T>)typeSafeDictionary).GetFasterValuesBuffer(out count); | |||
} | |||
public T[] QueryEntities<T>(int groupID, ref EGIDMapper<T> mapper) where T : IEntityStruct | |||
{ | |||
TypeSafeDictionary<T> casted; | |||
if (!FindSafeDictionary(groupID, out casted)) | |||
{ | |||
throw new Exception("Entity group found type: ".FastConcat(typeof(T)).FastConcat(" groupID: ").FastConcat(groupID)); | |||
} | |||
mapper.map = casted; | |||
int count; | |||
return QueryEntities<T>(groupID, out count); | |||
} | |||
public T[] QueryEntitiesAndIndex<T>(EGID entityGID, out uint index) where T : IEntityStruct | |||
{ | |||
T[] array; | |||
@@ -85,7 +99,7 @@ namespace Svelto.ECS.Internal | |||
public void ExecuteOnEntity<T, W>(EGID entityGID, ref W value, ActionRef<T, W> action) where T : IEntityStruct | |||
{ | |||
TypeSafeDictionary<T> casted; | |||
if (FindSafeDictionary(entityGID, out casted)) | |||
if (FindSafeDictionary(entityGID.groupID, out casted)) | |||
{ | |||
if (casted != null) | |||
if (casted.ExecuteOnEntityView(entityGID.entityID, ref value, action) == true) | |||
@@ -98,7 +112,7 @@ namespace Svelto.ECS.Internal | |||
public void ExecuteOnEntity<T>(EGID entityGID, ActionRef<T> action) where T : IEntityStruct | |||
{ | |||
TypeSafeDictionary<T> casted; | |||
if (FindSafeDictionary(entityGID, out casted)) | |||
if (FindSafeDictionary(entityGID.groupID, out casted)) | |||
{ | |||
if (casted != null) | |||
if (casted.ExecuteOnEntityView(entityGID.entityID, action) == true) | |||
@@ -139,11 +153,7 @@ namespace Svelto.ECS.Internal | |||
public void ExecuteOnEntities<T>(ActionRef<T> action) where T : IEntityStruct | |||
{ | |||
int count; | |||
var entities = QueryEntities<T>(out count); | |||
for (int i = 0; i < count; i++) | |||
action(ref entities[i]); | |||
ExecuteOnEntities(ExclusiveGroup.StandardEntitiesGroup, action); | |||
} | |||
public void ExecuteOnEntities<T, W>(int groupID, ref W value, ActionRef<T, W> action) where T : IEntityStruct | |||
@@ -157,11 +167,7 @@ namespace Svelto.ECS.Internal | |||
public void ExecuteOnEntities<T, W>(ref W value, ActionRef<T, W> action) where T : IEntityStruct | |||
{ | |||
int count; | |||
var entities = QueryEntities<T>(out count); | |||
for (int i = 0; i < count; i++) | |||
action(ref entities[i], ref value); | |||
ExecuteOnEntities(ExclusiveGroup.StandardEntitiesGroup, ref value, action); | |||
} | |||
public void ExecuteOnAllEntities<T>(ActionRef<T> action) where T : IEntityStruct | |||
@@ -197,7 +203,7 @@ namespace Svelto.ECS.Internal | |||
public bool Exists<T>(EGID entityGID) where T : IEntityStruct | |||
{ | |||
TypeSafeDictionary<T> casted; | |||
if (!FindSafeDictionary(entityGID, out casted)) return false; | |||
if (!FindSafeDictionary(entityGID.groupID, out casted)) return false; | |||
if (casted != null && | |||
casted.ContainsKey(entityGID.entityID)) | |||
@@ -208,14 +214,14 @@ namespace Svelto.ECS.Internal | |||
return false; | |||
} | |||
bool FindSafeDictionary<T>(EGID entityGID, out TypeSafeDictionary<T> casted) where T : IEntityStruct | |||
bool FindSafeDictionary<T>(int groupID, out TypeSafeDictionary<T> casted) where T : IEntityStruct | |||
{ | |||
var type = typeof(T); | |||
ITypeSafeDictionary entityViews; | |||
Dictionary<Type, ITypeSafeDictionary> entitiesInGroupPerType; | |||
if (_groupEntityViewsDB.TryGetValue(entityGID.groupID, out entitiesInGroupPerType) == false) | |||
if (_groupEntityViewsDB.TryGetValue(groupID, out entitiesInGroupPerType) == false) | |||
{ | |||
casted = null; | |||
return false; | |||
@@ -248,7 +254,7 @@ namespace Svelto.ECS.Internal | |||
bool TryQueryEntityViewInGroup<T>(EGID entityGID, out T entityView) where T:IEntityStruct | |||
{ | |||
TypeSafeDictionary<T> casted; | |||
if (!FindSafeDictionary(entityGID, out casted)) | |||
if (!FindSafeDictionary(entityGID.groupID, out casted)) | |||
{ | |||
entityView = default(T); | |||
return false; | |||
@@ -268,16 +274,16 @@ namespace Svelto.ECS.Internal | |||
T[] QueryEntitiesAndIndexInternal<T>(EGID entityGID, out uint index) where T : IEntityStruct | |||
{ | |||
TypeSafeDictionary<T> casted; | |||
if (!FindSafeDictionary(entityGID, out casted)) | |||
if (!FindSafeDictionary(entityGID.groupID, out casted)) | |||
{ | |||
index = 0; | |||
return null; | |||
throw new Exception("Entity group found type: ".FastConcat(typeof(T)).FastConcat(" groupID: ").FastConcat(entityGID.groupID)); | |||
} | |||
if (casted == null || casted.TryFindElementIndex(entityGID.entityID, out index) == false) | |||
{ | |||
index = 0; | |||
return null; | |||
throw new Exception("Entity not found type: ".FastConcat(typeof(T)).FastConcat(" groupID: ").FastConcat(entityGID.entityID)); | |||
} | |||
int count; | |||
@@ -296,6 +302,8 @@ namespace Svelto.ECS.Internal | |||
//grouped set of entity views, this is the standard way to handle entity views | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityViewsDB; | |||
Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>> _groupedGroups; | |||
//needed to be able to iterate over all the entities of the same type regardless the group | |||
//may change in future | |||
readonly Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>> _groupedGroups; | |||
} | |||
} |
@@ -37,18 +37,44 @@ namespace Svelto.ECS | |||
var field = fields[i]; | |||
var fieldFieldType = field.FieldType; | |||
if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true) | |||
SubCheckFields(fieldFieldType); | |||
} | |||
if (type.Assembly == Assembly.GetCallingAssembly()) | |||
{ | |||
var methods = type.GetMethods(BindingFlags.Public | | |||
BindingFlags.Instance | BindingFlags.DeclaredOnly); | |||
var properties = type.GetProperties(BindingFlags.Public | | |||
BindingFlags.Instance | BindingFlags.DeclaredOnly); | |||
if (methods.Length > properties.Length + 1) | |||
throw new EntityStructException(type); | |||
for (int i = properties.Length - 1; i >= 0; --i) | |||
{ | |||
if (fieldFieldType.IsValueType && !fieldFieldType.IsEnum) | |||
{ | |||
CheckFields(fieldFieldType); | |||
} | |||
var propertyInfo = properties[i]; | |||
continue; | |||
var fieldFieldType = propertyInfo.PropertyType; | |||
SubCheckFields(fieldFieldType); | |||
} | |||
} | |||
} | |||
throw new EntityStructException(fieldFieldType); | |||
static void SubCheckFields(Type fieldFieldType) | |||
{ | |||
if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true) | |||
{ | |||
if (fieldFieldType.IsValueType && !fieldFieldType.IsEnum && fieldFieldType.IsPrimitive == false) | |||
{ | |||
CheckFields(fieldFieldType); | |||
} | |||
return; | |||
} | |||
throw new EntityStructException(fieldFieldType); | |||
} | |||
#endif | |||
@@ -115,7 +141,7 @@ namespace Svelto.ECS | |||
public class EntityStructException : Exception | |||
{ | |||
public EntityStructException(Type fieldType):base("EntityStruct must contains only value types! " + fieldType.ToString()) | |||
public EntityStructException(Type fieldType):base("EntityStruct must contains only value types and no public methods! " + fieldType.ToString()) | |||
{} | |||
} | |||
} |
@@ -33,6 +33,7 @@ namespace Svelto.ECS | |||
//to use with EntityViews, EntityStructs and EntityViewStructs | |||
T[] QueryEntities<T>(out int count) where T : IEntityStruct; | |||
T[] QueryEntities<T>(int group, out int count) where T : IEntityStruct; | |||
T[] QueryEntities<T>(int groupID, ref EGIDMapper<T> mapper) where T : IEntityStruct; | |||
T[] QueryEntitiesAndIndex<T>(EGID entityGid, out uint index) where T : IEntityStruct; | |||
bool TryQueryEntitiesAndIndex<T>(EGID entityGid, out uint index, out T[] array) where T : IEntityStruct; | |||
@@ -13,9 +13,9 @@ namespace Svelto.ECS | |||
void RemoveGroupAndEntities(int groupID); | |||
void SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new(); | |||
void SwapEntityGroup<T>(EGID id, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new(); | |||
void SwapEntityGroup<T>(int entityID, int toGroupID) where T : IEntityDescriptor, new(); | |||
EGID SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new(); | |||
EGID SwapEntityGroup<T>(EGID id, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new(); | |||
EGID SwapEntityGroup<T>(int entityID, int toGroupID) where T : IEntityDescriptor, new(); | |||
EGID SwapFirstEntityGroup<T>(int fromGroupID = ExclusiveGroup.StandardEntitiesGroup, int toGroupID = ExclusiveGroup.StandardEntitiesGroup) where T : IEntityDescriptor, new(); | |||
} | |||
} |
@@ -5,28 +5,26 @@ using System.Collections.Generic; | |||
namespace Svelto.ECS | |||
{ | |||
public class Steps : Dictionary<IEngine, IDictionary> | |||
{} | |||
public class To<C> : Dictionary<C, IStep[]> where C : struct, IConvertible | |||
{ | |||
public void Add(C condition, IStep engine) | |||
{ | |||
Add(condition, new [] {engine}); | |||
} | |||
public void Add(C condition, params IStep[] engines) | |||
public new void Add(IEngine engine, IDictionary dictionary) | |||
{ | |||
Add(condition, engines); | |||
if (ContainsKey(engine)) | |||
{ | |||
Utility.Console.LogError("can't hold multiple steps with the same engine as origin in a Sequencer"); | |||
} | |||
base.Add(engine, dictionary); | |||
} | |||
public void Add(params IStep[] engines) | |||
} | |||
public class To<C> : Dictionary<C, IStep<C>[]> where C : struct, IConvertible | |||
{ | |||
public new void Add(C condition, params IStep<C>[] engines) | |||
{ | |||
Add(default(C), engines); | |||
base.Add(condition, engines); | |||
} | |||
} | |||
public interface IStep | |||
{} | |||
public interface IStep<in C>:IStep where C:struct,IConvertible | |||
public interface IStep<in C> where C:struct,IConvertible | |||
{ | |||
void Step(C condition, EGID id); | |||
} | |||
@@ -38,32 +36,18 @@ namespace Svelto.ECS | |||
_steps = steps; | |||
} | |||
public void Next(IEngine engine, EGID id) | |||
{ | |||
Next(engine, Condition.Always, id); | |||
} | |||
public void Next(IEngine engine) | |||
{ | |||
Next(engine, Condition.Always); | |||
} | |||
public void Next<C>(IEngine engine, C condition, EGID id = new EGID()) where C:struct,IConvertible | |||
public void Next<C>(IEngine engine, C condition, EGID id) where C:struct,IConvertible | |||
{ | |||
C branch = condition; | |||
var steps = (_steps[engine] as Dictionary<C, IStep[]>)[branch]; | |||
var steps = (_steps[engine] as Dictionary<C, IStep<C>[]>)[branch]; | |||
if (steps == null) return; | |||
if (steps == null) | |||
Utility.Console.LogError("selected steps not found in sequencer ".FastConcat(this.ToString())); | |||
for (var i = 0; i < steps.Length; i++) | |||
((IStep<C>)steps[i]).Step(condition, id); | |||
steps[i].Step(condition, id); | |||
} | |||
Steps _steps; | |||
} | |||
public static class Condition | |||
{ | |||
public const int Always = 0; | |||
} | |||
} |