com.elestrago.unity.entitas-redux 3.2.5 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
## [3.3.1](https://gitlab.com/elestrago-pkg/entitas-redux/-/tags/3.3.1)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `Optional` flag to `CommandAttribute`
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## [3.3.0](https://gitlab.com/elestrago-pkg/entitas-redux/-/tags/3.3.0)
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- `Register<TCommand>` method to `ICommandBuffer` for create pool
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Create new command only allow for registered commands
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
5
25
|
## [3.2.5](https://gitlab.com/elestrago-pkg/entitas-redux/-/tags/3.2.5)
|
|
6
26
|
|
|
7
27
|
### Fixed
|
|
@@ -1,56 +1,132 @@
|
|
|
1
1
|
using System;
|
|
2
|
-
using System.
|
|
2
|
+
using System.Reflection;
|
|
3
|
+
using System.Threading;
|
|
3
4
|
|
|
4
5
|
namespace JCMG.EntitasRedux.Commands
|
|
5
6
|
{
|
|
6
|
-
public abstract class CommandBuffer : ICommandBuffer
|
|
7
|
+
public abstract class CommandBuffer : ICommandBuffer
|
|
7
8
|
{
|
|
8
|
-
|
|
9
|
+
// Helper to get a unique, static index for each command type.
|
|
10
|
+
private static class CommandType
|
|
11
|
+
{
|
|
12
|
+
private static int _indexCounter;
|
|
13
|
+
|
|
14
|
+
internal static class Info<TCommand> where TCommand : struct
|
|
15
|
+
{
|
|
16
|
+
// This value is calculated once per TCommand and cached.
|
|
17
|
+
public static readonly int Index = Interlocked.Increment(ref _indexCounter) - 1;
|
|
18
|
+
public static readonly bool Optional;
|
|
19
|
+
|
|
20
|
+
static Info()
|
|
21
|
+
{
|
|
22
|
+
var type = typeof(TCommand);
|
|
23
|
+
var attribute = type.GetCustomAttribute<CommandAttribute>();
|
|
24
|
+
if (attribute == null)
|
|
25
|
+
return;
|
|
9
26
|
|
|
10
|
-
|
|
11
|
-
|
|
27
|
+
Optional = attribute.Optional;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
12
31
|
|
|
13
|
-
|
|
32
|
+
// Use a raw array for performance. It's not readonly because we resize it.
|
|
33
|
+
private ICommandPool[] _pools = new ICommandPool[4];
|
|
14
34
|
|
|
15
|
-
|
|
35
|
+
/// <summary>
|
|
36
|
+
/// Registers a pool for the specified command type. This must be called
|
|
37
|
+
/// before creating or accessing commands of this type.
|
|
38
|
+
/// </summary>
|
|
39
|
+
public void Register<TCommand>() where TCommand : struct
|
|
16
40
|
{
|
|
17
|
-
|
|
41
|
+
var index = CommandType.Info<TCommand>.Index;
|
|
42
|
+
|
|
43
|
+
// Ensure the array is large enough, resizing if necessary.
|
|
44
|
+
if (index >= _pools.Length)
|
|
18
45
|
{
|
|
19
|
-
|
|
20
|
-
|
|
46
|
+
// Resize to the exact size needed to include the new index.
|
|
47
|
+
Array.Resize(ref _pools, index + 1);
|
|
21
48
|
}
|
|
22
49
|
|
|
23
|
-
|
|
50
|
+
// Create the pool if it doesn't exist for this buffer instance.
|
|
51
|
+
ref var commandPool = ref _pools[index];
|
|
52
|
+
commandPool ??= new CommandPool<TCommand>();
|
|
24
53
|
}
|
|
25
54
|
|
|
26
|
-
public
|
|
55
|
+
public ref TCommand Create<TCommand>() where TCommand : struct
|
|
27
56
|
{
|
|
28
|
-
|
|
29
|
-
|
|
57
|
+
var pool = GetPool<TCommand>();
|
|
58
|
+
if (pool != null)
|
|
59
|
+
return ref pool.Create();
|
|
30
60
|
|
|
31
|
-
|
|
61
|
+
if (!CommandType.Info<TCommand>.Optional)
|
|
62
|
+
{
|
|
63
|
+
#if DEBUG
|
|
64
|
+
throw new Exception($"[CommandBuffer] Command type '{typeof(TCommand).Name}' is not registered. " +
|
|
65
|
+
$"Call Register<{typeof(TCommand).Name}>() first. Command will be ignored.");
|
|
66
|
+
#endif
|
|
67
|
+
}
|
|
32
68
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
var pool = _pools[CommandPool<TCommand>.Index] as CommandPool<TCommand>;
|
|
36
|
-
return ref pool.Create();
|
|
69
|
+
// Return a reference to a dummy variable to satisfy the ref return.
|
|
70
|
+
return ref Dummy<TCommand>.Value;
|
|
37
71
|
}
|
|
38
72
|
|
|
39
73
|
public void Create<TCommand>(TCommand command) where TCommand : struct
|
|
40
74
|
{
|
|
41
|
-
var pool =
|
|
42
|
-
pool
|
|
75
|
+
var pool = GetPool<TCommand>();
|
|
76
|
+
if (pool != null)
|
|
77
|
+
{
|
|
78
|
+
pool.Create(command);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (CommandType.Info<TCommand>.Optional)
|
|
83
|
+
return;
|
|
84
|
+
|
|
85
|
+
#if DEBUG
|
|
86
|
+
throw new Exception($"[CommandBuffer] Command type '{typeof(TCommand).Name}' is not registered. " +
|
|
87
|
+
$"Call Register<{typeof(TCommand).Name}>() first. Command will be ignored.");
|
|
88
|
+
#endif
|
|
43
89
|
}
|
|
44
90
|
|
|
45
91
|
public Span<TCommand> GetCommands<TCommand>() where TCommand : struct
|
|
46
92
|
{
|
|
47
|
-
var pool =
|
|
48
|
-
return pool.Read();
|
|
93
|
+
var pool = GetPool<TCommand>();
|
|
94
|
+
return pool != null ? pool.Read() : Span<TCommand>.Empty;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
private CommandPool<TCommand> GetPool<TCommand>() where TCommand : struct
|
|
98
|
+
{
|
|
99
|
+
var index = CommandType.Info<TCommand>.Index;
|
|
100
|
+
|
|
101
|
+
// Use .Length for array boundary check.
|
|
102
|
+
if (index >= _pools.Length)
|
|
103
|
+
return null;
|
|
104
|
+
|
|
105
|
+
return _pools[index] as CommandPool<TCommand>;
|
|
49
106
|
}
|
|
50
107
|
|
|
51
108
|
public void Clear<TCommand>() where TCommand : struct
|
|
52
|
-
|
|
109
|
+
{
|
|
110
|
+
var index = CommandType.Info<TCommand>.Index;
|
|
111
|
+
|
|
112
|
+
// Use .Length for array boundary check.
|
|
113
|
+
if (index < _pools.Length)
|
|
114
|
+
_pools[index]?.Clear();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public void ClearAll()
|
|
118
|
+
{
|
|
119
|
+
for (var i = 0; i < _pools.Length; i++)
|
|
120
|
+
_pools[i]?.Clear();
|
|
121
|
+
}
|
|
53
122
|
|
|
123
|
+
// A helper to provide a valid ref return when a pool doesn't exist.
|
|
124
|
+
private static class Dummy<T> where T : struct
|
|
125
|
+
{
|
|
126
|
+
public static T Value;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// The interface and pool implementation are now much simpler.
|
|
54
130
|
private interface ICommandPool
|
|
55
131
|
{
|
|
56
132
|
void Clear();
|
|
@@ -59,23 +135,9 @@ namespace JCMG.EntitasRedux.Commands
|
|
|
59
135
|
private class CommandPool<TCommand> : ICommandPool
|
|
60
136
|
where TCommand : struct
|
|
61
137
|
{
|
|
62
|
-
public static readonly int Index;
|
|
63
|
-
|
|
64
138
|
private TCommand[] _pool = new TCommand[4];
|
|
65
139
|
private int _position;
|
|
66
140
|
|
|
67
|
-
static CommandPool()
|
|
68
|
-
{
|
|
69
|
-
lock (PoolFactories)
|
|
70
|
-
{
|
|
71
|
-
Index = _commandsCounter++;
|
|
72
|
-
PoolFactories.Add(Factory);
|
|
73
|
-
PoolFactoryRegister?.Invoke(Factory);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private static CommandPool<TCommand> Factory() => new();
|
|
78
|
-
|
|
79
141
|
public ref TCommand Create()
|
|
80
142
|
{
|
|
81
143
|
var position = _position++;
|
|
@@ -98,8 +160,9 @@ namespace JCMG.EntitasRedux.Commands
|
|
|
98
160
|
|
|
99
161
|
public void Clear()
|
|
100
162
|
{
|
|
163
|
+
// Clear only the portion of the array that was used.
|
|
164
|
+
Array.Clear(_pool, 0, _position);
|
|
101
165
|
_position = 0;
|
|
102
|
-
Array.Clear(_pool, 0, _pool.Length);
|
|
103
166
|
}
|
|
104
167
|
}
|
|
105
168
|
}
|
|
@@ -4,6 +4,12 @@ namespace JCMG.EntitasRedux.Commands
|
|
|
4
4
|
{
|
|
5
5
|
public interface ICommandBuffer
|
|
6
6
|
{
|
|
7
|
+
/// <summary>
|
|
8
|
+
/// Registers a pool for the specified command type. This must be called
|
|
9
|
+
/// before creating or accessing commands of this type.
|
|
10
|
+
/// </summary>
|
|
11
|
+
void Register<TCommand>() where TCommand : struct;
|
|
12
|
+
|
|
7
13
|
ref TCommand Create<TCommand>() where TCommand : struct;
|
|
8
14
|
|
|
9
15
|
void Create<TCommand>(TCommand command) where TCommand : struct;
|
|
@@ -11,5 +17,7 @@ namespace JCMG.EntitasRedux.Commands
|
|
|
11
17
|
Span<TCommand> GetCommands<TCommand>() where TCommand : struct;
|
|
12
18
|
|
|
13
19
|
void Clear<TCommand>() where TCommand : struct;
|
|
20
|
+
|
|
21
|
+
void ClearAll();
|
|
14
22
|
}
|
|
15
23
|
}
|
|
@@ -6,12 +6,18 @@ namespace JCMG.EntitasRedux.Commands
|
|
|
6
6
|
where TCommand : struct
|
|
7
7
|
{
|
|
8
8
|
private readonly ICommandBuffer _commandBuffer;
|
|
9
|
+
private readonly bool _cleanUp;
|
|
9
10
|
|
|
10
|
-
protected
|
|
11
|
-
|
|
12
|
-
protected CommandSystem(ICommandBuffer commandBuffer)
|
|
11
|
+
protected CommandSystem(ICommandBuffer commandBuffer, bool cleanUp = true)
|
|
13
12
|
{
|
|
14
13
|
_commandBuffer = commandBuffer;
|
|
14
|
+
_cleanUp = cleanUp;
|
|
15
|
+
|
|
16
|
+
// We only need to register the command type with the buffer if this system
|
|
17
|
+
// is responsible for cleaning it up. The buffer uses this registration to
|
|
18
|
+
// know which command types to manage for its internal collections.
|
|
19
|
+
if (_cleanUp)
|
|
20
|
+
_commandBuffer.Register<TCommand>();
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
protected void ExecuteCommands()
|
|
@@ -21,7 +27,7 @@ namespace JCMG.EntitasRedux.Commands
|
|
|
21
27
|
return;
|
|
22
28
|
|
|
23
29
|
Execute(commands);
|
|
24
|
-
if (
|
|
30
|
+
if (_cleanUp)
|
|
25
31
|
_commandBuffer.Clear<TCommand>();
|
|
26
32
|
}
|
|
27
33
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.elestrago.unity.entitas-redux",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"displayName": "JCMG Entitas Redux",
|
|
5
5
|
"description": "Entitas Redux is an fast, accessible, and feature-rich ECS framework for Unity. It leverages code generation and an extensible plugin framework to make life easier for developers.",
|
|
6
6
|
"category": "Unity",
|