/// <summary>
        /// Updates all filters for changed component mask.
        /// </summary>
        /// <param name="entity">Entity.</param>
        /// <param name="component">Component.</param>
        /// <param name="oldMask">Old component state.</param>
        /// <param name="newMask">New component state.</param>
        void UpdateFilters(int entity, int component, EcsComponentMask oldMask, EcsComponentMask newMask)
        {
            for (var i = _filters.Count - 1; i >= 0; i--)
            {
                var filter = _filters[i];
                var isNewMaskCompatible = newMask.IsCompatible(filter.IncludeMask, filter.ExcludeMask);
                if (oldMask.IsCompatible(filter.IncludeMask, filter.ExcludeMask))
                {
                    if (!isNewMaskCompatible)
                    {
#if DEBUG && !ECS_PERF_TEST
                        if (filter.Entities.IndexOf(entity) == -1)
                        {
                            throw new Exception(
                                      string.Format("Something wrong - entity {0} should be in filter {1}, but not exits.", entity, filter));
                        }
#endif
                        filter.Entities.Remove(entity);
                        filter.RaiseOnEntityRemoved(entity, component);
                    }
                }
                else
                {
                    if (isNewMaskCompatible)
                    {
                        filter.Entities.Add(entity);
                        filter.RaiseOnEntityAdded(entity, component);
                    }
                }
            }
        }
        /// <summary>
        /// Gets filter for specific components.
        /// </summary>
        /// <param name="include">Component mask for required components.</param>
        /// <param name="include">Component mask for denied components.</param>
        internal EcsFilter GetFilter(EcsComponentMask include, EcsComponentMask exclude)
        {
#if DEBUG && !ECS_PERF_TEST
            if (include == null)
            {
                throw new ArgumentNullException("include");
            }
            if (exclude == null)
            {
                throw new ArgumentNullException("exclude");
            }
#endif
            var i = _filters.Count - 1;
            for (; i >= 0; i--)
            {
                if (this._filters[i].IncludeMask.IsEquals(include) && _filters[i].ExcludeMask.IsEquals(exclude))
                {
                    break;
                }
            }
            if (i == -1)
            {
                i = _filters.Count;
                _filters.Add(new EcsFilter(include, exclude));
            }
            return(_filters[i]);
        }
예제 #3
0
        /// <summary>
        /// Gets filter for specific components.
        /// </summary>
        public EcsFilter GetFilter <A, B> () where A : class, IEcsComponent where B : class, IEcsComponent
        {
            var mask = new EcsComponentMask();

            mask.SetBit(GetComponentIndex <A> (), true);
            mask.SetBit(GetComponentIndex <B> (), true);
            return(GetFilter(mask));
        }
예제 #4
0
파일: EcsWorld.cs 프로젝트: midgithub/ecs
        /// <summary>
        /// Gets filter for specific components.
        /// </summary>
        /// <param name="include">Component mask for required components.</param>
        /// <param name="include">Component mask for denied components.</param>
        /// <param name="shouldBeFilled">New filter should be filled with compatible entities on creation.</param>
        internal EcsFilter GetFilter(EcsComponentMask include, EcsComponentMask exclude, bool shouldBeFilled)
        {
#if DEBUG
            if (include == null)
            {
                throw new ArgumentNullException("include");
            }
            if (exclude == null)
            {
                throw new ArgumentNullException("exclude");
            }
#endif
            var i = _filtersCount - 1;
            for (; i >= 0; i--)
            {
                if (this._filters[i].IncludeMask.IsEquals(include) && _filters[i].ExcludeMask.IsEquals(exclude))
                {
                    break;
                }
            }
            if (i == -1)
            {
                i = _filtersCount;

                var filter = new EcsFilter(include, exclude);
                if (shouldBeFilled)
                {
                    FillFilter(filter);
                }

                if (_filtersCount == _filters.Length)
                {
                    Array.Resize(ref _filters, _filtersCount << 1);
                }
                _filters[_filtersCount++] = filter;

                for (var bit = 0; bit < include.BitsCount; bit++)
                {
                    var typeId = include.Bits[bit];
                    if (typeId >= _componentPoolFilters.Length)
                    {
                        Array.Resize(ref _componentPoolFilters, EcsHelpers.GetPowerOfTwoSize(typeId + 1));
                    }
                    var filterList = _componentPoolFilters[typeId];
                    if (filterList == null)
                    {
                        filterList = new EcsFilterList();
                        _componentPoolFilters[typeId] = filterList;
                    }
                    if (filterList.Count == filterList.Filters.Length)
                    {
                        Array.Resize(ref filterList.Filters, filterList.Count << 1);
                    }
                    filterList.Filters[filterList.Count++] = filter;
                }
            }
            return(_filters[i]);
        }
