@@ -59,7 +59,8 @@ namespace Svelto.ECS | |||
catch (Exception e) | |||
{ | |||
#if DEBUG && !PROFILER | |||
var str = "Entity Operation is ".FastConcat(entitiesOperations[i].type.ToString()) | |||
var str = "Crash while executing Entity Operation" | |||
.FastConcat(entitiesOperations[i].type.ToString()) | |||
.FastConcat(" id: ") | |||
.FastConcat(entitiesOperations[i].ID) | |||
.FastConcat(" to id: ") | |||
@@ -69,7 +70,7 @@ namespace Svelto.ECS | |||
.FastConcat(" to groupid: ") | |||
.FastConcat(entitiesOperations[i].toGroupID); | |||
#if RELAXED_ECS | |||
Console.LogException(str.FastConcat(" ").FastConcat(entitiesOperations[i].trace), e); | |||
Console.LogException(str.FastConcat(" ", entitiesOperations[i].trace), e); | |||
#else | |||
throw new ECSException(str.FastConcat(" ").FastConcat(entitiesOperations[i].trace), e); | |||
#endif | |||
@@ -0,0 +1,131 @@ | |||
#if !DEBUG || PROFILER | |||
#define DISABLE_CHECKS | |||
using System.Diagnostics; | |||
#endif | |||
using System; | |||
using System.Reflection; | |||
using Svelto.ECS.Internal; | |||
namespace Svelto.ECS | |||
{ | |||
public partial class EntityBuilder<T> | |||
{ | |||
#if DISABLE_CHECKS | |||
[Conditional("_CHECKS_DISABLED")] | |||
#endif | |||
static void CheckFields(Type type, bool needsReflection, bool isRoot) | |||
{ | |||
if (ENTITY_VIEW_TYPE == typeof(EntityInfoView)) return; | |||
if (type == EGIDType || type == ExclusiveGroupStructType) return; | |||
{ | |||
var methods = type.GetMethods(BindingFlags.Public | | |||
BindingFlags.Instance | BindingFlags.DeclaredOnly); | |||
var properties = type.GetProperties(BindingFlags.Public | | |||
BindingFlags.Instance | BindingFlags.DeclaredOnly); | |||
if (isRoot) | |||
{ | |||
if (properties.Length > 1) | |||
ProcessError("EntityViews cannot have public methods or properties", type); | |||
if (methods.Length > properties.Length + 1) | |||
ProcessError("EntityViews cannot have public methods or properties", type); | |||
} | |||
else | |||
{ | |||
if (properties.Length > 0) | |||
ProcessError("Entity components fields cannot have public methods or properties", type); | |||
if (methods.Length > 0) | |||
ProcessError("Entity components fields cannot have public methods or properties", type); | |||
} | |||
} | |||
if (needsReflection == false) | |||
{ | |||
if (type.IsClass) | |||
throw new ECSException("IEntityStructs must be structs - EntityView: ".FastConcat(ENTITY_VIEW_TYPE)); | |||
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); | |||
for (int i = fields.Length - 1; i >= 0; --i) | |||
{ | |||
var field = fields[i]; | |||
var fieldFieldType = field.FieldType; | |||
SubCheckFields(fieldFieldType); | |||
} | |||
} | |||
else | |||
{ | |||
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance); | |||
if (fields.Length < 1) | |||
ProcessError("Entity View Structs must hold entity components interfaces", type); | |||
for (int i = fields.Length - 1; i >= 0; --i) | |||
{ | |||
var field = fields[i]; | |||
if (field.FieldType.IsInterfaceEx() == false) | |||
ProcessError("Entity View Structs must hold entity components interfaces", type); | |||
var properties = field.FieldType.GetProperties(BindingFlags.Public | | |||
BindingFlags.Instance | BindingFlags.DeclaredOnly); | |||
for (int j = properties.Length - 1; j >= 0; --j) | |||
{ | |||
if (properties[j].PropertyType.IsGenericType == true) | |||
{ | |||
var genericTypeDefinition = properties[j].PropertyType.GetGenericTypeDefinition(); | |||
if (genericTypeDefinition == typeof(DispatchOnSet<>) || | |||
genericTypeDefinition == typeof(DispatchOnChange<>)) continue; | |||
} | |||
SubCheckFields(properties[j].PropertyType); | |||
} | |||
} | |||
} | |||
} | |||
static void SubCheckFields(Type fieldFieldType) | |||
{ | |||
if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true) | |||
{ | |||
if (fieldFieldType.IsValueType && !fieldFieldType.IsEnum && fieldFieldType.IsPrimitive == false) | |||
{ | |||
CheckFields(fieldFieldType, false, false); | |||
} | |||
return; | |||
} | |||
ProcessError("Entity Structs field and Entity View Struct components must hold value types", fieldFieldType); | |||
} | |||
static void ProcessError(string message, Type type) | |||
{ | |||
#if !RELAXED_ECS | |||
throw new EntityStructException(message, ENTITY_VIEW_TYPE, type); | |||
#else | |||
Utilities.Console.LogError("Invalid entity view detected - EntityViews must handle only value types and have " + | |||
"no public methods! EntityView ".FastConcat(ENTITY_VIEW_NAME).FastConcat( | |||
" invalid field: ", type.ToString())); | |||
#endif | |||
} | |||
static readonly Type EGIDType = typeof(EGID); | |||
static readonly Type ExclusiveGroupStructType = typeof(ExclusiveGroup.ExclusiveGroupStruct); | |||
} | |||
public class EntityStructException : Exception | |||
{ | |||
public EntityStructException(string message, Type entityViewType, Type type): | |||
base(message.FastConcat(" entity view: ", entityViewType.ToString(), " field: ", type.ToString())) | |||
{} | |||
} | |||
} |
@@ -1,9 +1,4 @@ | |||
#if !DEBUG || PROFILER | |||
#define DISABLE_CHECKS | |||
using System.Diagnostics; | |||
#endif | |||
using System.Reflection; | |||
using System; | |||
using System; | |||
using System.Collections.Generic; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS.Internal; | |||
@@ -11,93 +6,18 @@ using Svelto.Utilities; | |||
namespace Svelto.ECS | |||
{ | |||
public class EntityBuilder<T> : IEntityBuilder where T : IEntityStruct, new() | |||
public partial class EntityBuilder<T> : IEntityBuilder where T : IEntityStruct, new() | |||
{ | |||
public EntityBuilder() | |||
{ | |||
_initializer = defaultIt; | |||
_initializer = DEFAULT_IT; | |||
CheckFields(ENTITY_VIEW_TYPE); | |||
CheckFields(ENTITY_VIEW_TYPE, NEEDS_REFLECTION, true); | |||
if (needsReflection == true) | |||
if (NEEDS_REFLECTION == true) | |||
EntityView<T>.InitCache(); | |||
} | |||
#if DISABLE_CHECKS | |||
[Conditional("_CHECKS_DISABLED")] | |||
#endif | |||
static void CheckFields(Type type) | |||
{ | |||
if (ENTITY_VIEW_TYPE == typeof(EntityInfoView)) return; | |||
if (needsReflection == false ) | |||
{ | |||
if (type.IsClass) | |||
throw new ECSException("IEntityStructs must be structs - EntityView:".FastConcat(typeof(T))); | |||
var fields = type.GetFields(BindingFlags.Public | | |||
BindingFlags.Instance); | |||
for (int i = fields.Length - 1; i >= 0; --i) | |||
{ | |||
var field = fields[i]; | |||
var fieldFieldType = field.FieldType; | |||
SubCheckFields(fieldFieldType); | |||
} | |||
if (type.Assembly == Assembly.GetCallingAssembly() && type != EGIDType) | |||
{ | |||
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) | |||
{ | |||
var propertyInfo = properties[i]; | |||
var fieldFieldType = propertyInfo.PropertyType; | |||
SubCheckFields(fieldFieldType); | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
var fields = type.GetFields(BindingFlags.Public | | |||
BindingFlags.Instance); | |||
if (fields.Length < 1) | |||
#if !RELAXED_ECS | |||
throw new ECSException("Invalid entity view struct detected - EntityView:".FastConcat(typeof(T))); | |||
#else | |||
Svelto.Utilities.Console.LogError("Invalid entity view struct detected - EntityView:".FastConcat(typeof(T))); | |||
#endif | |||
} | |||
} | |||
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); | |||
} | |||
public void BuildEntityAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors) | |||
{ | |||
if (dictionary == null) | |||
@@ -105,7 +25,7 @@ namespace Svelto.ECS | |||
var castedDic = dictionary as TypeSafeDictionary<T>; | |||
if (needsReflection == true) | |||
if (NEEDS_REFLECTION == true) | |||
{ | |||
DBC.ECS.Check.Require(implementors != null, "Implementors not found while building an EntityView"); | |||
DBC.ECS.Check.Require(castedDic.ContainsKey(entityID.entityID) == false, | |||
@@ -154,18 +74,11 @@ namespace Svelto.ECS | |||
} | |||
static readonly Type ENTITY_VIEW_TYPE = typeof(T); | |||
static readonly T DEFAULT_IT = default(T); | |||
static readonly bool NEEDS_REFLECTION = typeof(IEntityViewStruct).IsAssignableFrom(typeof(T)); | |||
static readonly string ENTITY_VIEW_NAME = ENTITY_VIEW_TYPE.ToString(); | |||
static readonly bool needsReflection = typeof(IEntityViewStruct).IsAssignableFrom(typeof(T)); | |||
static readonly T defaultIt = default(T); | |||
static readonly Type EGIDType = typeof(EGID); | |||
internal T _initializer; | |||
} | |||
public class EntityStructException : Exception | |||
{ | |||
public EntityStructException(Type fieldType) : | |||
base("EntityStruct must contains only value types and no public methods! " + fieldType.ToString()) | |||
{} | |||
} | |||
} |
@@ -93,7 +93,7 @@ namespace Svelto.ECS | |||
/// <summary> | |||
/// Use this constructor to reserve N groups | |||
/// </summary> | |||
public ExclusiveGroupStruct(ushort range) | |||
internal ExclusiveGroupStruct(ushort range) | |||
{ | |||
_id = (int) _globalId; | |||
DBC.ECS.Check.Require(_globalId + range < ushort.MaxValue, "too many exclusive groups created"); | |||