com.artromskiy.deltaecs.unity 0.0.38 → 0.0.40
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 +8 -0
- package/CHANGELOG.md.meta +7 -0
- package/Editor/BoundEntityRootEditor.cs +23 -6
- package/Editor/ComponentPropertyBagFields.cs +280 -0
- package/Editor/ComponentPropertyBagFields.cs.meta +2 -0
- package/Editor/Resources/Inspector/SceneAuthoringEditor.uss +15 -16
- package/Editor/Resources/Inspector/SceneAuthoringEditor.uxml +1 -1
- package/Editor/SceneEntityInspectorView.cs +251 -120
- package/Editor.meta +8 -0
- package/README.md +17 -4
- package/Runtime/ComponentData.cs +16 -25
- package/Runtime/PropertyBagValueAccess.cs +258 -0
- package/Runtime/PropertyBagValueAccess.cs.meta +2 -0
- package/Runtime/SceneWorld.cs +91 -8
- package/Runtime/SceneWorldExtensions.cs +59 -0
- package/Runtime/SceneWorldExtensions.cs.meta +2 -0
- package/Runtime.meta +8 -0
- package/package.json +8 -2
- package/package.json.meta +2 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
using System;
|
|
2
|
+
using System.Collections.Generic;
|
|
3
|
+
using Delta.ECS;
|
|
4
|
+
using Unity.Properties;
|
|
5
|
+
|
|
6
|
+
namespace Delta.ECS.Unity
|
|
7
|
+
{
|
|
8
|
+
internal static class PropertyBagValueAccess
|
|
9
|
+
{
|
|
10
|
+
internal static bool TryGetValue(object container, Type containerType, string[] path, out object value)
|
|
11
|
+
{
|
|
12
|
+
value = null;
|
|
13
|
+
if (container == null || path == null || path.Length == 0)
|
|
14
|
+
{
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
IPropertyBag propertyBag = PropertyBag.GetPropertyBag(containerType);
|
|
19
|
+
if (propertyBag == null)
|
|
20
|
+
{
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var visitor = new ReadPathVisitor(path, 0);
|
|
25
|
+
propertyBag.Accept(visitor, ref container);
|
|
26
|
+
value = visitor.Value;
|
|
27
|
+
return visitor.Found;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
internal static bool TrySetValue(ref object container, Type containerType, string[] path, object value)
|
|
31
|
+
{
|
|
32
|
+
if (container == null || path == null || path.Length == 0)
|
|
33
|
+
{
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
IPropertyBag propertyBag = PropertyBag.GetPropertyBag(containerType);
|
|
38
|
+
if (propertyBag == null)
|
|
39
|
+
{
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var visitor = new WritePathVisitor(path, 0, value);
|
|
44
|
+
propertyBag.Accept(visitor, ref container);
|
|
45
|
+
return visitor.Succeeded;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
internal static string FormatPath(IReadOnlyList<string> path)
|
|
49
|
+
{
|
|
50
|
+
return string.Join("/", path);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
internal static string[] ParsePath(string path)
|
|
54
|
+
{
|
|
55
|
+
return string.IsNullOrEmpty(path) ? Array.Empty<string>() : path.Split('/');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
internal static void CollectEntityReferences(object container, Type containerType,
|
|
59
|
+
Func<Entity, string> stableIdResolver, IList<EntityReference> references)
|
|
60
|
+
{
|
|
61
|
+
if (container == null)
|
|
62
|
+
{
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
IPropertyBag propertyBag = PropertyBag.GetPropertyBag(containerType);
|
|
67
|
+
if (propertyBag == null)
|
|
68
|
+
{
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
var visitor = new EntityReferenceVisitor(stableIdResolver, references);
|
|
73
|
+
propertyBag.Accept(visitor, ref container);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private sealed class ReadPathVisitor : IPropertyBagVisitor
|
|
77
|
+
{
|
|
78
|
+
private readonly string[] _path;
|
|
79
|
+
private readonly int _pathIndex;
|
|
80
|
+
|
|
81
|
+
internal object Value;
|
|
82
|
+
internal bool Found;
|
|
83
|
+
|
|
84
|
+
internal ReadPathVisitor(string[] path, int pathIndex)
|
|
85
|
+
{
|
|
86
|
+
_path = path;
|
|
87
|
+
_pathIndex = pathIndex;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public void Visit<TContainer>(IPropertyBag<TContainer> properties, ref TContainer container)
|
|
91
|
+
{
|
|
92
|
+
foreach (var property in properties.GetProperties(ref container))
|
|
93
|
+
{
|
|
94
|
+
if (!string.Equals(property.Name, _path[_pathIndex], StringComparison.Ordinal))
|
|
95
|
+
{
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
object value = property.GetValue(ref container);
|
|
100
|
+
if (_pathIndex == _path.Length - 1)
|
|
101
|
+
{
|
|
102
|
+
Value = value;
|
|
103
|
+
Found = true;
|
|
104
|
+
}
|
|
105
|
+
else if (value != null)
|
|
106
|
+
{
|
|
107
|
+
IPropertyBag nestedBag = PropertyBag.GetPropertyBag(value.GetType());
|
|
108
|
+
if (nestedBag != null)
|
|
109
|
+
{
|
|
110
|
+
var nestedVisitor = new ReadPathVisitor(_path, _pathIndex + 1);
|
|
111
|
+
nestedBag.Accept(nestedVisitor, ref value);
|
|
112
|
+
Value = nestedVisitor.Value;
|
|
113
|
+
Found = nestedVisitor.Found;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private sealed class WritePathVisitor : IPropertyBagVisitor
|
|
123
|
+
{
|
|
124
|
+
private readonly string[] _path;
|
|
125
|
+
private readonly int _pathIndex;
|
|
126
|
+
private readonly object _value;
|
|
127
|
+
|
|
128
|
+
internal bool Succeeded;
|
|
129
|
+
|
|
130
|
+
internal WritePathVisitor(string[] path, int pathIndex, object value)
|
|
131
|
+
{
|
|
132
|
+
_path = path;
|
|
133
|
+
_pathIndex = pathIndex;
|
|
134
|
+
_value = value;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public void Visit<TContainer>(IPropertyBag<TContainer> properties, ref TContainer container)
|
|
138
|
+
{
|
|
139
|
+
TContainer updated = container;
|
|
140
|
+
foreach (var property in properties.GetProperties(ref updated))
|
|
141
|
+
{
|
|
142
|
+
if (!string.Equals(property.Name, _path[_pathIndex], StringComparison.Ordinal))
|
|
143
|
+
{
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (property.IsReadOnly)
|
|
148
|
+
{
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (_pathIndex == _path.Length - 1)
|
|
153
|
+
{
|
|
154
|
+
property.SetValue(ref updated, _value);
|
|
155
|
+
Succeeded = true;
|
|
156
|
+
}
|
|
157
|
+
else
|
|
158
|
+
{
|
|
159
|
+
object nestedValue = property.GetValue(ref updated);
|
|
160
|
+
if (nestedValue == null)
|
|
161
|
+
{
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
IPropertyBag nestedBag = PropertyBag.GetPropertyBag(nestedValue.GetType());
|
|
166
|
+
if (nestedBag == null)
|
|
167
|
+
{
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
var nestedVisitor = new WritePathVisitor(_path, _pathIndex + 1, _value);
|
|
172
|
+
nestedBag.Accept(nestedVisitor, ref nestedValue);
|
|
173
|
+
if (nestedVisitor.Succeeded)
|
|
174
|
+
{
|
|
175
|
+
property.SetValue(ref updated, nestedValue);
|
|
176
|
+
Succeeded = true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
container = updated;
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private sealed class EntityReferenceVisitor : IPropertyBagVisitor, IPropertyVisitor
|
|
187
|
+
{
|
|
188
|
+
private readonly Func<Entity, string> _stableIdResolver;
|
|
189
|
+
private readonly IList<EntityReference> _references;
|
|
190
|
+
private readonly List<string> _path = new();
|
|
191
|
+
private readonly HashSet<object> _activeReferences = new HashSet<object>(new ReferenceSet());
|
|
192
|
+
|
|
193
|
+
internal EntityReferenceVisitor(Func<Entity, string> stableIdResolver, IList<EntityReference> references)
|
|
194
|
+
{
|
|
195
|
+
_stableIdResolver = stableIdResolver;
|
|
196
|
+
_references = references;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public void Visit<TContainer>(IPropertyBag<TContainer> properties, ref TContainer container)
|
|
200
|
+
{
|
|
201
|
+
foreach (var property in properties.GetProperties(ref container))
|
|
202
|
+
{
|
|
203
|
+
((IPropertyAccept<TContainer>)property).Accept(this, ref container);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
public void Visit<TContainer, TValue>(Property<TContainer, TValue> property, ref TContainer container)
|
|
208
|
+
{
|
|
209
|
+
TValue value = property.GetValue(ref container);
|
|
210
|
+
_path.Add(property.Name);
|
|
211
|
+
try
|
|
212
|
+
{
|
|
213
|
+
if (typeof(TValue) == typeof(Entity))
|
|
214
|
+
{
|
|
215
|
+
string targetId = _stableIdResolver((Entity)(object)value);
|
|
216
|
+
if (!string.IsNullOrEmpty(targetId))
|
|
217
|
+
{
|
|
218
|
+
_references.Add(new EntityReference(FormatPath(_path), targetId));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (_path.Count < 24 && value != null)
|
|
222
|
+
{
|
|
223
|
+
object activeReference = value;
|
|
224
|
+
bool trackReference = !typeof(TValue).IsValueType;
|
|
225
|
+
if (!trackReference || _activeReferences.Add(activeReference))
|
|
226
|
+
{
|
|
227
|
+
try
|
|
228
|
+
{
|
|
229
|
+
object nestedValue = value;
|
|
230
|
+
if (PropertyBag.TryGetPropertyBagForValue(ref nestedValue, out IPropertyBag nestedBag))
|
|
231
|
+
{
|
|
232
|
+
nestedBag.Accept(this, ref nestedValue);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
finally
|
|
236
|
+
{
|
|
237
|
+
if (trackReference)
|
|
238
|
+
{
|
|
239
|
+
_activeReferences.Remove(activeReference);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
finally
|
|
246
|
+
{
|
|
247
|
+
_path.RemoveAt(_path.Count - 1);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private sealed class ReferenceSet : IEqualityComparer<object>
|
|
253
|
+
{
|
|
254
|
+
public new bool Equals(object left, object right) => ReferenceEquals(left, right);
|
|
255
|
+
public int GetHashCode(object value) => System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(value);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
package/Runtime/SceneWorld.cs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections.Generic;
|
|
3
|
+
using System.Diagnostics.CodeAnalysis;
|
|
3
4
|
using Delta.ECS;
|
|
4
5
|
using Delta.ECS.Integration;
|
|
5
6
|
using UnityEngine;
|
|
@@ -69,6 +70,20 @@ namespace Delta.ECS.Unity
|
|
|
69
70
|
return false;
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
/// <summary>Resolves the live ECS world and entity currently associated with a Unity view.</summary>
|
|
74
|
+
public static bool TryGetBoundEntity(GameObject view, [NotNullWhen(true)] out World world, out Entity entity)
|
|
75
|
+
{
|
|
76
|
+
if (view != null && TryFindLiveWorld(view, out SceneWorld sceneWorld, out entity))
|
|
77
|
+
{
|
|
78
|
+
world = sceneWorld.World;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
world = null;
|
|
83
|
+
entity = default;
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
72
87
|
public Entity[] AuthoredEntities
|
|
73
88
|
{
|
|
74
89
|
get
|
|
@@ -104,7 +119,7 @@ namespace Delta.ECS.Unity
|
|
|
104
119
|
|
|
105
120
|
internal static SceneWorld CreatePreview(SceneData sceneData)
|
|
106
121
|
{
|
|
107
|
-
var world = new World(
|
|
122
|
+
var world = new World(CreateComponentLayouts(), DefaultEntityCapacity);
|
|
108
123
|
try
|
|
109
124
|
{
|
|
110
125
|
return new SceneWorld(world, sceneData, null,
|
|
@@ -124,7 +139,7 @@ namespace Delta.ECS.Unity
|
|
|
124
139
|
UnityThrowHelpers.ThrowArgumentNull(nameof(authoring));
|
|
125
140
|
}
|
|
126
141
|
|
|
127
|
-
var world = new World(
|
|
142
|
+
var world = new World(CreateComponentLayouts(), DefaultEntityCapacity);
|
|
128
143
|
try
|
|
129
144
|
{
|
|
130
145
|
return new SceneWorld(world, authoring.SceneData, authoring,
|
|
@@ -144,7 +159,7 @@ namespace Delta.ECS.Unity
|
|
|
144
159
|
UnityThrowHelpers.ThrowArgumentNull(nameof(authoring));
|
|
145
160
|
}
|
|
146
161
|
|
|
147
|
-
var world = new World(
|
|
162
|
+
var world = new World(CreateComponentLayouts(), RuntimeEntityCapacity);
|
|
148
163
|
try
|
|
149
164
|
{
|
|
150
165
|
return new SceneWorld(world, authoring.SceneData, authoring,
|
|
@@ -157,6 +172,17 @@ namespace Delta.ECS.Unity
|
|
|
157
172
|
}
|
|
158
173
|
}
|
|
159
174
|
|
|
175
|
+
private static ComponentLayoutRegistry CreateComponentLayouts()
|
|
176
|
+
{
|
|
177
|
+
var layouts = new ComponentLayoutRegistry();
|
|
178
|
+
foreach (IGeneratedComponentRegistration registration in GeneratedComponentCatalog.GetRegistrations())
|
|
179
|
+
{
|
|
180
|
+
layouts.Register(registration);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return layouts;
|
|
184
|
+
}
|
|
185
|
+
|
|
160
186
|
internal void RebuildAuthoringEntities()
|
|
161
187
|
{
|
|
162
188
|
ThrowIfDisposed();
|
|
@@ -212,6 +238,11 @@ namespace Delta.ECS.Unity
|
|
|
212
238
|
continue;
|
|
213
239
|
}
|
|
214
240
|
|
|
241
|
+
if (descriptor.IsTag)
|
|
242
|
+
{
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
|
|
215
246
|
object value = data.CreateValue(descriptor.ValueType, ResolveEntity);
|
|
216
247
|
if (_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out _)
|
|
217
248
|
&& !_integration.TryWrite(entity, descriptor.Id, value, snapshot.Stamp, out _, out EcsWriteError error))
|
|
@@ -341,7 +372,7 @@ namespace Delta.ECS.Unity
|
|
|
341
372
|
{
|
|
342
373
|
if (TryGetEntity(authoring, out Entity entity))
|
|
343
374
|
{
|
|
344
|
-
return
|
|
375
|
+
return TryRead(entity, descriptor, out snapshot, out error);
|
|
345
376
|
}
|
|
346
377
|
|
|
347
378
|
snapshot = default;
|
|
@@ -349,13 +380,50 @@ namespace Delta.ECS.Unity
|
|
|
349
380
|
return false;
|
|
350
381
|
}
|
|
351
382
|
|
|
383
|
+
internal bool TryRead(Entity entity, ComponentDescriptor descriptor,
|
|
384
|
+
out ComponentSnapshot snapshot, out EcsReadError error)
|
|
385
|
+
=> _integration.TryRead(entity, descriptor.Id, out snapshot, out error);
|
|
386
|
+
|
|
387
|
+
internal bool TryGetComponents(Entity entity, Span<ComponentId> destination, out int totalCount)
|
|
388
|
+
{
|
|
389
|
+
totalCount = 0;
|
|
390
|
+
if (!_integration.IsAlive(entity))
|
|
391
|
+
{
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
ReadOnlyMemory<ComponentDescriptor> components = _integration.Catalog.Components;
|
|
396
|
+
for (int index = 0; index < components.Length; index++)
|
|
397
|
+
{
|
|
398
|
+
ComponentId component = components.Span[index].Id;
|
|
399
|
+
if (!_world.Has(entity, component))
|
|
400
|
+
{
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (totalCount < destination.Length)
|
|
405
|
+
{
|
|
406
|
+
destination[totalCount] = component;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
totalCount++;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
|
|
352
415
|
internal bool TryWrite(EntityAuthoring authoring, ComponentData data,
|
|
353
416
|
ComponentDescriptor descriptor, object value, out EcsWriteError error)
|
|
354
417
|
{
|
|
355
|
-
if (!TryGetEntity(authoring, out Entity entity)
|
|
356
|
-
|| !_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out _))
|
|
418
|
+
if (!TryGetEntity(authoring, out Entity entity) || !_integration.IsAlive(entity))
|
|
357
419
|
{
|
|
358
|
-
error =
|
|
420
|
+
error = new EcsWriteError(EcsWriteErrorCode.EntityNotAlive);
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (!_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out _))
|
|
425
|
+
{
|
|
426
|
+
error = new EcsWriteError(EcsWriteErrorCode.ComponentMissing);
|
|
359
427
|
return false;
|
|
360
428
|
}
|
|
361
429
|
|
|
@@ -364,7 +432,15 @@ namespace Delta.ECS.Unity
|
|
|
364
432
|
return false;
|
|
365
433
|
}
|
|
366
434
|
|
|
367
|
-
|
|
435
|
+
if (descriptor.IsTag)
|
|
436
|
+
{
|
|
437
|
+
data.StoreDefaultTag();
|
|
438
|
+
}
|
|
439
|
+
else
|
|
440
|
+
{
|
|
441
|
+
data.StoreValue(value, GetStableIdOrEmpty);
|
|
442
|
+
}
|
|
443
|
+
|
|
368
444
|
return true;
|
|
369
445
|
}
|
|
370
446
|
|
|
@@ -395,6 +471,13 @@ namespace Delta.ECS.Unity
|
|
|
395
471
|
return false;
|
|
396
472
|
}
|
|
397
473
|
|
|
474
|
+
if (descriptor.IsTag)
|
|
475
|
+
{
|
|
476
|
+
data.StoreDefaultTag();
|
|
477
|
+
error = default;
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
|
|
398
481
|
object value = data.CreateValue(descriptor.ValueType, ResolveEntity);
|
|
399
482
|
if (!_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out EcsReadError readError))
|
|
400
483
|
{
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#nullable enable
|
|
2
|
+
|
|
3
|
+
using System;
|
|
4
|
+
using System.Diagnostics.CodeAnalysis;
|
|
5
|
+
using Delta.ECS;
|
|
6
|
+
using UnityEngine;
|
|
7
|
+
|
|
8
|
+
namespace Delta.ECS.Unity
|
|
9
|
+
{
|
|
10
|
+
public static class SceneWorldExtensions
|
|
11
|
+
{
|
|
12
|
+
/// <summary>Returns the entity bound to this GameObject, or the default entity when no binding exists.</summary>
|
|
13
|
+
/// <param name="world">The bound live ECS world, or <see langword="null"/> when no binding exists.</param>
|
|
14
|
+
public static Entity GetEntity(this GameObject? view, out World? world)
|
|
15
|
+
{
|
|
16
|
+
return TryGetEntity(view, out Entity entity, out world) ? entity : default;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// <summary>Returns whether this GameObject is bound to a live ECS entity.</summary>
|
|
20
|
+
public static bool TryGetEntity(
|
|
21
|
+
this GameObject? view,
|
|
22
|
+
out Entity entity,
|
|
23
|
+
[NotNullWhen(true)] out World? world)
|
|
24
|
+
{
|
|
25
|
+
if (view != null && SceneWorld.TryGetBoundEntity(view, out World boundWorld, out entity))
|
|
26
|
+
{
|
|
27
|
+
world = boundWorld;
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
entity = default;
|
|
32
|
+
world = null;
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// <summary>Returns the entity bound to this MonoBehaviour, or the default entity when no binding exists.</summary>
|
|
37
|
+
/// <param name="world">The bound live ECS world, or <see langword="null"/> when no binding exists.</param>
|
|
38
|
+
public static Entity GetEntity(this MonoBehaviour? behaviour, out World? world)
|
|
39
|
+
{
|
|
40
|
+
return TryGetEntity(behaviour, out Entity entity, out world) ? entity : default;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// <summary>Returns whether this MonoBehaviour is bound to a live ECS entity.</summary>
|
|
44
|
+
public static bool TryGetEntity(
|
|
45
|
+
this MonoBehaviour? behaviour,
|
|
46
|
+
out Entity entity,
|
|
47
|
+
[NotNullWhen(true)] out World? world)
|
|
48
|
+
{
|
|
49
|
+
if (behaviour != null)
|
|
50
|
+
{
|
|
51
|
+
return behaviour.gameObject.TryGetEntity(out entity, out world);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
entity = default;
|
|
55
|
+
world = null;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
package/Runtime.meta
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.artromskiy.deltaecs.unity",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.40",
|
|
4
4
|
"displayName": "DeltaECS Unity",
|
|
5
5
|
"description": "Unity scene authoring and editor integration for DeltaECS.",
|
|
6
6
|
"unity": "6000.7",
|
|
@@ -23,9 +23,15 @@
|
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"Runtime/",
|
|
26
|
+
"Runtime.meta",
|
|
26
27
|
"Editor/",
|
|
28
|
+
"Editor.meta",
|
|
27
29
|
"README.md",
|
|
30
|
+
"README.md.meta",
|
|
28
31
|
"CHANGELOG.md",
|
|
29
|
-
"
|
|
32
|
+
"CHANGELOG.md.meta",
|
|
33
|
+
"LICENSE.md",
|
|
34
|
+
"LICENSE.md.meta",
|
|
35
|
+
"package.json.meta"
|
|
30
36
|
]
|
|
31
37
|
}
|