Skip to content

Commit

Permalink
Merge pull request #190 from scellecs/stage-2023.1
Browse files Browse the repository at this point in the history
🚀 2023.1
  • Loading branch information
olegmrzv authored Sep 14, 2023
2 parents 46f3546 + 0801585 commit 26ab7f5
Show file tree
Hide file tree
Showing 168 changed files with 3,987 additions and 3,373 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2023.1.0] - 09.10.2023
### Fixed
- Fix `NativeFilter` allocations.
- Calling `World.InitializeDefaultWorld()` do not create new Update Loop Runner.
- Avoid defines modification by @vanifatovvlad.
- Small bugfix providers, when entity was destroyed.
### Added
- Aspects API. `IAspect`, `IFilterExtensions`, `Filter.Extend()`.
- New method for stashes `RemoveAll()` by @SH42913.
- Deinitilize method for `EntityProvider`, `MonoProvider`.
- `World.JobHandle`.
- Metrics for Unity Profiler.
- TriInspector Integration for replacing paid Odin Inspector.
- `World.IsDisposed` and `World.IsNullOrDisposed()`
- `MORPEH_DISABLE_SET_ICONS` define for disabling set icons in Project Window.
- Safety check for `World.Commit()` inside Filter foreach loop.
- New Pinned Collections.
- `World.DoNotDisableSystemOnException`
- `Filter.IsNotEmpty()`
### Changed
- **[Breaking]** Filters must be initialized with `Build()` method.
- Overrided Entity.ToString() will output ID by @SH42913.
- Rework types warmup for fast start of application.
- All archetypes are reworked. Performance has been significantly improved and RAM consumption has been reduced.
- All Native API changed from internal to public.
- `Entity` and `World` now has partial modifier.
### Removed
- Discover window.
- **[Breaking]** Removed `ComponentProvider`.

