com.artromskiy.deltaecs.unity 0.0.37

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/Editor/BoundEntityRootEditor.cs +288 -0
  3. package/Editor/BoundEntityRootEditor.cs.meta +2 -0
  4. package/Editor/ComponentDropdown.cs +73 -0
  5. package/Editor/ComponentDropdown.cs.meta +2 -0
  6. package/Editor/ComponentListController.cs +26 -0
  7. package/Editor/ComponentListController.cs.meta +2 -0
  8. package/Editor/DeltaECS.Unity.Editor.asmdef +18 -0
  9. package/Editor/DeltaECS.Unity.Editor.asmdef.meta +7 -0
  10. package/Editor/EditorLifecycle.cs +143 -0
  11. package/Editor/EditorLifecycle.cs.meta +2 -0
  12. package/Editor/EntityInspectorTarget.cs +26 -0
  13. package/Editor/EntityInspectorTarget.cs.meta +3 -0
  14. package/Editor/HierarchyMenu.cs +85 -0
  15. package/Editor/HierarchyMenu.cs.meta +2 -0
  16. package/Editor/HierarchyNodeHandler.cs +950 -0
  17. package/Editor/HierarchyNodeHandler.cs.meta +2 -0
  18. package/Editor/HierarchySelection.cs +171 -0
  19. package/Editor/HierarchySelection.cs.meta +3 -0
  20. package/Editor/InspectorState.cs +220 -0
  21. package/Editor/InspectorState.cs.meta +2 -0
  22. package/Editor/Resources/Inspector/BoundEntityRootEditor.uss +28 -0
  23. package/Editor/Resources/Inspector/BoundEntityRootEditor.uss.meta +2 -0
  24. package/Editor/Resources/Inspector/SceneAuthoringEditor.uss +282 -0
  25. package/Editor/Resources/Inspector/SceneAuthoringEditor.uss.meta +12 -0
  26. package/Editor/Resources/Inspector/SceneAuthoringEditor.uxml +8 -0
  27. package/Editor/Resources/Inspector/SceneAuthoringEditor.uxml.meta +10 -0
  28. package/Editor/Resources/Inspector.meta +8 -0
  29. package/Editor/Resources.meta +8 -0
  30. package/Editor/SceneEntityInspectorView.cs +1103 -0
  31. package/Editor/SceneEntityInspectorView.cs.meta +2 -0
  32. package/Editor/SelectionProxy.cs +19 -0
  33. package/Editor/SelectionProxy.cs.meta +2 -0
  34. package/Editor/SelectionProxyBridge.cs +64 -0
  35. package/Editor/SelectionProxyBridge.cs.meta +2 -0
  36. package/Editor/SelectionProxyEditor.cs +33 -0
  37. package/Editor/SelectionProxyEditor.cs.meta +2 -0
  38. package/LICENSE.md +21 -0
  39. package/LICENSE.md.meta +7 -0
  40. package/README.md +66 -0
  41. package/README.md.meta +2 -0
  42. package/Runtime/AssemblyInfo.cs +3 -0
  43. package/Runtime/AssemblyInfo.cs.meta +2 -0
  44. package/Runtime/ComponentData.cs +120 -0
  45. package/Runtime/ComponentData.cs.meta +2 -0
  46. package/Runtime/DeltaECS.Unity.asmdef +14 -0
  47. package/Runtime/DeltaECS.Unity.asmdef.meta +7 -0
  48. package/Runtime/Editor.meta +8 -0
  49. package/Runtime/EntityAuthoring.cs +47 -0
  50. package/Runtime/EntityAuthoring.cs.meta +2 -0
  51. package/Runtime/EntityReference.cs +21 -0
  52. package/Runtime/EntityReference.cs.meta +2 -0
  53. package/Runtime/SceneAuthoring.cs +202 -0
  54. package/Runtime/SceneAuthoring.cs.meta +2 -0
  55. package/Runtime/SceneData.cs +120 -0
  56. package/Runtime/SceneData.cs.meta +2 -0
  57. package/Runtime/SceneWorld.cs +618 -0
  58. package/Runtime/SceneWorld.cs.meta +2 -0
  59. package/Runtime/ThrowHelpers.cs +44 -0
  60. package/Runtime/ThrowHelpers.cs.meta +2 -0
  61. package/package.json +31 -0
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: d497cf58cf2e4748ac6c05e02facf99b
@@ -0,0 +1,19 @@
1
+ using UnityEngine;
2
+
3
+ namespace Delta.ECS.Unity.Editor
4
+ {
5
+ internal sealed class SelectionProxy : ScriptableObject
6
+ {
7
+ internal EntityInspectorTarget Target { get; private set; }
8
+
9
+ internal void SetTarget(EntityInspectorTarget target)
10
+ {
11
+ Target = target;
12
+ name = target.Authoring != null
13
+ ? target.Authoring.SceneData.TryGetEntity(target.StableId, out EntityAuthoring authoring)
14
+ ? authoring.Name
15
+ : "ECS Entity"
16
+ : $"Entity {target.RuntimeEntity.Index}";
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: c9f52ae22886432791d2a3289ea6a4ea
@@ -0,0 +1,64 @@
1
+ using System.Collections.Generic;
2
+ using Unity.Hierarchy;
3
+ using UnityEditor;
4
+ using UnityEngine;
5
+
6
+ namespace Delta.ECS.Unity.Editor
7
+ {
8
+ [InitializeOnLoad]
9
+ internal static class SelectionProxyBridge
10
+ {
11
+ private static readonly Dictionary<(HierarchyNodeHandler Handler, HierarchyNode Node), SelectionProxy> Proxies = new();
12
+
13
+ static SelectionProxyBridge()
14
+ {
15
+ AssemblyReloadEvents.beforeAssemblyReload += DisposeAll;
16
+ }
17
+
18
+ internal static EntityId GetEntityId(HierarchyNodeHandler handler, HierarchyNode node, EntityInspectorTarget target)
19
+ {
20
+ var key = (handler, node);
21
+ if (!Proxies.TryGetValue(key, out var proxy))
22
+ {
23
+ proxy = ScriptableObject.CreateInstance<SelectionProxy>();
24
+ proxy.hideFlags = HideFlags.DontSaveInEditor | HideFlags.DontSaveInBuild;
25
+ Proxies.Add(key, proxy);
26
+ }
27
+ proxy.SetTarget(target);
28
+ return proxy.GetEntityId();
29
+ }
30
+
31
+ internal static HierarchyNode GetNode(HierarchyNodeHandler handler, EntityId entityId)
32
+ {
33
+ foreach (var pair in Proxies)
34
+ if (pair.Key.Handler == handler && pair.Value.GetEntityId() == entityId)
35
+ return pair.Key.Node;
36
+ return HierarchyNode.Null;
37
+ }
38
+
39
+ internal static void UpdateTarget(HierarchyNodeHandler handler, HierarchyNode node, EntityInspectorTarget target)
40
+ {
41
+ if (Proxies.TryGetValue((handler, node), out var proxy))
42
+ proxy.SetTarget(target);
43
+ }
44
+
45
+ internal static void Select(HierarchyNodeHandler handler, HierarchyNode node, EntityInspectorTarget target)
46
+ {
47
+ GetEntityId(handler, node, target);
48
+ var proxy = Proxies[(handler, node)];
49
+ if (Selection.activeObject != proxy) Selection.activeObject = proxy;
50
+ }
51
+
52
+ internal static void Remove(HierarchyNodeHandler handler, HierarchyNode node)
53
+ {
54
+ if (Proxies.Remove((handler, node), out var proxy))
55
+ Object.DestroyImmediate(proxy);
56
+ }
57
+
58
+ private static void DisposeAll()
59
+ {
60
+ foreach (var proxy in Proxies.Values) Object.DestroyImmediate(proxy);
61
+ Proxies.Clear();
62
+ }
63
+ }
64
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 6c424da3b18e43de919acdd9c3a8cfe1
@@ -0,0 +1,33 @@
1
+ using UnityEditor;
2
+ using UnityEngine.UIElements;
3
+
4
+ namespace Delta.ECS.Unity.Editor
5
+ {
6
+ [CustomEditor(typeof(SelectionProxy))]
7
+ internal sealed class SelectionProxyEditor : UnityEditor.Editor
8
+ {
9
+ private SceneEntityInspectorView _view;
10
+
11
+ public override bool UseDefaultMargins() => false;
12
+
13
+ public override bool RequiresConstantRepaint() => EditorApplication.isPlaying;
14
+
15
+ private void OnEnable()
16
+ {
17
+ _view?.Dispose();
18
+ _view = new SceneEntityInspectorView(ResolveTarget);
19
+ }
20
+
21
+ private EntityInspectorTarget ResolveTarget() => target is SelectionProxy proxy && proxy != null
22
+ ? proxy.Target
23
+ : default;
24
+
25
+ private void OnDisable()
26
+ {
27
+ _view?.Dispose();
28
+ _view = null;
29
+ }
30
+
31
+ public override VisualElement CreateInspectorGUI() => _view.CreateGUI();
32
+ }
33
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 00aa700f5c4e4b4aa1e9482b37f4a0bc
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Artromskiy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 3e6daaa2fa564365859d2fa9bcb117c4
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # DeltaECS Unity
2
+
3
+ Unity scene authoring and editor integration for DeltaECS. This package
4
+ requires Unity 6.7 (`6000.7`) or newer.
5
+
6
+ ## Install
7
+
8
+ Add the npm-compatible registry and package to the Unity project's
9
+ `Packages/manifest.json`:
10
+
11
+ ```json
12
+ {
13
+ "scopedRegistries": [
14
+ {
15
+ "name": "Artromskiy",
16
+ "url": "https://registry.npmjs.org",
17
+ "scopes": ["com.artromskiy"]
18
+ }
19
+ ],
20
+ "dependencies": {
21
+ "com.artromskiy.deltaecs.unity": "0.0.37"
22
+ }
23
+ }
24
+ ```
25
+
26
+ Keep the project's existing `dependencies` and `scopedRegistries` entries when
27
+ adding these values. The core `DeltaECS` runtime and `DeltaECS.Generators` are
28
+ separate NuGet packages and are not included in this UPM package.
29
+
30
+ ## Register components
31
+
32
+ Install `DeltaECS.Generators` in the assembly that declares components, then
33
+ mark component structs with `DeltaEcsComponentAttribute`:
34
+
35
+ ```csharp
36
+ using Delta.ECS;
37
+
38
+ [DeltaEcsComponent]
39
+ public struct Health
40
+ {
41
+ public float Value;
42
+ }
43
+ ```
44
+
45
+ Generated module initializers register typed component factories. Create a
46
+ world with the generated layout catalog:
47
+
48
+ ```csharp
49
+ using var world = new World(GeneratedComponentCatalog.CreateLayoutRegistry());
50
+ ```
51
+
52
+ The generator reports the stable schema ID for each component. Set
53
+ `SchemaId` explicitly when a component's serialized identity must remain
54
+ unchanged after a type rename:
55
+
56
+ ```csharp
57
+ [DeltaEcsComponent(SchemaId = 0x1234UL)]
58
+ public struct Position
59
+ {
60
+ public float X;
61
+ public float Y;
62
+ }
63
+ ```
64
+
65
+ See the [DeltaECS documentation](https://github.com/Artromskiy/DeltaECS/wiki)
66
+ for the runtime and generator APIs.
package/README.md.meta ADDED
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 664213c7fff44a7b8136ecf8a78f0f7a
@@ -0,0 +1,3 @@
1
+ using System.Runtime.CompilerServices;
2
+
3
+ [assembly: InternalsVisibleTo("DeltaECS.Unity.Editor")]
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: bba909334e21b26fe9387f80cb9de995
@@ -0,0 +1,120 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.Reflection;
4
+ using Delta.ECS;
5
+ using Delta.ECS.Integration;
6
+ using UnityEngine;
7
+
8
+ namespace Delta.ECS.Unity
9
+ {
10
+ [Serializable]
11
+ internal sealed class ComponentData
12
+ {
13
+ [SerializeField] private string _schemaId;
14
+ [SerializeField, TextArea(2, 8)] private string _json;
15
+ [SerializeField] private List<EntityReference> _entityReferences = new();
16
+
17
+ public string SchemaIdText => _schemaId;
18
+ public string Json => _json;
19
+ public IReadOnlyList<EntityReference> EntityReferences => _entityReferences ??= new List<EntityReference>();
20
+
21
+ public ComponentData(ulong schemaId, string json)
22
+ {
23
+ _schemaId = schemaId.ToString("X16");
24
+ _json = json;
25
+ }
26
+
27
+ public bool TryGetSchemaId(out SchemaId schemaId)
28
+ {
29
+ if (ulong.TryParse(_schemaId, System.Globalization.NumberStyles.HexNumber, null, out ulong value))
30
+ {
31
+ schemaId = new SchemaId(value);
32
+ return true;
33
+ }
34
+
35
+ schemaId = default;
36
+ return false;
37
+ }
38
+
39
+ public object CreateValue(Type componentType, Func<string, Entity> resolveEntity)
40
+ {
41
+ object value = string.IsNullOrEmpty(_json)
42
+ ? Activator.CreateInstance(componentType)
43
+ : JsonUtility.FromJson(_json, componentType);
44
+
45
+ if (value == null)
46
+ {
47
+ value = Activator.CreateInstance(componentType);
48
+ }
49
+
50
+ FieldInfo[] fields = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public);
51
+ List<EntityReference> references = EntityReferenceList;
52
+ for (int i = 0; i < references.Count; i++)
53
+ {
54
+ EntityReference reference = references[i];
55
+ for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
56
+ {
57
+ FieldInfo field = fields[fieldIndex];
58
+ if (field.Name == reference.FieldName && field.FieldType == typeof(Entity))
59
+ {
60
+ field.SetValue(value, resolveEntity(reference.TargetEntityId));
61
+ break;
62
+ }
63
+ }
64
+ }
65
+
66
+ return value;
67
+ }
68
+
69
+ public void StoreValue(object value, Func<Entity, string> stableIdResolver)
70
+ {
71
+ if (value == null)
72
+ {
73
+ UnityThrowHelpers.ThrowArgumentNull(nameof(value));
74
+ }
75
+
76
+ _json = JsonUtility.ToJson(value);
77
+ EntityReferenceList.Clear();
78
+
79
+ FieldInfo[] fields = value.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
80
+ for (int i = 0; i < fields.Length; i++)
81
+ {
82
+ FieldInfo field = fields[i];
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
+ }
95
+ }
96
+
97
+ public string GetEntityReference(string fieldName)
98
+ {
99
+ List<EntityReference> references = EntityReferenceList;
100
+ for (int i = 0; i < references.Count; i++)
101
+ {
102
+ if (string.Equals(references[i].FieldName, fieldName, StringComparison.Ordinal))
103
+ {
104
+ return references[i].TargetEntityId;
105
+ }
106
+ }
107
+
108
+ return string.Empty;
109
+ }
110
+
111
+ private List<EntityReference> EntityReferenceList =>
112
+ _entityReferences ??= new List<EntityReference>();
113
+
114
+ public static ComponentData CreateDefault(ComponentDescriptor descriptor)
115
+ {
116
+ object value = Activator.CreateInstance(descriptor.ValueType);
117
+ return new ComponentData(descriptor.Schema.Value, JsonUtility.ToJson(value));
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 87f1a4659d8d42d286312f0d0c72248e
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "DeltaECS.Unity",
3
+ "rootNamespace": "Delta.ECS.Unity",
4
+ "references": [],
5
+ "includePlatforms": [],
6
+ "excludePlatforms": [],
7
+ "allowUnsafeCode": false,
8
+ "overrideReferences": false,
9
+ "precompiledReferences": [],
10
+ "autoReferenced": true,
11
+ "defineConstraints": [],
12
+ "versionDefines": [],
13
+ "noEngineReferences": false
14
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: a8f27bf435dbf7a9cca6b632d9a7ed34
3
+ AssemblyDefinitionImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: e46a551e30de4d1383d31cd87e391b28
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,47 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using UnityEngine;
4
+
5
+ namespace Delta.ECS.Unity
6
+ {
7
+ [Serializable]
8
+ internal sealed class EntityAuthoring
9
+ {
10
+ [SerializeField] private string _stableId;
11
+ [SerializeField] private string _name = "Entity";
12
+ [SerializeField] private List<ComponentData> _components = new();
13
+
14
+ public string StableId
15
+ {
16
+ get
17
+ {
18
+ EnsureStableId();
19
+ return _stableId;
20
+ }
21
+ }
22
+
23
+ public string Name
24
+ {
25
+ get => string.IsNullOrEmpty(_name) ? "Entity" : _name;
26
+ set => _name = string.IsNullOrWhiteSpace(value) ? "Entity" : value;
27
+ }
28
+
29
+ public IList<ComponentData> Components => _components ??= new List<ComponentData>();
30
+
31
+ internal bool EnsureStableId()
32
+ {
33
+ if (!string.IsNullOrEmpty(_stableId))
34
+ {
35
+ return false;
36
+ }
37
+
38
+ _stableId = Guid.NewGuid().ToString("N");
39
+ return true;
40
+ }
41
+
42
+ internal void ReplaceStableId()
43
+ {
44
+ _stableId = Guid.NewGuid().ToString("N");
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 862a594bb6d04e46901300e28f45e4f8
@@ -0,0 +1,21 @@
1
+ using System;
2
+ using UnityEngine;
3
+
4
+ namespace Delta.ECS.Unity
5
+ {
6
+ [Serializable]
7
+ internal sealed class EntityReference
8
+ {
9
+ [SerializeField] private string _fieldName;
10
+ [SerializeField] private string _targetEntityId;
11
+
12
+ public string FieldName => _fieldName;
13
+ public string TargetEntityId => _targetEntityId;
14
+
15
+ public EntityReference(string fieldName, string targetEntityId)
16
+ {
17
+ _fieldName = fieldName;
18
+ _targetEntityId = targetEntityId;
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 671e0ab0af8a4eb0a9e62dcb7b3048aa
@@ -0,0 +1,202 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using UnityEngine;
4
+ using UnityEngine.SceneManagement;
5
+
6
+ namespace Delta.ECS.Unity
7
+ {
8
+ /// <summary>
9
+ /// Stores entities authored for a Delta ECS scene. The Unity editor integration
10
+ /// creates a hidden scene object for it automatically; it does not own a Delta ECS World.
11
+ /// </summary>
12
+ [DisallowMultipleComponent]
13
+ [AddComponentMenu("Delta ECS/Scene Authoring")]
14
+ public sealed class SceneAuthoring : MonoBehaviour
15
+ {
16
+ internal const string AuthoringObjectName = "Delta ECS Scene Authoring";
17
+
18
+ [SerializeField, HideInInspector]
19
+ private SceneData _sceneData = new();
20
+ [SerializeField, HideInInspector]
21
+ private List<SceneViewBinding> _viewBindings = new();
22
+
23
+ [NonSerialized] private Dictionary<string, GameObject> _viewsByStableId;
24
+ [NonSerialized] private Dictionary<UnityEngine.EntityId, string> _stableIdsByView;
25
+
26
+ internal SceneData SceneData => _sceneData ??= new SceneData();
27
+
28
+ internal bool TryGetView(string stableId, out GameObject view)
29
+ {
30
+ EnsureBindingIndex();
31
+ if (!string.IsNullOrEmpty(stableId) && _viewsByStableId.TryGetValue(stableId, out view) && view != null)
32
+ {
33
+ return true;
34
+ }
35
+
36
+ view = null;
37
+ return false;
38
+ }
39
+
40
+ internal bool TryGetStableId(GameObject view, out string stableId)
41
+ {
42
+ EnsureBindingIndex();
43
+ if (view != null && _stableIdsByView.TryGetValue(view.GetEntityId(), out stableId))
44
+ {
45
+ return true;
46
+ }
47
+
48
+ stableId = null;
49
+ return false;
50
+ }
51
+
52
+ /// <summary>Persists a same-scene Unity view binding for an authored ECS entity.</summary>
53
+ internal bool SetView(string stableId, GameObject view)
54
+ {
55
+ if (string.IsNullOrEmpty(stableId)
56
+ || (view != null && !SceneData.TryGetEntity(stableId, out _))
57
+ || (view != null && view.scene != gameObject.scene))
58
+ {
59
+ return false;
60
+ }
61
+
62
+ EnsureBindingIndex();
63
+ UnityEngine.EntityId viewId = view != null ? view.GetEntityId() : UnityEngine.EntityId.None;
64
+ for (int i = _viewBindings.Count - 1; i >= 0; i--)
65
+ {
66
+ SceneViewBinding binding = _viewBindings[i];
67
+ bool sameEntity = string.Equals(binding.StableId, stableId, StringComparison.Ordinal);
68
+ bool sameView = view != null && binding.View != null && binding.View.GetEntityId() == viewId;
69
+ if (sameEntity || sameView)
70
+ {
71
+ _viewBindings.RemoveAt(i);
72
+ }
73
+ }
74
+
75
+ if (view != null)
76
+ {
77
+ _viewBindings.Add(new SceneViewBinding(stableId, view));
78
+ }
79
+
80
+ InvalidateBindingIndex();
81
+ EnsureBindingIndex();
82
+ return true;
83
+ }
84
+
85
+ internal bool RemoveView(string stableId) => SetView(stableId, null);
86
+
87
+ internal static SceneAuthoring FindForScene(Scene scene)
88
+ {
89
+ if (!scene.IsValid())
90
+ {
91
+ return null;
92
+ }
93
+
94
+ SceneAuthoring[] authorings = Resources.FindObjectsOfTypeAll<SceneAuthoring>();
95
+ for (int i = 0; i < authorings.Length; i++)
96
+ {
97
+ SceneAuthoring authoring = authorings[i];
98
+ if (authoring != null && authoring.gameObject.scene == scene)
99
+ {
100
+ return authoring;
101
+ }
102
+ }
103
+
104
+ return null;
105
+ }
106
+
107
+ internal static SceneAuthoring GetOrCreateForScene(Scene scene)
108
+ {
109
+ if (!scene.IsValid() || !scene.isLoaded)
110
+ {
111
+ UnityThrowHelpers.ThrowArgument("Scene authoring requires a valid, loaded scene.", nameof(scene));
112
+ }
113
+
114
+ SceneAuthoring existing = FindForScene(scene);
115
+ if (existing != null)
116
+ {
117
+ return existing;
118
+ }
119
+
120
+ var authoringObject = new GameObject(AuthoringObjectName);
121
+ SceneManager.MoveGameObjectToScene(authoringObject, scene);
122
+ SceneAuthoring authoring = authoringObject.AddComponent<SceneAuthoring>();
123
+ authoringObject.hideFlags |= HideFlags.HideInHierarchy;
124
+ return authoring;
125
+ }
126
+
127
+ private void OnValidate()
128
+ {
129
+ SceneData.EnsureStableIds();
130
+ InvalidateBindingIndex();
131
+ }
132
+
133
+ private void OnEnable()
134
+ {
135
+ SceneData.Changed -= OnSceneDataChanged;
136
+ SceneData.Changed += OnSceneDataChanged;
137
+ InvalidateBindingIndex();
138
+ }
139
+
140
+ private void OnDisable()
141
+ {
142
+ if (_sceneData != null)
143
+ {
144
+ _sceneData.Changed -= OnSceneDataChanged;
145
+ }
146
+ }
147
+
148
+ private void OnSceneDataChanged(SceneDataChange change)
149
+ {
150
+ if (change.Kind == SceneDataChangeKind.EntityDestroyed)
151
+ {
152
+ RemoveView(change.StableId);
153
+ }
154
+ }
155
+
156
+ private void EnsureBindingIndex()
157
+ {
158
+ if (_viewsByStableId != null && _stableIdsByView != null)
159
+ {
160
+ return;
161
+ }
162
+
163
+ _viewsByStableId = new Dictionary<string, GameObject>(StringComparer.Ordinal);
164
+ _stableIdsByView = new Dictionary<UnityEngine.EntityId, string>();
165
+ _viewBindings ??= new List<SceneViewBinding>();
166
+ for (int i = 0; i < _viewBindings.Count; i++)
167
+ {
168
+ SceneViewBinding binding = _viewBindings[i];
169
+ if (string.IsNullOrEmpty(binding.StableId) || binding.View == null)
170
+ {
171
+ continue;
172
+ }
173
+
174
+ UnityEngine.EntityId viewId = binding.View.GetEntityId();
175
+ _viewsByStableId[binding.StableId] = binding.View;
176
+ _stableIdsByView[viewId] = binding.StableId;
177
+ }
178
+ }
179
+
180
+ private void InvalidateBindingIndex()
181
+ {
182
+ _viewsByStableId = null;
183
+ _stableIdsByView = null;
184
+ }
185
+ }
186
+
187
+ [Serializable]
188
+ internal struct SceneViewBinding
189
+ {
190
+ [SerializeField] private string _stableId;
191
+ [SerializeField] private GameObject _view;
192
+
193
+ public string StableId => _stableId;
194
+ public GameObject View => _view;
195
+
196
+ public SceneViewBinding(string stableId, GameObject view)
197
+ {
198
+ _stableId = stableId;
199
+ _view = view;
200
+ }
201
+ }
202
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: d8543b39d9164a58b86c14879b341f5b