com.artromskiy.deltaecs.unity 0.0.37 → 0.0.39

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.
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 54aae609d31564e449408ffc4cfe0ffd
@@ -212,6 +212,11 @@ namespace Delta.ECS.Unity
212
212
  continue;
213
213
  }
214
214
 
215
+ if (descriptor.IsTag)
216
+ {
217
+ continue;
218
+ }
219
+
215
220
  object value = data.CreateValue(descriptor.ValueType, ResolveEntity);
216
221
  if (_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out _)
217
222
  && !_integration.TryWrite(entity, descriptor.Id, value, snapshot.Stamp, out _, out EcsWriteError error))
@@ -341,7 +346,7 @@ namespace Delta.ECS.Unity
341
346
  {
342
347
  if (TryGetEntity(authoring, out Entity entity))
343
348
  {
344
- return _integration.TryRead(entity, descriptor.Id, out snapshot, out error);
349
+ return TryRead(entity, descriptor, out snapshot, out error);
345
350
  }
346
351
 
347
352
  snapshot = default;
@@ -349,13 +354,50 @@ namespace Delta.ECS.Unity
349
354
  return false;
350
355
  }
351
356
 
357
+ internal bool TryRead(Entity entity, ComponentDescriptor descriptor,
358
+ out ComponentSnapshot snapshot, out EcsReadError error)
359
+ => _integration.TryRead(entity, descriptor.Id, out snapshot, out error);
360
+
361
+ internal bool TryGetComponents(Entity entity, Span<ComponentId> destination, out int totalCount)
362
+ {
363
+ totalCount = 0;
364
+ if (!_integration.IsAlive(entity))
365
+ {
366
+ return false;
367
+ }
368
+
369
+ ReadOnlyMemory<ComponentDescriptor> components = _integration.Catalog.Components;
370
+ for (int index = 0; index < components.Length; index++)
371
+ {
372
+ ComponentId component = components.Span[index].Id;
373
+ if (!_world.Has(entity, component))
374
+ {
375
+ continue;
376
+ }
377
+
378
+ if (totalCount < destination.Length)
379
+ {
380
+ destination[totalCount] = component;
381
+ }
382
+
383
+ totalCount++;
384
+ }
385
+
386
+ return true;
387
+ }
388
+
352
389
  internal bool TryWrite(EntityAuthoring authoring, ComponentData data,
353
390
  ComponentDescriptor descriptor, object value, out EcsWriteError error)
354
391
  {
355
- if (!TryGetEntity(authoring, out Entity entity)
356
- || !_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out _))
392
+ if (!TryGetEntity(authoring, out Entity entity) || !_integration.IsAlive(entity))
357
393
  {
358
- error = default;
394
+ error = new EcsWriteError(EcsWriteErrorCode.EntityNotAlive);
395
+ return false;
396
+ }
397
+
398
+ if (!_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out _))
399
+ {
400
+ error = new EcsWriteError(EcsWriteErrorCode.ComponentMissing);
359
401
  return false;
360
402
  }
361
403
 
@@ -364,7 +406,15 @@ namespace Delta.ECS.Unity
364
406
  return false;
365
407
  }
366
408
 
367
- data.StoreValue(value, GetStableIdOrEmpty);
409
+ if (descriptor.IsTag)
410
+ {
411
+ data.StoreDefaultTag();
412
+ }
413
+ else
414
+ {
415
+ data.StoreValue(value, GetStableIdOrEmpty);
416
+ }
417
+
368
418
  return true;
369
419
  }
370
420
 
@@ -395,6 +445,13 @@ namespace Delta.ECS.Unity
395
445
  return false;
396
446
  }
397
447
 
448
+ if (descriptor.IsTag)
449
+ {
450
+ data.StoreDefaultTag();
451
+ error = default;
452
+ return true;
453
+ }
454
+
398
455
  object value = data.CreateValue(descriptor.ValueType, ResolveEntity);
399
456
  if (!_integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out EcsReadError readError))
400
457
  {
package/Runtime.meta ADDED
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 849d9b97c54a43d6b100098ea1278f34
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.artromskiy.deltaecs.unity",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
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
- "LICENSE.md"
32
+ "CHANGELOG.md.meta",
33
+ "LICENSE.md",
34
+ "LICENSE.md.meta",
35
+ "package.json.meta"
30
36
  ]
31
37
  }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 97f36ccebac94385907d421b09dd5287