## [2022.2.3] - 18.05.2023
### Fixed
- RemoveEntityOnDestroy doesnt work properly.
Expand Down
36 changes: 6 additions & 30 deletions Core/Archetype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,26 @@ namespace Scellecs.Morpeh {
using Collections;
using Unity.IL2CPP.CompilerServices;
using UnityEngine;

#if !MORPEH_NON_SERIALIZED
[Serializable]
#endif

[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
internal sealed class Archetype {
[SerializeField]
internal int[] typeIds;
[SerializeField]
internal BitMap entities;
[SerializeField]
internal FastList<int> entitiesNative;
[NonSerialized]
internal FastList<Filter> filters;
[SerializeField]
internal UnsafeIntHashMap<int> removeTransfer;
[SerializeField]
internal UnsafeIntHashMap<int> addTransfer;
[SerializeField]
internal int length;
[SerializeField]
internal int worldId;
[SerializeField]
internal int id;
[SerializeField]
internal bool usedInNative;
internal long id;

[NonSerialized]
internal World world;

internal Archetype(int id, int[] typeIds, int worldId) {

internal Archetype(long id, World world) {
this.id = id;
this.typeIds = typeIds;
this.length = 0;
this.entities = new BitMap();
this.addTransfer = new UnsafeIntHashMap<int>();
this.removeTransfer = new UnsafeIntHashMap<int>();
this.usedInNative = false;

this.worldId = worldId;
this.filters = new FastList<Filter>();

this.Ctor();
this.world = world;
}
}
}
71 changes: 13 additions & 58 deletions Core/ArchetypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,37 @@ namespace Scellecs.Morpeh {
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
[Il2CppSetOption(Option.DivideByZeroChecks, false)]
internal static class ArchetypeExtensions {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Ctor(this Archetype archetype) {
archetype.world = World.worlds.data[archetype.worldId];
archetype.filters = new FastList<Filter>();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void Dispose(this Archetype archetype) {
archetype.usedInNative = false;

archetype.id = -1;
archetype.length = -1;

archetype.typeIds = null;
archetype.world = null;

archetype.entities?.Clear();
archetype.entities = null;

archetype.entitiesNative?.Clear();
archetype.entitiesNative = null;

archetype.addTransfer.Clear();
archetype.addTransfer = null;

archetype.removeTransfer.Clear();
archetype.removeTransfer = null;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Add(this Archetype archetype, Entity entity) {
archetype.length++;

if (archetype.usedInNative) {
entity.indexInCurrentArchetype = archetype.entitiesNative.Add(entity.entityId.id);
}
else {
archetype.entities.Set(entity.entityId.id);
if (archetype.entities.Set(entity.entityId.id)) {
archetype.length++;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Remove(this Archetype archetype, Entity entity) {
archetype.length--;

if (archetype.usedInNative) {
var index = entity.indexInCurrentArchetype;
if (archetype.entitiesNative.RemoveAtSwap(index, out int newValue)) {
archetype.world.entities[newValue].indexInCurrentArchetype = index;
if (archetype.entities.Unset(entity.entityId.id)) {
if (--archetype.length == 0) {
Pool(archetype);
}
}
else {
archetype.entities.Unset(entity.entityId.id);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void Pool(Archetype archetype) {
archetype.world.archetypes.Remove(archetype.id, out _);
archetype.world.removedArchetypes.Add(archetype);
archetype.world.archetypesCount--;
archetype.entities.Clear();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand All @@ -72,27 +49,5 @@ public static void AddFilter(this Archetype archetype, Filter filter) {
public static void RemoveFilter(this Archetype archetype, Filter filter) {
archetype.filters.Remove(filter);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddTransfer(this Archetype archetype, int typeId, out int archetypeId, out Archetype newArchetype) {
if (archetype.addTransfer.TryGetValue(typeId, out archetypeId)) {
newArchetype = archetype.world.archetypes.data[archetypeId];
}
else {
newArchetype = archetype.world.GetArchetype(archetype.typeIds, typeId, true, out archetypeId);
archetype.addTransfer.Add(typeId, archetypeId, out _);
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void RemoveTransfer(this Archetype archetype, int typeId, out int archetypeId, out Archetype newArchetype) {
if (archetype.removeTransfer.TryGetValue(typeId, out archetypeId)) {
newArchetype = archetype.world.archetypes.data[archetypeId];
}
else {
newArchetype = archetype.world.GetArchetype(archetype.typeIds, typeId, false, out archetypeId);
archetype.removeTransfer.Add(typeId, archetypeId, out _);
}
}
}
}
11 changes: 11 additions & 0 deletions Core/Aspect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Scellecs.Morpeh {
public interface IAspect {
Entity Entity { get; set; }

void OnGetAspectFactory(World world);
}

public struct AspectFactory<T> where T : struct, IAspect {
internal T value;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Core/AspectExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Scellecs.Morpeh {
public static class AspectExtensions {
public static T Get<T>(this ref AspectFactory<T> aspectFactory, Entity entity) where T : struct, IAspect {
var aspect = aspectFactory.value;
aspect.Entity = entity;
return aspect;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 49 additions & 10 deletions Core/Collections/ArrayHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,59 @@ public static int IndexOf<T>(T[] array, T value, EqualityComparer<T> comparer) {
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int IndexOfUnsafeInt(int[] array, int value) {
fixed (int* arr = &array[0]) {
var i = 0;
for (int* current = arr, length = arr + array.Length; current < length; ++current) {
if (*current == value) {
return i;
}

++i;
public static unsafe int IndexOfUnsafeInt(int* array, int length, int value) {
var i = 0;
for (int* current = array, len = array + length; current < len; ++current) {
if (*current == value) {
return i;
}
}

++i;
}

return -1;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InsertionSort(this int[] array, int offset, int length) {
var r = offset + length;
for (var i = offset + 1; i < r; i++)
{
ref var ie = ref array[i];
ref var im1e = ref array[i - 1];
if (ie < im1e)
{
var currentElement = ie;
ie = im1e;
var j = i - 1;
for (; j > offset && (currentElement < array[j - 1]); j--)
{
array[j] = array[j - 1];
}
array[j] = currentElement;
}
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InsertionSort(this long[] array, int offset, int length) {
var r = offset + length;
for (var i = offset + 1; i < r; i++)
{
ref var ie = ref array[i];
ref var im1e = ref array[i - 1];
if (ie < im1e)
{
var currentElement = ie;
ie = im1e;
var j = i - 1;
for (; j > offset && (currentElement < array[j - 1]); j--)
{
array[j] = array[j - 1];
}
array[j] = currentElement;
}
}
}
}
}
Loading

0 comments on commit 26ab7f5

Please sign in to comment.