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.
- 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 +1 -1
- package/Runtime/ComponentData.cs +16 -25
- package/Runtime/PropertyBagValueAccess.cs +258 -0
- package/Runtime/PropertyBagValueAccess.cs.meta +2 -0
- package/Runtime/SceneWorld.cs +62 -5
- package/Runtime.meta +8 -0
- package/package.json +8 -2
- package/package.json.meta +2 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections.Generic;
|
|
3
3
|
using System.Linq;
|
|
4
|
-
using System.Reflection;
|
|
5
4
|
using Delta;
|
|
6
5
|
using Delta.ECS;
|
|
7
6
|
using Delta.ECS.Integration;
|
|
@@ -194,10 +193,12 @@ namespace Delta.ECS.Unity.Editor
|
|
|
194
193
|
_header.Add(BuildEntityHeader(authoring));
|
|
195
194
|
_componentEntries.AddRange(ProjectAuthoringComponents(authoring));
|
|
196
195
|
RenderComponentRows();
|
|
196
|
+
_footer.Add(BuildAddComponentMenu(authoring));
|
|
197
197
|
var deleteButton = new Button(() => HierarchyMenu.DeleteEntity(Authoring, authoring.StableId))
|
|
198
198
|
{
|
|
199
199
|
text = "Delete Entity"
|
|
200
200
|
};
|
|
201
|
+
deleteButton.AddToClassList("ecs-action-button");
|
|
201
202
|
deleteButton.AddToClassList("ecs-delete-entity");
|
|
202
203
|
_footer.Add(deleteButton);
|
|
203
204
|
}
|
|
@@ -302,6 +303,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
302
303
|
text = "Unbind",
|
|
303
304
|
tooltip = "Remove the GameObject binding from this entity"
|
|
304
305
|
};
|
|
306
|
+
unbind.AddToClassList("ecs-action-button");
|
|
305
307
|
unbind.SetEnabled(currentView != null);
|
|
306
308
|
field.RegisterValueChangedCallback(evt =>
|
|
307
309
|
{
|
|
@@ -335,6 +337,12 @@ namespace Delta.ECS.Unity.Editor
|
|
|
335
337
|
{
|
|
336
338
|
return BuildComponentCard(descriptor, body =>
|
|
337
339
|
{
|
|
340
|
+
if (descriptor.IsTag)
|
|
341
|
+
{
|
|
342
|
+
body.Add(CreateClassLabel("Tag · membership only", "ecs-empty-component"));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
338
346
|
if (!_previewWorld.TryRead(authoring, descriptor, out ComponentSnapshot snapshot, out EcsReadError readError))
|
|
339
347
|
{
|
|
340
348
|
body.Add(new HelpBox($"Could not read component: {readError.Code}.", HelpBoxMessageType.Error));
|
|
@@ -343,7 +351,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
343
351
|
|
|
344
352
|
DrawEditableValue(body, authoring, data, descriptor, snapshot.Value);
|
|
345
353
|
},
|
|
346
|
-
() => ResetComponent(authoring, data, descriptor),
|
|
354
|
+
descriptor.IsTag ? null : () => ResetComponent(authoring, data, descriptor),
|
|
347
355
|
() => RemoveComponent(authoring, data, descriptor));
|
|
348
356
|
}
|
|
349
357
|
|
|
@@ -366,6 +374,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
366
374
|
private VisualElement BuildAddComponentMenu(EntityAuthoring authoring)
|
|
367
375
|
{
|
|
368
376
|
var button = new Button { text = "Add Component" };
|
|
377
|
+
button.AddToClassList("ecs-action-button");
|
|
369
378
|
button.AddToClassList("ecs-add-component");
|
|
370
379
|
HashSet<ulong> existingSchemas = authoring.Components
|
|
371
380
|
.Select(GetSchemaId)
|
|
@@ -483,25 +492,26 @@ namespace Delta.ECS.Unity.Editor
|
|
|
483
492
|
private void DrawEditableValue(VisualElement body, EntityAuthoring authoring, ComponentData data,
|
|
484
493
|
ComponentDescriptor descriptor, object value)
|
|
485
494
|
{
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
for (int i = 0; i < fields.Length; i++)
|
|
494
|
-
{
|
|
495
|
-
FieldInfo field = fields[i];
|
|
496
|
-
object current = field.GetValue(value);
|
|
497
|
-
VisualElement control = CreateFieldControl(field, current, next =>
|
|
495
|
+
bool canWrite = (descriptor.Capabilities & ComponentCapabilities.Write) != 0
|
|
496
|
+
&& descriptor.ValueType.IsValueType;
|
|
497
|
+
int previousChildCount = body.childCount;
|
|
498
|
+
ComponentPropertyBinding[] bindings = ComponentPropertyBagFields.Build(body, descriptor, value,
|
|
499
|
+
canWrite,
|
|
500
|
+
(path, next) =>
|
|
498
501
|
{
|
|
499
|
-
|
|
502
|
+
object updated = value;
|
|
503
|
+
if (!PropertyBagValueAccess.TrySetValue(ref updated, descriptor.ValueType, path, next))
|
|
504
|
+
{
|
|
505
|
+
Debug.LogWarning($"Could not edit a property on {descriptor.Name}: the property path is unavailable.", Authoring);
|
|
506
|
+
RefreshContent();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (Equals(updated, value)) return;
|
|
500
511
|
Undo.RecordObject(Authoring, $"Edit {descriptor.Name}");
|
|
501
|
-
|
|
502
|
-
if (_previewWorld.TryWrite(authoring, data, descriptor, value, out EcsWriteError writeError))
|
|
512
|
+
if (_previewWorld.TryWrite(authoring, data, descriptor, updated, out EcsWriteError writeError))
|
|
503
513
|
{
|
|
504
|
-
|
|
514
|
+
value = updated;
|
|
505
515
|
MarkSceneDirty();
|
|
506
516
|
}
|
|
507
517
|
else
|
|
@@ -509,66 +519,13 @@ namespace Delta.ECS.Unity.Editor
|
|
|
509
519
|
Debug.LogError($"Could not write {descriptor.Name}: {writeError.Code}.", Authoring);
|
|
510
520
|
RefreshContent();
|
|
511
521
|
}
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
}
|
|
515
|
-
}
|
|
522
|
+
},
|
|
523
|
+
(label, current, onChanged) => CreateEntityReferenceField(label, current, onChanged));
|
|
516
524
|
|
|
517
|
-
|
|
518
|
-
{
|
|
519
|
-
string label = ObjectNames.NicifyVariableName(field.Name);
|
|
520
|
-
Type type = field.FieldType;
|
|
521
|
-
if (type == typeof(float))
|
|
522
|
-
{
|
|
523
|
-
var fieldControl = new FloatField(label) { value = (float)value, isDelayed = true };
|
|
524
|
-
AddInspectorFieldClasses(fieldControl);
|
|
525
|
-
fieldControl.RegisterValueChangedCallback(evt => onChanged(evt.newValue));
|
|
526
|
-
return fieldControl;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
if (type == typeof(byte) || type == typeof(int))
|
|
530
|
-
{
|
|
531
|
-
var fieldControl = new IntegerField(label) { value = Convert.ToInt32(value), isDelayed = true };
|
|
532
|
-
AddInspectorFieldClasses(fieldControl);
|
|
533
|
-
fieldControl.RegisterValueChangedCallback(evt => onChanged(type == typeof(byte)
|
|
534
|
-
? (object)(byte)Mathf.Clamp(evt.newValue, byte.MinValue, byte.MaxValue)
|
|
535
|
-
: evt.newValue));
|
|
536
|
-
return fieldControl;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
if (type == typeof(bool))
|
|
540
|
-
{
|
|
541
|
-
var fieldControl = new Toggle(label) { value = (bool)value };
|
|
542
|
-
AddInspectorFieldClasses(fieldControl);
|
|
543
|
-
fieldControl.RegisterValueChangedCallback(evt => onChanged(evt.newValue));
|
|
544
|
-
return fieldControl;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
if (type == typeof(float3))
|
|
548
|
-
{
|
|
549
|
-
float3 vector = (float3)value;
|
|
550
|
-
var fieldControl = new Vector3Field(label) { value = new Vector3(vector.x, vector.y, vector.z) };
|
|
551
|
-
AddInspectorFieldClasses(fieldControl);
|
|
552
|
-
fieldControl.RegisterValueChangedCallback(evt => onChanged(new float3(evt.newValue.x, evt.newValue.y, evt.newValue.z)));
|
|
553
|
-
return fieldControl;
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
if (type == typeof(Entity))
|
|
557
|
-
{
|
|
558
|
-
return CreateEntityReferenceField(label, (Entity)value, onChanged);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
if (type.IsEnum)
|
|
525
|
+
if (bindings.Length == 0 && body.childCount == previousChildCount)
|
|
562
526
|
{
|
|
563
|
-
|
|
564
|
-
AddInspectorFieldClasses(fieldControl);
|
|
565
|
-
fieldControl.RegisterValueChangedCallback(evt => onChanged(evt.newValue));
|
|
566
|
-
return fieldControl;
|
|
527
|
+
body.Add(CreateClassLabel("Component has no exposed properties.", "ecs-empty-component"));
|
|
567
528
|
}
|
|
568
|
-
|
|
569
|
-
var unsupported = new Label($"{label} · Unsupported: {type.Name}");
|
|
570
|
-
unsupported.AddToClassList("ecs-unsupported-field");
|
|
571
|
-
return unsupported;
|
|
572
529
|
}
|
|
573
530
|
|
|
574
531
|
private VisualElement CreateEntityReferenceField(string label, Entity current, Action<object> onChanged)
|
|
@@ -640,13 +597,19 @@ namespace Delta.ECS.Unity.Editor
|
|
|
640
597
|
{
|
|
641
598
|
return BuildComponentCard(descriptor, body =>
|
|
642
599
|
{
|
|
643
|
-
if (
|
|
600
|
+
if (descriptor.IsTag)
|
|
601
|
+
{
|
|
602
|
+
body.Add(CreateClassLabel("Tag · membership only", "ecs-empty-component"));
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (!world.TryRead(entity, descriptor, out ComponentSnapshot snapshot, out EcsReadError error))
|
|
644
607
|
{
|
|
645
608
|
body.Add(new HelpBox($"Could not read component: {error.Code}.", HelpBoxMessageType.Error));
|
|
646
609
|
return;
|
|
647
610
|
}
|
|
648
611
|
|
|
649
|
-
|
|
612
|
+
DrawRuntimeValue(body, world, entity, descriptor, snapshot);
|
|
650
613
|
});
|
|
651
614
|
}
|
|
652
615
|
|
|
@@ -654,7 +617,6 @@ namespace Delta.ECS.Unity.Editor
|
|
|
654
617
|
{
|
|
655
618
|
_componentItems.Clear();
|
|
656
619
|
_componentItems.AddRange(_componentEntries);
|
|
657
|
-
if (_authoringEntity != null) _componentItems.Add(default);
|
|
658
620
|
_componentList.itemsSource = _componentItems;
|
|
659
621
|
_componentList.Rebuild();
|
|
660
622
|
}
|
|
@@ -662,19 +624,10 @@ namespace Delta.ECS.Unity.Editor
|
|
|
662
624
|
private void BindComponentItem(VisualElement row, int index)
|
|
663
625
|
{
|
|
664
626
|
row.Clear();
|
|
665
|
-
|
|
666
|
-
row.parent.parent.EnableInClassList("ecs-add-component-row", isAddButton);
|
|
667
|
-
row.parent.parent.EnableInClassList("ecs-component-last-bound-row",
|
|
627
|
+
SetReorderableItemClass(row, "ecs-component-last-bound-row",
|
|
668
628
|
_embedded && _target.IsRuntime && index == _componentEntries.Count - 1);
|
|
669
|
-
row.EnableInClassList("ecs-component-row", !isAddButton);
|
|
670
|
-
if (isAddButton)
|
|
671
|
-
{
|
|
672
|
-
row.userData = null;
|
|
673
|
-
row.Add(BuildAddComponentMenu(_authoringEntity));
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
629
|
ComponentEntry entry = _componentItems[index];
|
|
630
|
+
row.EnableInClassList("ecs-component-row", true);
|
|
678
631
|
row.userData = entry;
|
|
679
632
|
row.Add(_target.IsRuntime
|
|
680
633
|
? BuildRuntimeComponentCard(_target.RuntimeWorld, _target.RuntimeEntity, entry.Descriptor.Value)
|
|
@@ -683,6 +636,20 @@ namespace Delta.ECS.Unity.Editor
|
|
|
683
636
|
: BuildUnknownComponentCard(_authoringEntity, entry.Data));
|
|
684
637
|
}
|
|
685
638
|
|
|
639
|
+
private void SetReorderableItemClass(VisualElement row, string className, bool enabled)
|
|
640
|
+
{
|
|
641
|
+
for (VisualElement ancestor = row.parent; ancestor != null && ancestor != _componentList; ancestor = ancestor.parent)
|
|
642
|
+
{
|
|
643
|
+
if (ancestor.Q<VisualElement>(className: "unity-list-view__reorderable-handle") == null)
|
|
644
|
+
{
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
ancestor.EnableInClassList(className, enabled);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
686
653
|
private void UnbindComponentItem(VisualElement row, int index)
|
|
687
654
|
{
|
|
688
655
|
if (row.userData is ComponentEntry entry && entry.Descriptor.HasValue)
|
|
@@ -752,7 +719,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
752
719
|
{
|
|
753
720
|
ReadOnlyMemory<ComponentDescriptor> catalog = world.Integration.Catalog.Components;
|
|
754
721
|
_runtimeComponentBuffer = new ComponentId[catalog.Length];
|
|
755
|
-
if (!world.
|
|
722
|
+
if (!world.TryGetComponents(entity, _runtimeComponentBuffer, out int count))
|
|
756
723
|
{
|
|
757
724
|
_runtimeComponentIds = null;
|
|
758
725
|
return null;
|
|
@@ -794,31 +761,113 @@ namespace Delta.ECS.Unity.Editor
|
|
|
794
761
|
return card;
|
|
795
762
|
}
|
|
796
763
|
|
|
797
|
-
private void
|
|
764
|
+
private void DrawRuntimeValue(VisualElement body, SceneWorld world, Entity entity,
|
|
765
|
+
ComponentDescriptor descriptor, ComponentSnapshot snapshot)
|
|
798
766
|
{
|
|
799
|
-
|
|
800
|
-
|
|
767
|
+
bool canWrite = (descriptor.Capabilities & ComponentCapabilities.Write) != 0
|
|
768
|
+
&& descriptor.ValueType.IsValueType;
|
|
769
|
+
int previousChildCount = body.childCount;
|
|
770
|
+
ComponentPropertyBinding[] properties = ComponentPropertyBagFields.Build(body, descriptor,
|
|
771
|
+
snapshot.Value, canWrite,
|
|
772
|
+
(path, next) => WriteRuntimeField(world, entity, descriptor, path, next),
|
|
773
|
+
(label, current, onChanged) => CreateRuntimeEntityReferenceField(world, label, current, onChanged));
|
|
774
|
+
|
|
775
|
+
if (properties.Length > 0)
|
|
801
776
|
{
|
|
802
|
-
|
|
777
|
+
_runtimeBindings.Add(new RuntimeValueBinding(descriptor, properties));
|
|
778
|
+
}
|
|
779
|
+
else if (body.childCount == previousChildCount)
|
|
780
|
+
{
|
|
781
|
+
body.Add(CreateClassLabel("Component has no exposed properties.", "ecs-empty-component"));
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
private VisualElement CreateRuntimeEntityReferenceField(SceneWorld world, string label, Entity current,
|
|
786
|
+
Action<object> onChanged)
|
|
787
|
+
{
|
|
788
|
+
Entity[] authored = world.AuthoredEntities;
|
|
789
|
+
var values = new List<Entity>(authored.Length + 2) { default };
|
|
790
|
+
var options = new List<string>(authored.Length + 2) { "None" };
|
|
791
|
+
var names = new List<string>(authored.Length);
|
|
792
|
+
for (int i = 0; i < authored.Length; i++)
|
|
793
|
+
{
|
|
794
|
+
Entity candidate = authored[i];
|
|
795
|
+
if (!world.Integration.IsAlive(candidate)) continue;
|
|
796
|
+
names.Add(GetRuntimeEntityName(world, candidate));
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
HashSet<string> duplicateNames = names
|
|
800
|
+
.GroupBy(name => name, StringComparer.Ordinal)
|
|
801
|
+
.Where(group => group.Count() > 1)
|
|
802
|
+
.Select(group => group.Key)
|
|
803
|
+
.ToHashSet(StringComparer.Ordinal);
|
|
804
|
+
|
|
805
|
+
int currentIndex = current.IsValid ? -1 : 0;
|
|
806
|
+
int nameIndex = 0;
|
|
807
|
+
for (int i = 0; i < authored.Length; i++)
|
|
808
|
+
{
|
|
809
|
+
Entity candidate = authored[i];
|
|
810
|
+
if (!world.Integration.IsAlive(candidate)) continue;
|
|
811
|
+
string name = names[nameIndex++];
|
|
812
|
+
string stableId = world.TryGetStableId(candidate, out string id) ? id : string.Empty;
|
|
813
|
+
values.Add(candidate);
|
|
814
|
+
options.Add(duplicateNames.Contains(name) && !string.IsNullOrEmpty(stableId)
|
|
815
|
+
? $"{name} ({stableId.Substring(0, Math.Min(8, stableId.Length))})"
|
|
816
|
+
: name);
|
|
817
|
+
if (candidate == current) currentIndex = values.Count - 1;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (current.IsValid && currentIndex < 0)
|
|
821
|
+
{
|
|
822
|
+
values.Add(current);
|
|
823
|
+
options.Add($"Current ({FormatValue(typeof(Entity), current, world)})");
|
|
824
|
+
currentIndex = values.Count - 1;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
var fieldControl = new DropdownField(label, options, currentIndex);
|
|
828
|
+
AddInspectorFieldClasses(fieldControl);
|
|
829
|
+
fieldControl.userData = new RuntimeEntityReferenceChoices(options.ToArray(), values.ToArray());
|
|
830
|
+
fieldControl.RegisterValueChangedCallback(evt =>
|
|
831
|
+
{
|
|
832
|
+
int index = options.IndexOf(evt.newValue);
|
|
833
|
+
Entity next = index >= 0 && index < values.Count ? values[index] : default;
|
|
834
|
+
onChanged(next);
|
|
835
|
+
});
|
|
836
|
+
return fieldControl;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
private string GetRuntimeEntityName(SceneWorld world, Entity entity)
|
|
840
|
+
{
|
|
841
|
+
return world.TryGetStableId(entity, out string stableId)
|
|
842
|
+
&& world.TryGetAuthoring(stableId, out EntityAuthoring authoring)
|
|
843
|
+
? authoring.Name
|
|
844
|
+
: entity.ToString();
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
private void WriteRuntimeField(SceneWorld world, Entity entity, ComponentDescriptor descriptor,
|
|
848
|
+
string[] path, object next)
|
|
849
|
+
{
|
|
850
|
+
if (!world.Integration.TryRead(entity, descriptor.Id, out ComponentSnapshot snapshot, out EcsReadError readError))
|
|
851
|
+
{
|
|
852
|
+
Debug.LogWarning($"Could not read {descriptor.Name} before editing: {readError.Code}.");
|
|
853
|
+
RefreshRuntimeView();
|
|
803
854
|
return;
|
|
804
855
|
}
|
|
805
856
|
|
|
806
|
-
|
|
807
|
-
|
|
857
|
+
object updated = snapshot.Value;
|
|
858
|
+
if (!PropertyBagValueAccess.TrySetValue(ref updated, descriptor.ValueType, path, next))
|
|
808
859
|
{
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
labels[i] = new TextField(ObjectNames.NicifyVariableName(field.Name))
|
|
813
|
-
{
|
|
814
|
-
value = display,
|
|
815
|
-
isReadOnly = true
|
|
816
|
-
};
|
|
817
|
-
AddInspectorFieldClasses(labels[i]);
|
|
818
|
-
body.Add(labels[i]);
|
|
860
|
+
Debug.LogWarning($"Could not edit {descriptor.Name}: the property path is unavailable.");
|
|
861
|
+
RefreshRuntimeView();
|
|
862
|
+
return;
|
|
819
863
|
}
|
|
820
864
|
|
|
821
|
-
|
|
865
|
+
if (!world.Integration.TryWrite(entity, descriptor.Id, updated, snapshot.Stamp,
|
|
866
|
+
out _, out EcsWriteError writeError))
|
|
867
|
+
{
|
|
868
|
+
Debug.LogWarning($"Could not edit {descriptor.Name}: {writeError.Code}.");
|
|
869
|
+
RefreshRuntimeView();
|
|
870
|
+
}
|
|
822
871
|
}
|
|
823
872
|
|
|
824
873
|
private string FormatValue(Type type, object value, SceneWorld world)
|
|
@@ -842,9 +891,6 @@ namespace Delta.ECS.Unity.Editor
|
|
|
842
891
|
return value?.ToString() ?? "None";
|
|
843
892
|
}
|
|
844
893
|
|
|
845
|
-
private static FieldInfo[] GetComponentFields(Type type) =>
|
|
846
|
-
type.GetFields(BindingFlags.Instance | BindingFlags.Public);
|
|
847
|
-
|
|
848
894
|
private static Label CreateClassLabel(string text, string className)
|
|
849
895
|
{
|
|
850
896
|
var label = new Label(text);
|
|
@@ -887,7 +933,7 @@ namespace Delta.ECS.Unity.Editor
|
|
|
887
933
|
return;
|
|
888
934
|
}
|
|
889
935
|
|
|
890
|
-
if (!world.
|
|
936
|
+
if (!world.TryGetComponents(entity, _runtimeComponentBuffer, out int count)
|
|
891
937
|
|| count != _runtimeComponentIds.Length)
|
|
892
938
|
{
|
|
893
939
|
RefreshContent();
|
|
@@ -911,18 +957,93 @@ namespace Delta.ECS.Unity.Editor
|
|
|
911
957
|
continue;
|
|
912
958
|
}
|
|
913
959
|
|
|
914
|
-
for (int fieldIndex = 0; fieldIndex < binding.
|
|
960
|
+
for (int fieldIndex = 0; fieldIndex < binding.Properties.Length; fieldIndex++)
|
|
915
961
|
{
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
962
|
+
ComponentPropertyBinding property = binding.Properties[fieldIndex];
|
|
963
|
+
VisualElement control = property.Control;
|
|
964
|
+
VisualElement focused = control.panel?.focusController?.focusedElement as VisualElement;
|
|
965
|
+
if (focused != null && control.Contains(focused))
|
|
966
|
+
{
|
|
967
|
+
continue;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
if (PropertyBagValueAccess.TryGetValue(snapshot.Value, binding.Descriptor.ValueType,
|
|
971
|
+
property.Path, out object value))
|
|
919
972
|
{
|
|
920
|
-
|
|
973
|
+
SetRuntimeFieldValue(control, property.ValueType, value, world);
|
|
921
974
|
}
|
|
922
975
|
}
|
|
923
976
|
}
|
|
924
977
|
}
|
|
925
978
|
|
|
979
|
+
private void SetRuntimeFieldValue(VisualElement control, Type type, object value, SceneWorld world)
|
|
980
|
+
{
|
|
981
|
+
if (control is FloatField floatField)
|
|
982
|
+
{
|
|
983
|
+
floatField.SetValueWithoutNotify(value == null ? 0f : (float)value);
|
|
984
|
+
}
|
|
985
|
+
else if (control is DoubleField doubleField)
|
|
986
|
+
{
|
|
987
|
+
doubleField.SetValueWithoutNotify(value == null ? 0d : (double)value);
|
|
988
|
+
}
|
|
989
|
+
else if (control is TextField textField)
|
|
990
|
+
{
|
|
991
|
+
textField.SetValueWithoutNotify(type == typeof(string) ? (string)value ?? string.Empty
|
|
992
|
+
: type == typeof(char) ? value == null ? string.Empty : value.ToString()
|
|
993
|
+
: FormatValue(type, value, world));
|
|
994
|
+
}
|
|
995
|
+
else if (control is IntegerField integerField)
|
|
996
|
+
{
|
|
997
|
+
integerField.SetValueWithoutNotify(value == null ? 0 : Convert.ToInt32(value));
|
|
998
|
+
}
|
|
999
|
+
else if (control is LongField longField)
|
|
1000
|
+
{
|
|
1001
|
+
longField.SetValueWithoutNotify(value == null ? 0L : Convert.ToInt64(value));
|
|
1002
|
+
}
|
|
1003
|
+
else if (control is Toggle toggle)
|
|
1004
|
+
{
|
|
1005
|
+
toggle.SetValueWithoutNotify(value != null && (bool)value);
|
|
1006
|
+
}
|
|
1007
|
+
else if (control is Vector2Field vector2Field && value is Vector2 vector2)
|
|
1008
|
+
{
|
|
1009
|
+
vector2Field.SetValueWithoutNotify(vector2);
|
|
1010
|
+
}
|
|
1011
|
+
else if (control is Vector3Field vectorField && value is Vector3 vector3)
|
|
1012
|
+
{
|
|
1013
|
+
vectorField.SetValueWithoutNotify(vector3);
|
|
1014
|
+
}
|
|
1015
|
+
else if (control is Vector3Field float3Field && value is float3 vector)
|
|
1016
|
+
{
|
|
1017
|
+
float3Field.SetValueWithoutNotify(new Vector3(vector.x, vector.y, vector.z));
|
|
1018
|
+
}
|
|
1019
|
+
else if (control is Vector4Field vector4Field && value is Vector4 vector4)
|
|
1020
|
+
{
|
|
1021
|
+
vector4Field.SetValueWithoutNotify(vector4);
|
|
1022
|
+
}
|
|
1023
|
+
else if (control is ColorField colorField && value is Color color)
|
|
1024
|
+
{
|
|
1025
|
+
colorField.SetValueWithoutNotify(color);
|
|
1026
|
+
}
|
|
1027
|
+
else if (control is EnumField enumField && value is Enum enumValue)
|
|
1028
|
+
{
|
|
1029
|
+
enumField.SetValueWithoutNotify(enumValue);
|
|
1030
|
+
}
|
|
1031
|
+
else if (control is ObjectField objectField)
|
|
1032
|
+
{
|
|
1033
|
+
objectField.SetValueWithoutNotify(value as UnityEngine.Object);
|
|
1034
|
+
}
|
|
1035
|
+
else if (control is DropdownField entityField
|
|
1036
|
+
&& type == typeof(Entity)
|
|
1037
|
+
&& entityField.userData is RuntimeEntityReferenceChoices choices)
|
|
1038
|
+
{
|
|
1039
|
+
int index = Array.IndexOf(choices.Entities, (Entity)value);
|
|
1040
|
+
if (index >= 0)
|
|
1041
|
+
{
|
|
1042
|
+
entityField.SetValueWithoutNotify(choices.Labels[index]);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
926
1047
|
private ComponentEntry[] ProjectAuthoringComponents(EntityAuthoring authoring)
|
|
927
1048
|
{
|
|
928
1049
|
Dictionary<ulong, ComponentDescriptor> descriptors = _previewWorld.Integration.Catalog.Components
|
|
@@ -1089,14 +1210,24 @@ namespace Delta.ECS.Unity.Editor
|
|
|
1089
1210
|
private readonly struct RuntimeValueBinding
|
|
1090
1211
|
{
|
|
1091
1212
|
public readonly ComponentDescriptor Descriptor;
|
|
1092
|
-
public readonly
|
|
1093
|
-
public readonly TextField[] Labels;
|
|
1213
|
+
public readonly ComponentPropertyBinding[] Properties;
|
|
1094
1214
|
|
|
1095
|
-
public RuntimeValueBinding(ComponentDescriptor descriptor,
|
|
1215
|
+
public RuntimeValueBinding(ComponentDescriptor descriptor, ComponentPropertyBinding[] properties)
|
|
1096
1216
|
{
|
|
1097
1217
|
Descriptor = descriptor;
|
|
1098
|
-
|
|
1218
|
+
Properties = properties;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
private sealed class RuntimeEntityReferenceChoices
|
|
1223
|
+
{
|
|
1224
|
+
public readonly string[] Labels;
|
|
1225
|
+
public readonly Entity[] Entities;
|
|
1226
|
+
|
|
1227
|
+
public RuntimeEntityReferenceChoices(string[] labels, Entity[] entities)
|
|
1228
|
+
{
|
|
1099
1229
|
Labels = labels;
|
|
1230
|
+
Entities = entities;
|
|
1100
1231
|
}
|
|
1101
1232
|
}
|
|
1102
1233
|
}
|
package/Editor.meta
ADDED
package/README.md
CHANGED
package/Runtime/ComponentData.cs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections.Generic;
|
|
3
|
-
using System.Reflection;
|
|
4
3
|
using Delta.ECS;
|
|
5
4
|
using Delta.ECS.Integration;
|
|
6
5
|
using UnityEngine;
|
|
@@ -47,19 +46,16 @@ namespace Delta.ECS.Unity
|
|
|
47
46
|
value = Activator.CreateInstance(componentType);
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
FieldInfo[] fields = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public);
|
|
51
49
|
List<EntityReference> references = EntityReferenceList;
|
|
52
50
|
for (int i = 0; i < references.Count; i++)
|
|
53
51
|
{
|
|
54
52
|
EntityReference reference = references[i];
|
|
55
|
-
|
|
53
|
+
object resolvedValue = resolveEntity(reference.TargetEntityId);
|
|
54
|
+
object current = value;
|
|
55
|
+
if (PropertyBagValueAccess.TrySetValue(ref current, componentType,
|
|
56
|
+
PropertyBagValueAccess.ParsePath(reference.FieldName), resolvedValue))
|
|
56
57
|
{
|
|
57
|
-
|
|
58
|
-
if (field.Name == reference.FieldName && field.FieldType == typeof(Entity))
|
|
59
|
-
{
|
|
60
|
-
field.SetValue(value, resolveEntity(reference.TargetEntityId));
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
58
|
+
value = current;
|
|
63
59
|
}
|
|
64
60
|
}
|
|
65
61
|
|
|
@@ -75,23 +71,13 @@ namespace Delta.ECS.Unity
|
|
|
75
71
|
|
|
76
72
|
_json = JsonUtility.ToJson(value);
|
|
77
73
|
EntityReferenceList.Clear();
|
|
74
|
+
PropertyBagValueAccess.CollectEntityReferences(value, value.GetType(), stableIdResolver, EntityReferenceList);
|
|
75
|
+
}
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
{
|
|
82
|
-
|
|
83
|
-
if (field.FieldType != typeof(Entity))
|
|
84
|
-
{
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
Entity target = (Entity)field.GetValue(value);
|
|
89
|
-
string targetId = stableIdResolver(target) ?? string.Empty;
|
|
90
|
-
if (!string.IsNullOrEmpty(targetId))
|
|
91
|
-
{
|
|
92
|
-
EntityReferenceList.Add(new EntityReference(field.Name, targetId));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
77
|
+
public void StoreDefaultTag()
|
|
78
|
+
{
|
|
79
|
+
_json = "{}";
|
|
80
|
+
EntityReferenceList.Clear();
|
|
95
81
|
}
|
|
96
82
|
|
|
97
83
|
public string GetEntityReference(string fieldName)
|
|
@@ -113,6 +99,11 @@ namespace Delta.ECS.Unity
|
|
|
113
99
|
|
|
114
100
|
public static ComponentData CreateDefault(ComponentDescriptor descriptor)
|
|
115
101
|
{
|
|
102
|
+
if (descriptor.IsTag)
|
|
103
|
+
{
|
|
104
|
+
return new ComponentData(descriptor.Schema.Value, "{}");
|
|
105
|
+
}
|
|
106
|
+
|
|
116
107
|
object value = Activator.CreateInstance(descriptor.ValueType);
|
|
117
108
|
return new ComponentData(descriptor.Schema.Value, JsonUtility.ToJson(value));
|
|
118
109
|
}
|