예제 #5
0
        /// <summary>
        /// Gets filter for specific components.
        /// </summary>
        /// <param name="mask">Component selection.</param>
        public EcsFilter GetFilter(EcsComponentMask mask)
        {
            var i = _filters.Count - 1;

            for (; i >= 0; i--)
            {
                if (_filters[i].Mask.IsEquals(mask))
                {
                    break;
                }
            }
            if (i == -1)
            {
                i = _filters.Count;
                _filters.Add(new EcsFilter(mask));
            }
            return(_filters[i]);
        }
예제 #6
0
 /// <summary>
 /// Updates all filters for changed component mask.
 /// </summary>
 /// <param name="entity">Entity.</param>
 /// <param name="oldMask">Old component state.</param>
 /// <param name="newMask">New component state.</param>
 void UpdateFilters(int entity, EcsComponentMask oldMask, EcsComponentMask newMask)
 {
     for (var i = _filters.Count - 1; i >= 0; i--)
     {
         var isNewMaskCompatible = newMask.IsCompatible(_filters[i].Mask);
         if (oldMask.IsCompatible(_filters[i].Mask))
         {
             if (!isNewMaskCompatible)
             {
                 _filters[i].Entities.Remove(entity);
             }
         }
         else
         {
             if (isNewMaskCompatible)
             {
                 _filters[i].Entities.Add(entity);
             }
         }
     }
 }
예제 #7
0
파일: EcsWorld.cs 프로젝트: midgithub/ecs
        void UpdateFilters(int entity, object component, EcsComponentMask oldMask, EcsComponentMask newMask)
        {
            for (var i = _filtersCount - 1; i >= 0; i--)
            {
                var filter = _filters[i];
                var isNewMaskCompatible = newMask.IsCompatible(filter);
                if (oldMask.IsCompatible(filter))
                {
                    if (!isNewMaskCompatible)
                    {
#if DEBUG
                        var ii = filter.EntitiesCount - 1;
                        for (; ii >= 0; ii--)
                        {
                            if (filter.Entities[ii] == entity)
                            {
                                break;
                            }
                        }
                        if (ii == -1)
                        {
                            throw new Exception(
                                      string.Format("Something wrong - entity {0} should be in filter {1}, but not exits.", entity, filter));
                        }
#endif
                        filter.RaiseOnRemoveEvent(entity, component);
                    }
                }
                else
                {
                    if (isNewMaskCompatible)
                    {
                        filter.RaiseOnAddEvent(entity, component);
                    }
                }
            }
        }
예제 #8
0
 internal EcsFilter(EcsComponentMask include, EcsComponentMask exclude)
 {
     IncludeMask = include;
     ExcludeMask = exclude;
 }
예제 #9
0
        /// <summary>
        /// Processes delayed updates. Use carefully!
        /// </summary>
        public void ProcessDelayedUpdates()
        {
            var iMax = _delayedUpdates.Count;

            for (var i = 0; i < iMax; i++)
            {
                var op         = _delayedUpdates[i];
                var entityData = _entities[op.Entity];
                var oldMask    = entityData.Mask;
                switch (op.Type)
                {
                case DelayedUpdate.Op.RemoveEntity:
                    if (!entityData.IsReserved)
                    {
                        var componentId = 0;
                        var empty       = new EcsComponentMask();
                        while (!entityData.Mask.IsEmpty())
                        {
                            if (entityData.Mask.GetBit(componentId))
                            {
                                entityData.Mask.SetBit(componentId, false);
                                DetachComponent(op.Entity, entityData, componentId);
                            }
                            componentId++;
                        }
                        UpdateFilters(op.Entity, oldMask, empty);
                        entityData.IsReserved = true;
                        _reservedEntityIds.Add(op.Entity);
                    }
                    break;

                case DelayedUpdate.Op.AddComponent:
                    if (!entityData.Mask.GetBit(op.Component))
                    {
                        entityData.Mask.SetBit(op.Component, true);
                        OnComponentAttach(op.Entity, entityData.Components[op.Component]);
                        UpdateFilters(op.Entity, oldMask, entityData.Mask);
                    }
                    break;

                case DelayedUpdate.Op.RemoveComponent:
                    if (entityData.Mask.GetBit(op.Component))
                    {
                        entityData.Mask.SetBit(op.Component, false);
                        DetachComponent(op.Entity, entityData, op.Component);
                        UpdateFilters(op.Entity, oldMask, entityData.Mask);
                    }
                    break;
                }
            }
            if (iMax > 0)
            {
                if (_delayedUpdates.Count == iMax)
                {
                    _delayedUpdates.Clear();
                }
                else
                {
                    _delayedUpdates.RemoveRange(0, iMax);
                    ProcessDelayedUpdates();
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Gets filter for specific component.
        /// </summary>
        public EcsFilter GetFilter <A> () where A : class, IEcsComponent
        {
            var mask = new EcsComponentMask(GetComponentIndex <A> ());

            return(GetFilter(mask));
        }
예제 #11
0
 public EcsFilter(EcsComponentMask mask)
 {
     Mask = mask;
 }