com.artromskiy.deltaecs.unity 0.0.61 → 0.0.63
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/Editor/ComponentDropdown.cs +8 -9
- package/Editor/ComponentPropertyBagFields.cs +2 -3
- package/Editor/HierarchyNodeHandler.cs +28 -2
- package/Editor/SceneEntityInspectorView.cs +147 -144
- package/README.md +1 -1
- package/Runtime/ComponentData.cs +5 -6
- package/Runtime/SceneWorld.cs +56 -113
- package/Runtime/ViewComponents.cs +16 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|
|
3
3
|
using System.Linq;
|
|
4
4
|
using System.Reflection;
|
|
5
5
|
|
|
6
|
-
using Delta.ECS.Integration;
|
|
7
6
|
|
|
8
7
|
using UnityEditor.IMGUI.Controls;
|
|
9
8
|
|
|
@@ -13,13 +12,13 @@ namespace Delta.ECS.Unity.Editor
|
|
|
13
12
|
{
|
|
14
13
|
internal sealed class ComponentDropdown : AdvancedDropdown
|
|
15
14
|
{
|
|
16
|
-
private readonly
|
|
17
|
-
private readonly Func<
|
|
18
|
-
private readonly Action<
|
|
19
|
-
private readonly Dictionary<int,
|
|
15
|
+
private readonly ComponentId[] _components;
|
|
16
|
+
private readonly Func<ComponentId, string> _getMenuPath;
|
|
17
|
+
private readonly Action<ComponentId> _add;
|
|
18
|
+
private readonly Dictionary<int, ComponentId> _items = new();
|
|
20
19
|
|
|
21
|
-
public ComponentDropdown(
|
|
22
|
-
Func<
|
|
20
|
+
public ComponentDropdown(ComponentId[] components,
|
|
21
|
+
Func<ComponentId, string> getMenuPath, Action<ComponentId> add)
|
|
23
22
|
: base(new AdvancedDropdownState())
|
|
24
23
|
{
|
|
25
24
|
_components = components;
|
|
@@ -67,9 +66,9 @@ namespace Delta.ECS.Unity.Editor
|
|
|
67
66
|
|
|
68
67
|
protected override void ItemSelected(AdvancedDropdownItem item)
|
|
69
68
|
{
|
|
70
|
-
if (_items.TryGetValue(item.id, out
|
|
69
|
+
if (_items.TryGetValue(item.id, out ComponentId componentId))
|
|
71
70
|
{
|
|
72
|
-
_add(
|
|
71
|
+
_add(componentId);
|
|
73
72
|
}
|
|
74
73
|
}
|
|
75
74
|
}
|
|
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|
|
3
3
|
|
|
4
4
|
using Delta;
|
|
5
5
|
using Delta.ECS;
|
|
6
|
-
using Delta.ECS.Integration;
|
|
7
6
|
using Delta.ECS.Unity;
|
|
8
7
|
|
|
9
8
|
using Unity.Properties;
|
|
@@ -19,7 +18,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
19
18
|
|
|
20
19
|
internal static class ComponentPropertyBagFields
|
|
21
20
|
{
|
|
22
|
-
internal static ComponentPropertyBinding[] Build(VisualElement parent,
|
|
21
|
+
internal static ComponentPropertyBinding[] Build(VisualElement parent, Type componentType,
|
|
23
22
|
object value, bool canWrite, Action<string[], object> onChanged,
|
|
24
23
|
Func<string, Entity, Action<object>, VisualElement> createEntityField)
|
|
25
24
|
{
|
|
@@ -28,7 +27,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
28
27
|
return Array.Empty<ComponentPropertyBinding>();
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
IPropertyBag propertyBag = PropertyBag.GetPropertyBag(
|
|
30
|
+
IPropertyBag propertyBag = PropertyBag.GetPropertyBag(componentType);
|
|
32
31
|
if (propertyBag == null)
|
|
33
32
|
{
|
|
34
33
|
return Array.Empty<ComponentPropertyBinding>();
|
|
@@ -20,6 +20,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
20
20
|
{
|
|
21
21
|
private const double RuntimeHierarchyRefreshInterval = 0.5d;
|
|
22
22
|
private static readonly ComponentId[] NoRequiredComponents = Array.Empty<ComponentId>();
|
|
23
|
+
private static readonly SchemaId HiddenEntitySchema = new(ViewComponentSchemaIds.HideFromEntityHierarchy);
|
|
23
24
|
private static double _nextRuntimeHierarchyRefresh;
|
|
24
25
|
private static bool _wasPlaying;
|
|
25
26
|
private static readonly HashSet<HierarchyNodeHandler> Instances = new();
|
|
@@ -269,6 +270,30 @@ namespace Delta.ECS.Unity.Editor
|
|
|
269
270
|
return true;
|
|
270
271
|
}
|
|
271
272
|
|
|
273
|
+
private static bool IsHiddenFromHierarchy(
|
|
274
|
+
EntityAuthoring authoring,
|
|
275
|
+
SceneWorld runtimeWorld,
|
|
276
|
+
Entity runtimeEntity)
|
|
277
|
+
{
|
|
278
|
+
if (runtimeWorld != null && runtimeWorld.World.IsAlive(runtimeEntity))
|
|
279
|
+
{
|
|
280
|
+
return runtimeWorld.World.Has(runtimeEntity, runtimeWorld.HiddenEntityHierarchyComponentId);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
IList<ComponentData> components = authoring.Components;
|
|
284
|
+
for (int index = 0; index < components.Count; index++)
|
|
285
|
+
{
|
|
286
|
+
if (components[index] != null
|
|
287
|
+
&& components[index].TryGetSchemaId(out SchemaId schema)
|
|
288
|
+
&& schema == HiddenEntitySchema)
|
|
289
|
+
{
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
|
|
272
297
|
private void BindToView(HierarchyView view) => OnBindView(view);
|
|
273
298
|
|
|
274
299
|
private void OnEntityNameChanged(ChangeEvent<string> evt)
|
|
@@ -458,7 +483,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
458
483
|
|| (runtimeWorld != null
|
|
459
484
|
&& runtimeWorld.World.IsAlive(runtimeEntity)
|
|
460
485
|
&& runtimeWorld.TryGetView(runtimeEntity, out _));
|
|
461
|
-
if (hasView)
|
|
486
|
+
if (hasView || IsHiddenFromHierarchy(authoring, runtimeWorld, runtimeEntity))
|
|
462
487
|
{
|
|
463
488
|
continue;
|
|
464
489
|
}
|
|
@@ -569,7 +594,8 @@ namespace Delta.ECS.Unity.Editor
|
|
|
569
594
|
HierarchyNode sceneNode,
|
|
570
595
|
SceneWorld runtimeWorld)
|
|
571
596
|
{
|
|
572
|
-
Query query = runtimeWorld.World.
|
|
597
|
+
Query query = runtimeWorld.World.WhereNone(runtimeWorld.HiddenEntityHierarchyComponentId)
|
|
598
|
+
.WhereAll(NoRequiredComponents);
|
|
573
599
|
bool changed = false;
|
|
574
600
|
runtimeWorld.World.ForEachEntity(in query, entity =>
|
|
575
601
|
{
|
|
@@ -4,7 +4,6 @@ using System.Linq;
|
|
|
4
4
|
|
|
5
5
|
using Delta;
|
|
6
6
|
using Delta.ECS;
|
|
7
|
-
using Delta.ECS.Integration;
|
|
8
7
|
|
|
9
8
|
using UnityEditor;
|
|
10
9
|
using UnityEditor.UIElements;
|
|
@@ -191,19 +190,15 @@ namespace Delta.ECS.Unity.Editor
|
|
|
191
190
|
|
|
192
191
|
private static Label CreateEntityIcon() => CreateClassLabel("◆", "ecs-entity-icon");
|
|
193
192
|
|
|
194
|
-
private
|
|
195
|
-
IReadOnlyDictionary<ulong, ComponentDescriptor> descriptors)
|
|
196
|
-
{
|
|
197
|
-
ulong? schema = GetSchemaId(data);
|
|
198
|
-
return schema.HasValue && descriptors.TryGetValue(schema.Value, out ComponentDescriptor descriptor)
|
|
199
|
-
? descriptor
|
|
200
|
-
: null;
|
|
201
|
-
}
|
|
193
|
+
private ComponentRegistry Components => (_target.IsRuntime ? _target.RuntimeWorld : _previewWorld).World.Components;
|
|
202
194
|
|
|
203
|
-
private
|
|
195
|
+
private ComponentId? TryGetComponentId(ComponentData data)
|
|
196
|
+
=> _previewWorld.TryGetComponentId(data, out ComponentId componentId) ? componentId : null;
|
|
197
|
+
|
|
198
|
+
private string GetComponentMenuPath(ComponentId componentId)
|
|
204
199
|
{
|
|
205
|
-
string namespacePath =
|
|
206
|
-
string shortName = GetShortTypeName(
|
|
200
|
+
string namespacePath = Components.GetComponentType(componentId).Namespace?.Replace('.', '/') ?? string.Empty;
|
|
201
|
+
string shortName = GetShortTypeName(Components.GetComponentType(componentId));
|
|
207
202
|
return string.IsNullOrEmpty(namespacePath) ? shortName : $"{namespacePath}/{shortName}";
|
|
208
203
|
}
|
|
209
204
|
|
|
@@ -414,26 +409,26 @@ namespace Delta.ECS.Unity.Editor
|
|
|
414
409
|
});
|
|
415
410
|
}
|
|
416
411
|
|
|
417
|
-
private VisualElement BuildAuthoringComponentCard(EntityAuthoring authoring, ComponentData data,
|
|
412
|
+
private VisualElement BuildAuthoringComponentCard(EntityAuthoring authoring, ComponentData data, ComponentId componentId)
|
|
418
413
|
{
|
|
419
|
-
return BuildComponentCard(
|
|
414
|
+
return BuildComponentCard(componentId, body =>
|
|
420
415
|
{
|
|
421
|
-
if (
|
|
416
|
+
if (Components.IsTag(componentId))
|
|
422
417
|
{
|
|
423
418
|
body.Add(CreateClassLabel("Tag · membership only", "ecs-empty-component"));
|
|
424
419
|
return;
|
|
425
420
|
}
|
|
426
421
|
|
|
427
|
-
if (!_previewWorld.TryRead(authoring,
|
|
422
|
+
if (!_previewWorld.TryRead(authoring, componentId, out object value))
|
|
428
423
|
{
|
|
429
|
-
body.Add(new HelpBox(
|
|
424
|
+
body.Add(new HelpBox("Could not read component.", HelpBoxMessageType.Error));
|
|
430
425
|
return;
|
|
431
426
|
}
|
|
432
427
|
|
|
433
|
-
DrawEditableValue(body, authoring, data,
|
|
428
|
+
DrawEditableValue(body, authoring, data, componentId, value);
|
|
434
429
|
},
|
|
435
|
-
|
|
436
|
-
() => RemoveComponent(authoring, data,
|
|
430
|
+
Components.IsTag(componentId) ? null : () => ResetComponent(authoring, data, componentId),
|
|
431
|
+
() => RemoveComponent(authoring, data, componentId));
|
|
437
432
|
}
|
|
438
433
|
|
|
439
434
|
private VisualElement BuildUnknownComponentCard(EntityAuthoring authoring, ComponentData data)
|
|
@@ -462,23 +457,22 @@ namespace Delta.ECS.Unity.Editor
|
|
|
462
457
|
.Where(schema => schema.HasValue)
|
|
463
458
|
.Select(schema => schema.Value)
|
|
464
459
|
.ToHashSet();
|
|
465
|
-
|
|
466
|
-
_previewWorld.
|
|
467
|
-
|
|
468
|
-
&& !existingSchemas.Contains(descriptor.Schema.Value));
|
|
460
|
+
ComponentId[] available = Array.FindAll(
|
|
461
|
+
_previewWorld.World.Components.GetComponentIds().ToArray(),
|
|
462
|
+
componentId => !existingSchemas.Contains(Components.GetSchemaId(componentId).Value));
|
|
469
463
|
button.SetEnabled(available.Length != 0);
|
|
470
464
|
button.clicked += () => new ComponentDropdown(available, GetComponentMenuPath,
|
|
471
|
-
|
|
465
|
+
componentId => AddComponent(authoring, componentId))
|
|
472
466
|
.Show(button.worldBound);
|
|
473
467
|
return button;
|
|
474
468
|
}
|
|
475
469
|
|
|
476
|
-
private VisualElement BuildComponentCard(
|
|
470
|
+
private VisualElement BuildComponentCard(ComponentId componentId, Action<VisualElement> buildBody,
|
|
477
471
|
Action resetComponent = null, Action removeComponent = null)
|
|
478
472
|
{
|
|
479
|
-
bool expanded = IsComponentExpanded(
|
|
480
|
-
return BuildComponentFoldout(GetShortTypeName(
|
|
481
|
-
header => AddComponentActions(header,
|
|
473
|
+
bool expanded = IsComponentExpanded(Components.GetSchemaId(componentId).Value);
|
|
474
|
+
return BuildComponentFoldout(GetShortTypeName(Components.GetComponentType(componentId)), Components.GetSchemaId(componentId).Value, expanded, buildBody,
|
|
475
|
+
header => AddComponentActions(header, componentId, resetComponent, removeComponent));
|
|
482
476
|
}
|
|
483
477
|
|
|
484
478
|
private Foldout BuildComponentFoldout(string title, ulong? schema, bool expanded,
|
|
@@ -517,19 +511,19 @@ namespace Delta.ECS.Unity.Editor
|
|
|
517
511
|
body.Clear();
|
|
518
512
|
if (schema.HasValue)
|
|
519
513
|
{
|
|
520
|
-
_runtimeBindings.RemoveAll(binding => binding.
|
|
514
|
+
_runtimeBindings.RemoveAll(binding => Components.GetSchemaId(binding.Component).Value == schema.Value);
|
|
521
515
|
}
|
|
522
516
|
}
|
|
523
517
|
});
|
|
524
518
|
return foldout;
|
|
525
519
|
}
|
|
526
520
|
|
|
527
|
-
private void AddComponentActions(Toggle header,
|
|
521
|
+
private void AddComponentActions(Toggle header, ComponentId componentId,
|
|
528
522
|
Action resetComponent, Action removeComponent)
|
|
529
523
|
{
|
|
530
524
|
var actions = CreateComponentMenu();
|
|
531
|
-
actions.menu.AppendAction("Move Up", _ => MoveComponent(
|
|
532
|
-
actions.menu.AppendAction("Move Down", _ => MoveComponent(
|
|
525
|
+
actions.menu.AppendAction("Move Up", _ => MoveComponent(Components.GetSchemaId(componentId).Value, -1));
|
|
526
|
+
actions.menu.AppendAction("Move Down", _ => MoveComponent(Components.GetSchemaId(componentId).Value, 1));
|
|
533
527
|
if (resetComponent != null || removeComponent != null)
|
|
534
528
|
{
|
|
535
529
|
actions.menu.AppendSeparator();
|
|
@@ -545,33 +539,31 @@ namespace Delta.ECS.Unity.Editor
|
|
|
545
539
|
}
|
|
546
540
|
|
|
547
541
|
private void DrawEditableValue(VisualElement body, EntityAuthoring authoring, ComponentData data,
|
|
548
|
-
|
|
542
|
+
ComponentId componentId, object value)
|
|
549
543
|
{
|
|
550
|
-
bool canWrite = (descriptor.Capabilities & ComponentCapabilities.Write) != 0
|
|
551
|
-
&& descriptor.ValueType.IsValueType;
|
|
552
544
|
int previousChildCount = body.childCount;
|
|
553
|
-
ComponentPropertyBinding[] bindings = ComponentPropertyBagFields.Build(body,
|
|
554
|
-
|
|
545
|
+
ComponentPropertyBinding[] bindings = ComponentPropertyBagFields.Build(body, Components.GetComponentType(componentId), value,
|
|
546
|
+
true,
|
|
555
547
|
(path, next) =>
|
|
556
548
|
{
|
|
557
549
|
object updated = value;
|
|
558
|
-
if (!PropertyBagValueAccess.TrySetValue(ref updated,
|
|
550
|
+
if (!PropertyBagValueAccess.TrySetValue(ref updated, Components.GetComponentType(componentId), path, next))
|
|
559
551
|
{
|
|
560
|
-
Debug.LogWarning($"Could not edit a property on {
|
|
552
|
+
Debug.LogWarning($"Could not edit a property on {Components.GetComponentType(componentId).FullName ?? Components.GetComponentType(componentId).Name}: the property path is unavailable.", Authoring);
|
|
561
553
|
RefreshContent();
|
|
562
554
|
return;
|
|
563
555
|
}
|
|
564
556
|
|
|
565
557
|
if (Equals(updated, value)) return;
|
|
566
|
-
Undo.RecordObject(Authoring, $"Edit {
|
|
567
|
-
if (_previewWorld.TryWrite(authoring, data,
|
|
558
|
+
Undo.RecordObject(Authoring, $"Edit {Components.GetComponentType(componentId).FullName ?? Components.GetComponentType(componentId).Name}");
|
|
559
|
+
if (_previewWorld.TryWrite(authoring, data, componentId, updated))
|
|
568
560
|
{
|
|
569
561
|
value = updated;
|
|
570
562
|
MarkSceneDirty();
|
|
571
563
|
}
|
|
572
564
|
else
|
|
573
565
|
{
|
|
574
|
-
Debug.LogError($"Could not write {
|
|
566
|
+
Debug.LogError($"Could not write {Components.GetComponentType(componentId).FullName ?? Components.GetComponentType(componentId).Name}.", Authoring);
|
|
575
567
|
RefreshContent();
|
|
576
568
|
}
|
|
577
569
|
},
|
|
@@ -618,47 +610,54 @@ namespace Delta.ECS.Unity.Editor
|
|
|
618
610
|
private void BuildRuntimeEntity()
|
|
619
611
|
{
|
|
620
612
|
_runtimeBindings.Clear();
|
|
621
|
-
SceneWorld
|
|
613
|
+
SceneWorld sceneWorld = _target.RuntimeWorld;
|
|
622
614
|
Entity entity = _target.RuntimeEntity;
|
|
623
|
-
if (
|
|
615
|
+
if (sceneWorld == null || !sceneWorld.IsBound)
|
|
616
|
+
{
|
|
617
|
+
_header.Add(new HelpBox("The selected runtime entity is no longer alive.", HelpBoxMessageType.Warning));
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
World world = sceneWorld.World;
|
|
622
|
+
if (!world.IsAlive(entity))
|
|
624
623
|
{
|
|
625
624
|
_header.Add(new HelpBox("The selected runtime entity is no longer alive.", HelpBoxMessageType.Warning));
|
|
626
625
|
return;
|
|
627
626
|
}
|
|
628
627
|
|
|
629
|
-
_header.Add(BuildRuntimeHeader(
|
|
630
|
-
|
|
628
|
+
_header.Add(BuildRuntimeHeader(sceneWorld, entity));
|
|
629
|
+
ComponentId[] components = ProjectRuntimeComponents(sceneWorld, entity);
|
|
631
630
|
if (components == null)
|
|
632
631
|
{
|
|
633
632
|
_header.Add(new HelpBox("Could not read the selected entity's components.", HelpBoxMessageType.Error));
|
|
634
633
|
return;
|
|
635
634
|
}
|
|
636
635
|
|
|
637
|
-
foreach (
|
|
636
|
+
foreach (ComponentId componentId in components)
|
|
638
637
|
{
|
|
639
|
-
_componentEntries.Add(new ComponentEntry(null,
|
|
638
|
+
_componentEntries.Add(new ComponentEntry(null, componentId));
|
|
640
639
|
}
|
|
641
640
|
|
|
642
641
|
RenderComponentRows();
|
|
643
642
|
}
|
|
644
643
|
|
|
645
|
-
private VisualElement BuildRuntimeComponentCard(SceneWorld world, Entity entity,
|
|
644
|
+
private VisualElement BuildRuntimeComponentCard(SceneWorld world, Entity entity, ComponentId componentId)
|
|
646
645
|
{
|
|
647
|
-
return BuildComponentCard(
|
|
646
|
+
return BuildComponentCard(componentId, body =>
|
|
648
647
|
{
|
|
649
|
-
if (
|
|
648
|
+
if (Components.IsTag(componentId))
|
|
650
649
|
{
|
|
651
650
|
body.Add(CreateClassLabel("Tag · membership only", "ecs-empty-component"));
|
|
652
651
|
return;
|
|
653
652
|
}
|
|
654
653
|
|
|
655
|
-
if (!world.TryRead(entity,
|
|
654
|
+
if (!world.TryRead(entity, componentId, out object value))
|
|
656
655
|
{
|
|
657
|
-
body.Add(new HelpBox(
|
|
656
|
+
body.Add(new HelpBox("Could not read component.", HelpBoxMessageType.Error));
|
|
658
657
|
return;
|
|
659
658
|
}
|
|
660
659
|
|
|
661
|
-
DrawRuntimeValue(body, world, entity,
|
|
660
|
+
DrawRuntimeValue(body, world, entity, componentId, value);
|
|
662
661
|
});
|
|
663
662
|
}
|
|
664
663
|
|
|
@@ -679,9 +678,9 @@ namespace Delta.ECS.Unity.Editor
|
|
|
679
678
|
row.EnableInClassList("ecs-component-row", true);
|
|
680
679
|
row.userData = entry;
|
|
681
680
|
row.Add(_target.IsRuntime
|
|
682
|
-
? BuildRuntimeComponentCard(_target.RuntimeWorld, _target.RuntimeEntity, entry.
|
|
683
|
-
: entry.
|
|
684
|
-
? BuildAuthoringComponentCard(_authoringEntity, entry.Data, entry.
|
|
681
|
+
? BuildRuntimeComponentCard(_target.RuntimeWorld, _target.RuntimeEntity, entry.Component.Value)
|
|
682
|
+
: entry.Component.HasValue
|
|
683
|
+
? BuildAuthoringComponentCard(_authoringEntity, entry.Data, entry.Component.Value)
|
|
685
684
|
: BuildUnknownComponentCard(_authoringEntity, entry.Data));
|
|
686
685
|
}
|
|
687
686
|
|
|
@@ -701,8 +700,8 @@ namespace Delta.ECS.Unity.Editor
|
|
|
701
700
|
|
|
702
701
|
private void UnbindComponentItem(VisualElement row, int index)
|
|
703
702
|
{
|
|
704
|
-
if (row.userData is ComponentEntry entry && entry.
|
|
705
|
-
_runtimeBindings.RemoveAll(binding => binding.
|
|
703
|
+
if (row.userData is ComponentEntry entry && entry.Component.HasValue)
|
|
704
|
+
_runtimeBindings.RemoveAll(binding => Components.GetSchemaId(binding.Component) == Components.GetSchemaId(entry.Component.Value));
|
|
706
705
|
row.userData = null;
|
|
707
706
|
row.Clear();
|
|
708
707
|
}
|
|
@@ -721,8 +720,8 @@ namespace Delta.ECS.Unity.Editor
|
|
|
721
720
|
List<ulong> componentOrder = state.GetComponentOrderSnapshot();
|
|
722
721
|
|
|
723
722
|
ulong[] visibleOrder = _componentEntries
|
|
724
|
-
.Select(entry => entry.
|
|
725
|
-
? (ulong?)entry.
|
|
723
|
+
.Select(entry => entry.Component.HasValue
|
|
724
|
+
? (ulong?)Components.GetSchemaId(entry.Component.Value).Value
|
|
726
725
|
: GetSchemaId(entry.Data))
|
|
727
726
|
.Where(schema => schema.HasValue)
|
|
728
727
|
.Select(schema => schema.Value)
|
|
@@ -730,17 +729,17 @@ namespace Delta.ECS.Unity.Editor
|
|
|
730
729
|
.ToArray();
|
|
731
730
|
HashSet<ulong> visibleSchemas = visibleOrder.ToHashSet();
|
|
732
731
|
|
|
733
|
-
IEnumerable<
|
|
734
|
-
? _previewWorld.
|
|
732
|
+
IEnumerable<ComponentId> catalog = _previewWorld != null
|
|
733
|
+
? _previewWorld.World.Components.GetComponentIds().ToArray()
|
|
735
734
|
: _target.RuntimeWorld != null && _target.RuntimeWorld.IsBound
|
|
736
|
-
? _target.RuntimeWorld.
|
|
737
|
-
: Array.Empty<
|
|
738
|
-
foreach (
|
|
739
|
-
.OrderBy(
|
|
735
|
+
? _target.RuntimeWorld.World.Components.GetComponentIds().ToArray()
|
|
736
|
+
: Array.Empty<ComponentId>();
|
|
737
|
+
foreach (ComponentId componentId in catalog
|
|
738
|
+
.OrderBy(componentId => GetShortTypeName(Components.GetComponentType(componentId)), StringComparer.Ordinal))
|
|
740
739
|
{
|
|
741
|
-
if (!componentOrder.Contains(
|
|
740
|
+
if (!componentOrder.Contains(Components.GetSchemaId(componentId).Value))
|
|
742
741
|
{
|
|
743
|
-
componentOrder.Add(
|
|
742
|
+
componentOrder.Add(Components.GetSchemaId(componentId).Value);
|
|
744
743
|
}
|
|
745
744
|
}
|
|
746
745
|
|
|
@@ -764,9 +763,9 @@ namespace Delta.ECS.Unity.Editor
|
|
|
764
763
|
state.SetComponentOrder(componentOrder);
|
|
765
764
|
}
|
|
766
765
|
|
|
767
|
-
private
|
|
766
|
+
private ComponentId[] ProjectRuntimeComponents(SceneWorld world, Entity entity)
|
|
768
767
|
{
|
|
769
|
-
|
|
768
|
+
ReadOnlySpan<ComponentId> catalog = world.World.Components.GetComponentIds();
|
|
770
769
|
_runtimeComponentBuffer = new ComponentId[catalog.Length];
|
|
771
770
|
if (!world.TryGetComponents(entity, _runtimeComponentBuffer, out int count))
|
|
772
771
|
{
|
|
@@ -776,19 +775,14 @@ namespace Delta.ECS.Unity.Editor
|
|
|
776
775
|
|
|
777
776
|
_runtimeComponentIds = new ComponentId[count];
|
|
778
777
|
Array.Copy(_runtimeComponentBuffer, _runtimeComponentIds, count);
|
|
779
|
-
|
|
780
|
-
.ToDictionary(descriptor => descriptor.Id);
|
|
781
|
-
|
|
782
|
-
return OrderComponentDescriptors(_runtimeComponentIds
|
|
783
|
-
.Where(descriptorsById.ContainsKey)
|
|
784
|
-
.Select(id => descriptorsById[id]));
|
|
778
|
+
return OrderComponents(_runtimeComponentIds);
|
|
785
779
|
}
|
|
786
780
|
|
|
787
|
-
private
|
|
781
|
+
private ComponentId[] OrderComponents(IEnumerable<ComponentId> componentIds)
|
|
788
782
|
{
|
|
789
|
-
return
|
|
790
|
-
.OrderBy(
|
|
791
|
-
.ThenBy(
|
|
783
|
+
return componentIds
|
|
784
|
+
.OrderBy(componentId => GetComponentOrder(Components.GetSchemaId(componentId).Value))
|
|
785
|
+
.ThenBy(componentId => GetShortTypeName(Components.GetComponentType(componentId)), StringComparer.Ordinal)
|
|
792
786
|
.ToArray();
|
|
793
787
|
}
|
|
794
788
|
|
|
@@ -811,19 +805,17 @@ namespace Delta.ECS.Unity.Editor
|
|
|
811
805
|
}
|
|
812
806
|
|
|
813
807
|
private void DrawRuntimeValue(VisualElement body, SceneWorld world, Entity entity,
|
|
814
|
-
|
|
808
|
+
ComponentId componentId, object value)
|
|
815
809
|
{
|
|
816
|
-
bool canWrite = (descriptor.Capabilities & ComponentCapabilities.Write) != 0
|
|
817
|
-
&& descriptor.ValueType.IsValueType;
|
|
818
810
|
int previousChildCount = body.childCount;
|
|
819
|
-
ComponentPropertyBinding[] properties = ComponentPropertyBagFields.Build(body,
|
|
820
|
-
|
|
821
|
-
(path, next) => WriteRuntimeField(world, entity,
|
|
811
|
+
ComponentPropertyBinding[] properties = ComponentPropertyBagFields.Build(body, Components.GetComponentType(componentId),
|
|
812
|
+
value, true,
|
|
813
|
+
(path, next) => WriteRuntimeField(world, entity, componentId, path, next),
|
|
822
814
|
(label, current, onChanged) => CreateRuntimeEntityReferenceField(world, label, current, onChanged));
|
|
823
815
|
|
|
824
816
|
if (properties.Length > 0)
|
|
825
817
|
{
|
|
826
|
-
_runtimeBindings.Add(new RuntimeValueBinding(
|
|
818
|
+
_runtimeBindings.Add(new RuntimeValueBinding(componentId, properties));
|
|
827
819
|
}
|
|
828
820
|
else if (body.childCount == previousChildCount)
|
|
829
821
|
{
|
|
@@ -831,18 +823,19 @@ namespace Delta.ECS.Unity.Editor
|
|
|
831
823
|
}
|
|
832
824
|
}
|
|
833
825
|
|
|
834
|
-
private VisualElement CreateRuntimeEntityReferenceField(SceneWorld
|
|
826
|
+
private VisualElement CreateRuntimeEntityReferenceField(SceneWorld sceneWorld, string label, Entity current,
|
|
835
827
|
Action<object> onChanged)
|
|
836
828
|
{
|
|
837
|
-
|
|
829
|
+
World world = sceneWorld.World;
|
|
830
|
+
Entity[] authored = sceneWorld.AuthoredEntities;
|
|
838
831
|
var values = new List<Entity>(authored.Length + 2) { default };
|
|
839
832
|
var options = new List<string>(authored.Length + 2) { "None" };
|
|
840
833
|
var names = new List<string>(authored.Length);
|
|
841
834
|
for (int i = 0; i < authored.Length; i++)
|
|
842
835
|
{
|
|
843
836
|
Entity candidate = authored[i];
|
|
844
|
-
if (!world.
|
|
845
|
-
names.Add(GetRuntimeEntityName(
|
|
837
|
+
if (!world.IsAlive(candidate)) continue;
|
|
838
|
+
names.Add(GetRuntimeEntityName(sceneWorld, candidate));
|
|
846
839
|
}
|
|
847
840
|
|
|
848
841
|
HashSet<string> duplicateNames = names
|
|
@@ -856,9 +849,9 @@ namespace Delta.ECS.Unity.Editor
|
|
|
856
849
|
for (int i = 0; i < authored.Length; i++)
|
|
857
850
|
{
|
|
858
851
|
Entity candidate = authored[i];
|
|
859
|
-
if (!world.
|
|
852
|
+
if (!world.IsAlive(candidate)) continue;
|
|
860
853
|
string name = names[nameIndex++];
|
|
861
|
-
string stableId =
|
|
854
|
+
string stableId = sceneWorld.TryGetStableId(candidate, out string id) ? id : string.Empty;
|
|
862
855
|
values.Add(candidate);
|
|
863
856
|
options.Add(duplicateNames.Contains(name) && !string.IsNullOrEmpty(stableId)
|
|
864
857
|
? $"{name} ({stableId.Substring(0, Math.Min(8, stableId.Length))})"
|
|
@@ -869,7 +862,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
869
862
|
if (current.IsValid && currentIndex < 0)
|
|
870
863
|
{
|
|
871
864
|
values.Add(current);
|
|
872
|
-
options.Add($"Current ({FormatValue(typeof(Entity), current,
|
|
865
|
+
options.Add($"Current ({FormatValue(typeof(Entity), current, sceneWorld)})");
|
|
873
866
|
currentIndex = values.Count - 1;
|
|
874
867
|
}
|
|
875
868
|
|
|
@@ -893,27 +886,27 @@ namespace Delta.ECS.Unity.Editor
|
|
|
893
886
|
: entity.ToString();
|
|
894
887
|
}
|
|
895
888
|
|
|
896
|
-
private void WriteRuntimeField(SceneWorld world, Entity entity,
|
|
889
|
+
private void WriteRuntimeField(SceneWorld world, Entity entity, ComponentId componentId,
|
|
897
890
|
string[] path, object next)
|
|
898
891
|
{
|
|
899
|
-
if (!world.
|
|
892
|
+
if (!world.TryRead(entity, componentId, out object value))
|
|
900
893
|
{
|
|
901
|
-
Debug.LogWarning($"Could not read {
|
|
894
|
+
Debug.LogWarning($"Could not read {Components.GetComponentType(componentId).FullName ?? Components.GetComponentType(componentId).Name} before editing.");
|
|
902
895
|
RefreshRuntimeView();
|
|
903
896
|
return;
|
|
904
897
|
}
|
|
905
898
|
|
|
906
|
-
object updated =
|
|
907
|
-
if (!PropertyBagValueAccess.TrySetValue(ref updated,
|
|
899
|
+
object updated = value;
|
|
900
|
+
if (!PropertyBagValueAccess.TrySetValue(ref updated, Components.GetComponentType(componentId), path, next))
|
|
908
901
|
{
|
|
909
|
-
Debug.LogWarning($"Could not edit {
|
|
902
|
+
Debug.LogWarning($"Could not edit {Components.GetComponentType(componentId).FullName ?? Components.GetComponentType(componentId).Name}: the property path is unavailable.");
|
|
910
903
|
RefreshRuntimeView();
|
|
911
904
|
return;
|
|
912
905
|
}
|
|
913
906
|
|
|
914
|
-
if (!world.
|
|
907
|
+
if (!world.TryWrite(entity, componentId, updated))
|
|
915
908
|
{
|
|
916
|
-
Debug.LogWarning($"Could not edit {
|
|
909
|
+
Debug.LogWarning($"Could not edit {Components.GetComponentType(componentId).FullName ?? Components.GetComponentType(componentId).Name}.");
|
|
917
910
|
RefreshRuntimeView();
|
|
918
911
|
}
|
|
919
912
|
}
|
|
@@ -951,9 +944,23 @@ namespace Delta.ECS.Unity.Editor
|
|
|
951
944
|
return;
|
|
952
945
|
}
|
|
953
946
|
|
|
954
|
-
SceneWorld
|
|
947
|
+
SceneWorld sceneWorld = _target.RuntimeWorld;
|
|
955
948
|
Entity entity = _target.RuntimeEntity;
|
|
956
|
-
if (
|
|
949
|
+
if (sceneWorld == null || !sceneWorld.IsBound)
|
|
950
|
+
{
|
|
951
|
+
if (_runtimeComponentIds != null)
|
|
952
|
+
{
|
|
953
|
+
_runtimeComponentIds = null;
|
|
954
|
+
_runtimeComponentBuffer = null;
|
|
955
|
+
_runtimeBindings.Clear();
|
|
956
|
+
RefreshContent();
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
World world = sceneWorld.World;
|
|
963
|
+
if (!world.IsAlive(entity))
|
|
957
964
|
{
|
|
958
965
|
if (_runtimeComponentIds != null)
|
|
959
966
|
{
|
|
@@ -972,7 +979,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
972
979
|
return;
|
|
973
980
|
}
|
|
974
981
|
|
|
975
|
-
if (!
|
|
982
|
+
if (!sceneWorld.TryGetComponents(entity, _runtimeComponentBuffer, out int count)
|
|
976
983
|
|| count != _runtimeComponentIds.Length)
|
|
977
984
|
{
|
|
978
985
|
RefreshContent();
|
|
@@ -991,7 +998,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
991
998
|
for (int i = 0; i < _runtimeBindings.Count; i++)
|
|
992
999
|
{
|
|
993
1000
|
RuntimeValueBinding binding = _runtimeBindings[i];
|
|
994
|
-
if (!
|
|
1001
|
+
if (!sceneWorld.TryRead(entity, binding.Component, out object componentValue))
|
|
995
1002
|
{
|
|
996
1003
|
continue;
|
|
997
1004
|
}
|
|
@@ -1006,10 +1013,10 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1006
1013
|
continue;
|
|
1007
1014
|
}
|
|
1008
1015
|
|
|
1009
|
-
if (PropertyBagValueAccess.TryGetValue(
|
|
1010
|
-
property.Path, out object
|
|
1016
|
+
if (PropertyBagValueAccess.TryGetValue(componentValue, Components.GetComponentType(binding.Component),
|
|
1017
|
+
property.Path, out object fieldValue))
|
|
1011
1018
|
{
|
|
1012
|
-
SetRuntimeFieldValue(control, property.ValueType,
|
|
1019
|
+
SetRuntimeFieldValue(control, property.ValueType, fieldValue, sceneWorld);
|
|
1013
1020
|
}
|
|
1014
1021
|
}
|
|
1015
1022
|
}
|
|
@@ -1085,26 +1092,22 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1085
1092
|
|
|
1086
1093
|
private ComponentEntry[] ProjectAuthoringComponents(EntityAuthoring authoring)
|
|
1087
1094
|
{
|
|
1088
|
-
Dictionary<ulong, ComponentDescriptor> descriptors = _previewWorld.Integration.Catalog.Components
|
|
1089
|
-
.ToArray()
|
|
1090
|
-
.ToDictionary(descriptor => descriptor.Schema.Value);
|
|
1091
|
-
|
|
1092
1095
|
return authoring.Components
|
|
1093
|
-
.Select(data => new ComponentEntry(data,
|
|
1094
|
-
.OrderBy(entry => entry.
|
|
1095
|
-
.ThenBy(entry => entry.
|
|
1096
|
-
? GetShortTypeName(entry.
|
|
1096
|
+
.Select(data => new ComponentEntry(data, TryGetComponentId(data)))
|
|
1097
|
+
.OrderBy(entry => entry.Component.HasValue ? GetComponentOrder(Components.GetSchemaId(entry.Component.Value).Value) : int.MaxValue)
|
|
1098
|
+
.ThenBy(entry => entry.Component.HasValue
|
|
1099
|
+
? GetShortTypeName(Components.GetComponentType(entry.Component.Value))
|
|
1097
1100
|
: entry.Data?.SchemaIdText ?? string.Empty, StringComparer.Ordinal)
|
|
1098
1101
|
.ToArray();
|
|
1099
1102
|
}
|
|
1100
1103
|
|
|
1101
|
-
private void AddComponent(EntityAuthoring authoring,
|
|
1104
|
+
private void AddComponent(EntityAuthoring authoring, ComponentId componentId)
|
|
1102
1105
|
{
|
|
1103
|
-
Undo.RecordObject(Authoring, $"Add {GetShortTypeName(
|
|
1104
|
-
ComponentData data = ComponentData.CreateDefault(
|
|
1105
|
-
if (!_previewWorld.AddComponent(authoring,
|
|
1106
|
+
Undo.RecordObject(Authoring, $"Add {GetShortTypeName(Components.GetComponentType(componentId))}");
|
|
1107
|
+
ComponentData data = ComponentData.CreateDefault(Components, componentId);
|
|
1108
|
+
if (!_previewWorld.AddComponent(authoring, componentId, data, out string failureReason))
|
|
1106
1109
|
{
|
|
1107
|
-
Debug.LogError($"Could not add {GetShortTypeName(
|
|
1110
|
+
Debug.LogError($"Could not add {GetShortTypeName(Components.GetComponentType(componentId))}: {failureReason}.", Authoring);
|
|
1108
1111
|
RebuildPreviewAndView();
|
|
1109
1112
|
return;
|
|
1110
1113
|
}
|
|
@@ -1115,16 +1118,16 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1115
1118
|
}
|
|
1116
1119
|
|
|
1117
1120
|
private void RemoveComponent(EntityAuthoring authoring, ComponentData data,
|
|
1118
|
-
|
|
1121
|
+
ComponentId? componentId = null)
|
|
1119
1122
|
{
|
|
1120
1123
|
int index = authoring.Components.IndexOf(data);
|
|
1121
1124
|
if (index < 0 || index >= authoring.Components.Count) return;
|
|
1122
|
-
if (!
|
|
1125
|
+
if (!componentId.HasValue && _previewWorld.TryGetComponentId(data, out ComponentId resolved))
|
|
1123
1126
|
{
|
|
1124
|
-
|
|
1127
|
+
componentId = resolved;
|
|
1125
1128
|
}
|
|
1126
1129
|
|
|
1127
|
-
if (!
|
|
1130
|
+
if (!componentId.HasValue)
|
|
1128
1131
|
{
|
|
1129
1132
|
Undo.RecordObject(Authoring, "Remove Unregistered Delta ECS Component");
|
|
1130
1133
|
authoring.Components.RemoveAt(index);
|
|
@@ -1133,11 +1136,11 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1133
1136
|
return;
|
|
1134
1137
|
}
|
|
1135
1138
|
|
|
1136
|
-
|
|
1137
|
-
Undo.RecordObject(Authoring, $"Remove {GetShortTypeName(component
|
|
1138
|
-
if (!_previewWorld.RemoveComponent(authoring, component
|
|
1139
|
+
ComponentId component = componentId.Value;
|
|
1140
|
+
Undo.RecordObject(Authoring, $"Remove {GetShortTypeName(Components.GetComponentType(component))}");
|
|
1141
|
+
if (!_previewWorld.RemoveComponent(authoring, component))
|
|
1139
1142
|
{
|
|
1140
|
-
Debug.LogError($"Could not remove {GetShortTypeName(component
|
|
1143
|
+
Debug.LogError($"Could not remove {GetShortTypeName(Components.GetComponentType(component))}.", Authoring);
|
|
1141
1144
|
return;
|
|
1142
1145
|
}
|
|
1143
1146
|
|
|
@@ -1146,18 +1149,18 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1146
1149
|
RebuildPreviewAndView();
|
|
1147
1150
|
}
|
|
1148
1151
|
|
|
1149
|
-
private void ResetComponent(EntityAuthoring authoring, ComponentData data,
|
|
1152
|
+
private void ResetComponent(EntityAuthoring authoring, ComponentData data, ComponentId componentId)
|
|
1150
1153
|
{
|
|
1151
|
-
Undo.RecordObject(Authoring, $"Reset {GetShortTypeName(
|
|
1152
|
-
object value = Activator.CreateInstance(
|
|
1153
|
-
if (_previewWorld.TryWrite(authoring, data,
|
|
1154
|
-
else Debug.LogError($"Could not reset {GetShortTypeName(
|
|
1154
|
+
Undo.RecordObject(Authoring, $"Reset {GetShortTypeName(Components.GetComponentType(componentId))}");
|
|
1155
|
+
object value = Activator.CreateInstance(Components.GetComponentType(componentId));
|
|
1156
|
+
if (_previewWorld.TryWrite(authoring, data, componentId, value)) MarkSceneDirty();
|
|
1157
|
+
else Debug.LogError($"Could not reset {GetShortTypeName(Components.GetComponentType(componentId))}.", Authoring);
|
|
1155
1158
|
RefreshContent();
|
|
1156
1159
|
}
|
|
1157
1160
|
|
|
1158
1161
|
private void MoveComponent(ulong schema, int direction)
|
|
1159
1162
|
{
|
|
1160
|
-
int index = _componentEntries.FindIndex(entry => entry.
|
|
1163
|
+
int index = _componentEntries.FindIndex(entry => entry.Component.HasValue && Components.GetSchemaId(entry.Component.Value).Value == schema);
|
|
1161
1164
|
int next = index + direction;
|
|
1162
1165
|
if (index < 0 || next < 0 || next >= _componentEntries.Count) return;
|
|
1163
1166
|
_componentList.viewController.Move(index, next);
|
|
@@ -1201,22 +1204,22 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1201
1204
|
private readonly struct ComponentEntry
|
|
1202
1205
|
{
|
|
1203
1206
|
public readonly ComponentData Data;
|
|
1204
|
-
public readonly
|
|
1205
|
-
public ComponentEntry(ComponentData data,
|
|
1207
|
+
public readonly ComponentId? Component;
|
|
1208
|
+
public ComponentEntry(ComponentData data, ComponentId? componentId)
|
|
1206
1209
|
{
|
|
1207
1210
|
Data = data;
|
|
1208
|
-
|
|
1211
|
+
Component = componentId;
|
|
1209
1212
|
}
|
|
1210
1213
|
}
|
|
1211
1214
|
|
|
1212
1215
|
private readonly struct RuntimeValueBinding
|
|
1213
1216
|
{
|
|
1214
|
-
public readonly
|
|
1217
|
+
public readonly ComponentId Component;
|
|
1215
1218
|
public readonly ComponentPropertyBinding[] Properties;
|
|
1216
1219
|
|
|
1217
|
-
public RuntimeValueBinding(
|
|
1220
|
+
public RuntimeValueBinding(ComponentId componentId, ComponentPropertyBinding[] properties)
|
|
1218
1221
|
{
|
|
1219
|
-
|
|
1222
|
+
Component = componentId;
|
|
1220
1223
|
Properties = properties;
|
|
1221
1224
|
}
|
|
1222
1225
|
}
|
package/README.md
CHANGED
package/Runtime/ComponentData.cs
CHANGED
|
@@ -2,7 +2,6 @@ using System;
|
|
|
2
2
|
using System.Collections.Generic;
|
|
3
3
|
|
|
4
4
|
using Delta.ECS;
|
|
5
|
-
using Delta.ECS.Integration;
|
|
6
5
|
|
|
7
6
|
using UnityEngine;
|
|
8
7
|
|
|
@@ -28,15 +27,15 @@ namespace Delta.ECS.Unity
|
|
|
28
27
|
_json = json;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
public static ComponentData CreateDefault(
|
|
30
|
+
public static ComponentData CreateDefault(ComponentRegistry components, ComponentId componentId)
|
|
32
31
|
{
|
|
33
|
-
if (
|
|
32
|
+
if (components.IsTag(componentId))
|
|
34
33
|
{
|
|
35
|
-
return new ComponentData(
|
|
34
|
+
return new ComponentData(components.GetSchemaId(componentId).Value, "{}");
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
object value = Activator.CreateInstance(
|
|
39
|
-
return new ComponentData(
|
|
37
|
+
object value = Activator.CreateInstance(components.GetComponentType(componentId));
|
|
38
|
+
return new ComponentData(components.GetSchemaId(componentId).Value, JsonUtility.ToJson(value));
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
public bool TryGetSchemaId(out SchemaId schemaId)
|
package/Runtime/SceneWorld.cs
CHANGED
|
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|
|
3
3
|
using System.Diagnostics.CodeAnalysis;
|
|
4
4
|
|
|
5
5
|
using Delta.ECS;
|
|
6
|
-
using Delta.ECS.Integration;
|
|
7
6
|
|
|
8
7
|
using UnityEngine;
|
|
9
8
|
using UnityEngine.SceneManagement;
|
|
@@ -25,10 +24,10 @@ namespace Delta.ECS.Unity
|
|
|
25
24
|
private readonly Dictionary<Entity, GameObject> _viewsByEntity = new();
|
|
26
25
|
private readonly Dictionary<UnityEngine.EntityId, Entity> _entitiesByView = new();
|
|
27
26
|
private readonly World _world;
|
|
28
|
-
private readonly IEcsWorld _integration;
|
|
29
27
|
private readonly SceneData _sceneData;
|
|
30
28
|
private readonly SceneAuthoring _authoring;
|
|
31
29
|
private readonly bool _ownsWorld;
|
|
30
|
+
private readonly ComponentId _hiddenEntityHierarchyComponentId;
|
|
32
31
|
private bool _disposed;
|
|
33
32
|
|
|
34
33
|
public World World => _world;
|
|
@@ -42,27 +41,21 @@ namespace Delta.ECS.Unity
|
|
|
42
41
|
return entities;
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
|
-
internal
|
|
44
|
+
internal ComponentId HiddenEntityHierarchyComponentId => _hiddenEntityHierarchyComponentId;
|
|
46
45
|
internal SceneData SceneData => _sceneData;
|
|
47
46
|
internal Scene UnityScene => _authoring != null ? _authoring.gameObject.scene : default;
|
|
48
47
|
internal bool IsBound => !_disposed;
|
|
49
48
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
{
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private SceneWorld(World world, SceneData sceneData,
|
|
56
|
-
SceneAuthoring authoring, bool ownsWorld, bool registerLiveWorld)
|
|
49
|
+
private SceneWorld(World world,
|
|
50
|
+
SceneData sceneData, SceneAuthoring authoring, bool ownsWorld, bool registerLiveWorld)
|
|
57
51
|
{
|
|
58
52
|
_world = world ?? UnityThrowHelpers.ThrowArgumentNull<World>(nameof(world));
|
|
59
53
|
_sceneData = sceneData ?? UnityThrowHelpers.ThrowArgumentNull<SceneData>(nameof(sceneData));
|
|
60
54
|
_authoring = authoring;
|
|
61
|
-
_integration = world;
|
|
62
55
|
_ownsWorld = ownsWorld;
|
|
56
|
+
_hiddenEntityHierarchyComponentId = world.Components.GetPrimary<HideFromEntityHierarchy>();
|
|
63
57
|
|
|
64
58
|
_sceneData.EnsureStableIds();
|
|
65
|
-
_integration.Initialize();
|
|
66
59
|
RebuildAuthoringEntities();
|
|
67
60
|
if (registerLiveWorld)
|
|
68
61
|
{
|
|
@@ -70,7 +63,7 @@ namespace Delta.ECS.Unity
|
|
|
70
63
|
}
|
|
71
64
|
}
|
|
72
65
|
|
|
73
|
-
/// <summary>Returns the
|
|
66
|
+
/// <summary>Returns the runtime context for a loaded Unity scene.</summary>
|
|
74
67
|
public static SceneWorld GetForScene(Scene scene) => SceneWorldRuntime.GetForScene(scene);
|
|
75
68
|
|
|
76
69
|
/// <summary>Resolves the live ECS world and entity currently associated with a Unity view.</summary>
|
|
@@ -90,7 +83,7 @@ namespace Delta.ECS.Unity
|
|
|
90
83
|
/// <summary>Registers a transient runtime association; it is not written into scene data.</summary>
|
|
91
84
|
public bool BindView(Entity entity, GameObject view)
|
|
92
85
|
{
|
|
93
|
-
if (view == null || !
|
|
86
|
+
if (view == null || !_world.IsAlive(entity))
|
|
94
87
|
{
|
|
95
88
|
return false;
|
|
96
89
|
}
|
|
@@ -125,7 +118,7 @@ namespace Delta.ECS.Unity
|
|
|
125
118
|
{
|
|
126
119
|
foreach (Entity candidate in _entitiesByStableId.Values)
|
|
127
120
|
{
|
|
128
|
-
if (
|
|
121
|
+
if (_world.IsAlive(candidate) && _world.Has(candidate, componentId))
|
|
129
122
|
{
|
|
130
123
|
entity = candidate;
|
|
131
124
|
return true;
|
|
@@ -156,7 +149,6 @@ namespace Delta.ECS.Unity
|
|
|
156
149
|
_stableIdsByEntity.Clear();
|
|
157
150
|
_viewsByEntity.Clear();
|
|
158
151
|
_entitiesByView.Clear();
|
|
159
|
-
_integration.Shutdown();
|
|
160
152
|
|
|
161
153
|
if (_ownsWorld)
|
|
162
154
|
{
|
|
@@ -217,7 +209,7 @@ namespace Delta.ECS.Unity
|
|
|
217
209
|
|
|
218
210
|
internal static SceneWorld CreatePreview(SceneData sceneData)
|
|
219
211
|
{
|
|
220
|
-
|
|
212
|
+
World world = CreateWorld(DefaultEntityCapacity);
|
|
221
213
|
try
|
|
222
214
|
{
|
|
223
215
|
return new SceneWorld(world, sceneData, null,
|
|
@@ -237,7 +229,7 @@ namespace Delta.ECS.Unity
|
|
|
237
229
|
UnityThrowHelpers.ThrowArgumentNull(nameof(authoring));
|
|
238
230
|
}
|
|
239
231
|
|
|
240
|
-
|
|
232
|
+
World world = CreateWorld(DefaultEntityCapacity);
|
|
241
233
|
try
|
|
242
234
|
{
|
|
243
235
|
return new SceneWorld(world, authoring.SceneData, authoring,
|
|
@@ -257,7 +249,7 @@ namespace Delta.ECS.Unity
|
|
|
257
249
|
UnityThrowHelpers.ThrowArgumentNull(nameof(authoring));
|
|
258
250
|
}
|
|
259
251
|
|
|
260
|
-
|
|
252
|
+
World world = CreateWorld(RuntimeEntityCapacity);
|
|
261
253
|
try
|
|
262
254
|
{
|
|
263
255
|
return new SceneWorld(world, authoring.SceneData, authoring,
|
|
@@ -292,10 +284,10 @@ namespace Delta.ECS.Unity
|
|
|
292
284
|
for (int componentIndex = 0; componentIndex < authoring.Components.Count; componentIndex++)
|
|
293
285
|
{
|
|
294
286
|
ComponentData data = authoring.Components[componentIndex];
|
|
295
|
-
if (
|
|
296
|
-
&& seenSchemas.Add(
|
|
287
|
+
if (TryGetComponentId(data, out ComponentId componentId)
|
|
288
|
+
&& seenSchemas.Add(_world.Components.GetSchemaId(componentId).Value))
|
|
297
289
|
{
|
|
298
|
-
componentIds.Add(
|
|
290
|
+
componentIds.Add(componentId);
|
|
299
291
|
}
|
|
300
292
|
else
|
|
301
293
|
{
|
|
@@ -303,7 +295,7 @@ namespace Delta.ECS.Unity
|
|
|
303
295
|
}
|
|
304
296
|
}
|
|
305
297
|
|
|
306
|
-
Entity entity =
|
|
298
|
+
Entity entity = _world.Create(componentIds.ToArray());
|
|
307
299
|
_entitiesByStableId.Add(authoring.StableId, entity);
|
|
308
300
|
_stableIdsByEntity.Add(entity, authoring.StableId);
|
|
309
301
|
}
|
|
@@ -320,21 +312,21 @@ namespace Delta.ECS.Unity
|
|
|
320
312
|
for (int componentIndex = 0; componentIndex < authoring.Components.Count; componentIndex++)
|
|
321
313
|
{
|
|
322
314
|
ComponentData data = authoring.Components[componentIndex];
|
|
323
|
-
if (!
|
|
315
|
+
if (!TryGetComponentId(data, out ComponentId componentId))
|
|
324
316
|
{
|
|
325
317
|
continue;
|
|
326
318
|
}
|
|
327
319
|
|
|
328
|
-
if (
|
|
320
|
+
if (_world.Components.IsTag(componentId))
|
|
329
321
|
{
|
|
330
322
|
continue;
|
|
331
323
|
}
|
|
332
324
|
|
|
333
|
-
object value = data.CreateValue(
|
|
334
|
-
if (
|
|
335
|
-
&& !
|
|
325
|
+
object value = data.CreateValue(_world.Components.GetComponentType(componentId), ResolveEntity);
|
|
326
|
+
if (TryRead(entity, componentId, out _)
|
|
327
|
+
&& !_world.TryWrite(entity, componentId, value))
|
|
336
328
|
{
|
|
337
|
-
Debug.LogError($"Failed to load {
|
|
329
|
+
Debug.LogError($"Failed to load {_world.Components.GetComponentType(componentId).FullName ?? _world.Components.GetComponentType(componentId).Name} on '{authoring.Name}'.");
|
|
338
330
|
}
|
|
339
331
|
}
|
|
340
332
|
}
|
|
@@ -366,7 +358,7 @@ namespace Delta.ECS.Unity
|
|
|
366
358
|
internal bool TryGetEntity(GameObject view, out Entity entity)
|
|
367
359
|
{
|
|
368
360
|
if (view != null && _entitiesByView.TryGetValue(view.GetEntityId(), out entity)
|
|
369
|
-
&&
|
|
361
|
+
&& _world.IsAlive(entity))
|
|
370
362
|
{
|
|
371
363
|
return true;
|
|
372
364
|
}
|
|
@@ -374,7 +366,7 @@ namespace Delta.ECS.Unity
|
|
|
374
366
|
if (view != null && _authoring != null
|
|
375
367
|
&& _authoring.TryGetStableId(view, out string stableId)
|
|
376
368
|
&& _entitiesByStableId.TryGetValue(stableId, out entity)
|
|
377
|
-
&&
|
|
369
|
+
&& _world.IsAlive(entity))
|
|
378
370
|
{
|
|
379
371
|
return true;
|
|
380
372
|
}
|
|
@@ -383,56 +375,42 @@ namespace Delta.ECS.Unity
|
|
|
383
375
|
return false;
|
|
384
376
|
}
|
|
385
377
|
|
|
386
|
-
internal bool
|
|
378
|
+
internal bool TryGetComponentId(ComponentData data, out ComponentId componentId)
|
|
387
379
|
{
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return false;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
ReadOnlyMemory<ComponentDescriptor> catalog = _integration.Catalog.Components;
|
|
395
|
-
for (int i = 0; i < catalog.Length; i++)
|
|
396
|
-
{
|
|
397
|
-
if (catalog.Span[i].Schema == schema)
|
|
398
|
-
{
|
|
399
|
-
descriptor = catalog.Span[i];
|
|
400
|
-
return true;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return false;
|
|
380
|
+
componentId = ComponentId.Invalid;
|
|
381
|
+
return data != null && data.TryGetSchemaId(out SchemaId schema)
|
|
382
|
+
&& _world.Components.TryGetComponentId(schema, out componentId);
|
|
405
383
|
}
|
|
406
384
|
|
|
407
|
-
internal bool TryRead(EntityAuthoring authoring,
|
|
408
|
-
out ComponentSnapshot snapshot, out EcsReadError error)
|
|
385
|
+
internal bool TryRead(EntityAuthoring authoring, ComponentId componentId, out object? value)
|
|
409
386
|
{
|
|
410
387
|
if (TryGetEntity(authoring, out Entity entity))
|
|
411
388
|
{
|
|
412
|
-
return TryRead(entity,
|
|
389
|
+
return TryRead(entity, componentId, out value);
|
|
413
390
|
}
|
|
414
391
|
|
|
415
|
-
|
|
416
|
-
error = default;
|
|
392
|
+
value = null;
|
|
417
393
|
return false;
|
|
418
394
|
}
|
|
419
395
|
|
|
420
|
-
internal bool TryRead(Entity entity,
|
|
421
|
-
|
|
422
|
-
|
|
396
|
+
internal bool TryRead(Entity entity, ComponentId componentId, out object? value)
|
|
397
|
+
=> _world.TryRead(entity, componentId, out value);
|
|
398
|
+
|
|
399
|
+
internal bool TryWrite(Entity entity, ComponentId componentId, object value)
|
|
400
|
+
=> _world.TryWrite(entity, componentId, value);
|
|
423
401
|
|
|
424
402
|
internal bool TryGetComponents(Entity entity, Span<ComponentId> destination, out int totalCount)
|
|
425
403
|
{
|
|
426
404
|
totalCount = 0;
|
|
427
|
-
if (!
|
|
405
|
+
if (!_world.IsAlive(entity))
|
|
428
406
|
{
|
|
429
407
|
return false;
|
|
430
408
|
}
|
|
431
409
|
|
|
432
|
-
|
|
410
|
+
ReadOnlySpan<ComponentId> components = _world.Components.GetComponentIds();
|
|
433
411
|
for (int index = 0; index < components.Length; index++)
|
|
434
412
|
{
|
|
435
|
-
ComponentId component = components
|
|
413
|
+
ComponentId component = components[index];
|
|
436
414
|
if (!_world.Has(entity, component))
|
|
437
415
|
{
|
|
438
416
|
continue;
|
|
@@ -450,26 +428,14 @@ namespace Delta.ECS.Unity
|
|
|
450
428
|
}
|
|
451
429
|
|
|
452
430
|
internal bool TryWrite(EntityAuthoring authoring, ComponentData data,
|
|
453
|
-
|
|
431
|
+
ComponentId componentId, object value)
|
|
454
432
|
{
|
|
455
|
-
if (!TryGetEntity(authoring, out Entity entity) || !
|
|
433
|
+
if (!TryGetEntity(authoring, out Entity entity) || !_world.TryWrite(entity, componentId, value))
|
|
456
434
|
{
|
|
457
|
-
error = new EcsWriteError(EcsWriteErrorCode.EntityNotAlive);
|
|
458
435
|
return false;
|
|
459
436
|
}
|
|
460
437
|
|
|
461
|
-
if (
|
|
462
|
-
{
|
|
463
|
-
error = new EcsWriteError(EcsWriteErrorCode.ComponentMissing);
|
|
464
|
-
return false;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (!_integration.TryWrite(entity, descriptor.Id, value, out error))
|
|
468
|
-
{
|
|
469
|
-
return false;
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
if (descriptor.IsTag)
|
|
438
|
+
if (_world.Components.IsTag(componentId))
|
|
473
439
|
{
|
|
474
440
|
data.StoreDefaultTag();
|
|
475
441
|
}
|
|
@@ -481,60 +447,41 @@ namespace Delta.ECS.Unity
|
|
|
481
447
|
return true;
|
|
482
448
|
}
|
|
483
449
|
|
|
484
|
-
internal bool AddComponent(EntityAuthoring authoring,
|
|
485
|
-
ComponentData data, out
|
|
450
|
+
internal bool AddComponent(EntityAuthoring authoring, ComponentId componentId,
|
|
451
|
+
ComponentData data, out string failureReason)
|
|
486
452
|
{
|
|
487
453
|
failureReason = null;
|
|
488
454
|
if (!TryGetEntity(authoring, out Entity entity))
|
|
489
455
|
{
|
|
490
|
-
error = new EcsWriteError(EcsWriteErrorCode.EntityNotAlive);
|
|
491
456
|
failureReason = "The authored entity is not bound to the preview world. Rebuild the preview and try again.";
|
|
492
457
|
return false;
|
|
493
458
|
}
|
|
494
459
|
|
|
495
|
-
if (!
|
|
460
|
+
if (!_world.IsAlive(entity))
|
|
496
461
|
{
|
|
497
|
-
error = new EcsWriteError(EcsWriteErrorCode.EntityNotAlive);
|
|
498
462
|
failureReason = "The entity is no longer alive in the preview world.";
|
|
499
463
|
return false;
|
|
500
464
|
}
|
|
501
465
|
|
|
502
|
-
if (!
|
|
466
|
+
if (!_world.Add(entity, componentId))
|
|
503
467
|
{
|
|
504
|
-
|
|
505
|
-
failureReason = _world.Has(entity, descriptor.Id)
|
|
468
|
+
failureReason = _world.Has(entity, componentId)
|
|
506
469
|
? "The component is already present in the preview world."
|
|
507
470
|
: "DeltaECS rejected the structural add without reporting a write error.";
|
|
508
471
|
return false;
|
|
509
472
|
}
|
|
510
473
|
|
|
511
|
-
if (
|
|
474
|
+
if (_world.Components.IsTag(componentId))
|
|
512
475
|
{
|
|
513
476
|
data.StoreDefaultTag();
|
|
514
|
-
error = default;
|
|
515
477
|
return true;
|
|
516
478
|
}
|
|
517
479
|
|
|
518
|
-
object value = data.CreateValue(
|
|
519
|
-
if (!
|
|
480
|
+
object value = data.CreateValue(_world.Components.GetComponentType(componentId), ResolveEntity);
|
|
481
|
+
if (!_world.TryWrite(entity, componentId, value))
|
|
520
482
|
{
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
{
|
|
524
|
-
EcsReadErrorCode.EntityNotAlive => EcsWriteErrorCode.EntityNotAlive,
|
|
525
|
-
EcsReadErrorCode.ComponentUnknown => EcsWriteErrorCode.ComponentUnknown,
|
|
526
|
-
EcsReadErrorCode.ComponentMissing => EcsWriteErrorCode.ComponentMissing,
|
|
527
|
-
EcsReadErrorCode.Unsupported => EcsWriteErrorCode.Unsupported,
|
|
528
|
-
_ => EcsWriteErrorCode.None
|
|
529
|
-
});
|
|
530
|
-
failureReason = $"The new component could not be read from the preview world ({readError.Code}).";
|
|
531
|
-
return false;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
if (!_integration.TryWrite(entity, descriptor.Id, value, out error))
|
|
535
|
-
{
|
|
536
|
-
_integration.Remove(entity, new[] { descriptor.Id });
|
|
537
|
-
failureReason = $"The default component value could not be written ({error.Code}).";
|
|
483
|
+
_world.Remove(entity, componentId);
|
|
484
|
+
failureReason = "The default component value could not be written.";
|
|
538
485
|
return false;
|
|
539
486
|
}
|
|
540
487
|
|
|
@@ -542,13 +489,8 @@ namespace Delta.ECS.Unity
|
|
|
542
489
|
return true;
|
|
543
490
|
}
|
|
544
491
|
|
|
545
|
-
internal bool RemoveComponent(EntityAuthoring authoring,
|
|
546
|
-
out
|
|
547
|
-
{
|
|
548
|
-
error = default;
|
|
549
|
-
return TryGetEntity(authoring, out Entity entity)
|
|
550
|
-
&& _integration.Remove(entity, new[] { descriptor.Id });
|
|
551
|
-
}
|
|
492
|
+
internal bool RemoveComponent(EntityAuthoring authoring, ComponentId componentId)
|
|
493
|
+
=> TryGetEntity(authoring, out Entity entity) && _world.Remove(entity, componentId);
|
|
552
494
|
|
|
553
495
|
internal bool TryGetAuthoring(string stableId, out EntityAuthoring authoring)
|
|
554
496
|
{
|
|
@@ -570,6 +512,7 @@ namespace Delta.ECS.Unity
|
|
|
570
512
|
private static World CreateWorld(int initialEntityCapacity)
|
|
571
513
|
{
|
|
572
514
|
var layouts = new ComponentRegistry();
|
|
515
|
+
layouts.Register<HideFromEntityHierarchy>(new SchemaId(ViewComponentSchemaIds.HideFromEntityHierarchy));
|
|
573
516
|
foreach (IGeneratedComponentRegistration registration in GeneratedComponentCatalog.GetRegistrations())
|
|
574
517
|
{
|
|
575
518
|
layouts.Register(registration);
|
|
@@ -582,9 +525,9 @@ namespace Delta.ECS.Unity
|
|
|
582
525
|
{
|
|
583
526
|
foreach (Entity entity in _entitiesByStableId.Values)
|
|
584
527
|
{
|
|
585
|
-
if (
|
|
528
|
+
if (_world.IsAlive(entity))
|
|
586
529
|
{
|
|
587
|
-
|
|
530
|
+
_world.Destroy(entity);
|
|
588
531
|
}
|
|
589
532
|
}
|
|
590
533
|
}
|
|
@@ -2,6 +2,7 @@ using Delta.ECS;
|
|
|
2
2
|
|
|
3
3
|
namespace Delta.ECS.Unity
|
|
4
4
|
{
|
|
5
|
+
|
|
5
6
|
/// <summary>Receives the entity context after a Unity view is bound to an entity.</summary>
|
|
6
7
|
public interface IEntityView
|
|
7
8
|
{
|
|
@@ -10,7 +11,7 @@ namespace Delta.ECS.Unity
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
/// <summary>Selects the Unity prefab used to represent an entity.</summary>
|
|
13
|
-
[ComponentSchema(
|
|
14
|
+
[ComponentSchema(ViewComponentSchemaIds.ViewToken)]
|
|
14
15
|
public readonly struct ViewToken
|
|
15
16
|
{
|
|
16
17
|
/// <summary>Gets the identifier of the view prefab in a <see cref="ViewPrefabCatalog"/>.</summary>
|
|
@@ -21,8 +22,21 @@ namespace Delta.ECS.Unity
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/// <summary>Marks an entity whose Unity view has already been bound.</summary>
|
|
24
|
-
[ComponentSchema(
|
|
25
|
+
[ComponentSchema(ViewComponentSchemaIds.ViewBound)]
|
|
25
26
|
public struct ViewBound
|
|
26
27
|
{
|
|
27
28
|
}
|
|
29
|
+
|
|
30
|
+
/// <summary>Hides an unbound ECS entity from the Unity Hierarchy window while this tag is present.</summary>
|
|
31
|
+
/// <remarks>Entities bound to a GameObject keep their normal Unity hierarchy visibility.</remarks>
|
|
32
|
+
[ComponentSchema(ViewComponentSchemaIds.HideFromEntityHierarchy)]
|
|
33
|
+
public readonly struct HideFromEntityHierarchy
|
|
34
|
+
{
|
|
35
|
+
}
|
|
36
|
+
internal static class ViewComponentSchemaIds
|
|
37
|
+
{
|
|
38
|
+
internal const ulong ViewToken = 0x405B11F5A17E14A1UL;
|
|
39
|
+
internal const ulong ViewBound = 0xB31CB42A81D3B164UL;
|
|
40
|
+
internal const ulong HideFromEntityHierarchy = 0x8C13A2E9764DB501UL;
|
|
41
|
+
}
|
|
28
42
|
}
|