diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index 9d13288..3bbc3d0 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -45,14 +45,13 @@ namespace GlitchyEditor.EditWindows ImGui.End(); return; } - - if(_entityHierarchyWindow.SelectedEntities.Count == 1) - { - Entity entity = _entityHierarchyWindow.SelectedEntities.Front; + if (_entityHierarchyWindow.SelectionSize == 1) + { + Entity entity = _entityHierarchyWindow.GetSelectedEntity(0); ShowComponents(entity); } - + ImGui.PopStyleVar(); ImGui.End(); } diff --git a/GlitchyEditor/src/EditWindows/EditorViewportWindow.bf b/GlitchyEditor/src/EditWindows/EditorViewportWindow.bf index ee7e1bf..d316a34 100644 --- a/GlitchyEditor/src/EditWindows/EditorViewportWindow.bf +++ b/GlitchyEditor/src/EditWindows/EditorViewportWindow.bf @@ -323,10 +323,10 @@ namespace GlitchyEditor.EditWindows Handles.SetViewProjection(view, projection); - if(_editor.EntityHierarchyWindow.SelectedEntities.Count == 0) + if(_editor.EntityHierarchyWindow.SelectionSize == 0) return false; - var entity = _editor.EntityHierarchyWindow.SelectedEntities.Back; + Entity entity = _editor.EntityHierarchyWindow.GetSelectedEntity(-1); var transformCmp = entity.GetComponent(); diff --git a/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf b/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf index d64a160..5f09bdb 100644 --- a/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf +++ b/GlitchyEditor/src/EditWindows/EntityHierarchyWindow.bf @@ -4,6 +4,8 @@ using ImGui; using System; using System.Collections; using GlitchyEngine; +using GlitchyEngine.Core; +using System.Diagnostics; namespace GlitchyEditor.EditWindows { @@ -19,14 +21,38 @@ namespace GlitchyEditor.EditWindows private Scene _scene; - private List _selectedEntities = new .() ~ delete _; + private List _selectedEntityIds = new .() ~ delete _; private Entity _entityToHighlight; - public List SelectedEntities => _selectedEntities; + /// Gets a list of selected entity IDs. + public List SelectedEntityIds => _selectedEntityIds; private List _entitiesToUnfold = new .() ~ delete _; + /// Gets the number of entities that are currently selected. + public int SelectionSize => _selectedEntityIds.Count; + + /// Returns the Entity at the given index or null if it doesn't exist. + public Entity GetSelectedEntity(int index) + { + var index; + + if (index < 0) + index = _selectedEntityIds.Count + index; + + UUID id = _selectedEntityIds[index]; + + Result selectedEntity = _editor.CurrentScene.GetEntityByID(id); + + if (selectedEntity case .Ok(let entity)) + return entity; + + // TODO: The entity should always exist in the scene, I'm sure! + // If we can assume that, then we can remove the nullable and make everything even easier! + Runtime.FatalError(scope $"No entity exists with selected id \"{id}\"."); + } + public void HighlightEntity(Entity e) { _entityToHighlight = e; @@ -49,7 +75,9 @@ namespace GlitchyEditor.EditWindows public void SetContext(Scene scene) { - ClearEntitySelection(); + // We could have looked here first, then we wouldn't changed the selection system to use UUIDs... + // We could have gotten the IDs here and simply searched for the corresponding entities in the new scene. + //ClearEntitySelection(); _scene = scene; } @@ -66,7 +94,7 @@ namespace GlitchyEditor.EditWindows /// Deselects all entities. public void ClearEntitySelection() { - _selectedEntities.Clear(); + _selectedEntityIds.Clear(); } /// Selects the given entity. @@ -77,20 +105,20 @@ namespace GlitchyEditor.EditWindows if (clearOldSelection) ClearEntitySelection(); - _selectedEntities.Add(entity); + _selectedEntityIds.Add(entity.UUID); } /// Deselects the given entity. /// @param entity The entity to deselect. public bool DeselectEntity(Entity entity) { - return _selectedEntities.Remove(entity); + return _selectedEntityIds.Remove(entity.UUID); } /// Returns whether or not the given entity is currently selected. public bool IsEntitySelected(Entity entity) { - return _selectedEntities.Contains(entity); + return _selectedEntityIds.Contains(entity.UUID); } protected override void InternalShow() @@ -137,13 +165,15 @@ namespace GlitchyEditor.EditWindows /// Returns whether or not all selected entities have the same parent. internal bool AllSelectionsOnSameLevel() { - EcsEntity? parent = .InvalidEntity; + EcsEntity? parent = null; - for(var selectedEntity in _selectedEntities) + for (int i < SelectionSize) { - var transformComponent = selectedEntity.GetComponent(); + Entity entity = GetSelectedEntity(i); - if(parent == .InvalidEntity) + var transformComponent = entity.GetComponent(); + + if(parent == null) { parent = transformComponent.Parent; } @@ -174,12 +204,13 @@ namespace GlitchyEditor.EditWindows /// Deletes all selected entities and their children. internal void DeleteSelectedEntities() { - for (var entity in _selectedEntities) + for (int i < _selectedEntityIds.Count) { - _scene.DestroyEntity(entity, true); + Entity selectedEntity = GetSelectedEntity(i); + _scene.DestroyEntity(selectedEntity, true); } - _selectedEntities.Clear(); + _selectedEntityIds.Clear(); } private void ShowEntityHierarchyMenuBar() @@ -190,7 +221,7 @@ namespace GlitchyEditor.EditWindows Show_ContextMenu_Delete(); - if(ImGui.MenuItem("Delete", null, false, !_selectedEntities.IsEmpty) || + if(ImGui.MenuItem("Delete", null, false, SelectionSize != 0) || (Input.IsKeyPressed(.Delete) && ImGui.IsWindowHovered())) { DeleteSelectedEntities(); @@ -210,9 +241,9 @@ namespace GlitchyEditor.EditWindows /// Creates a new entity that is a child of the given entity. private void CreateChild(Entity? entity) { - var newEntity = _scene.CreateEntity(); + let newEntity = _scene.CreateEntity(); - var transformCmp = newEntity.GetComponent(); + let transformCmp = newEntity.GetComponent(); // Last entity in list is the entity that has been selected last. transformCmp.Parent = entity?.Handle ?? .InvalidEntity; } @@ -220,29 +251,29 @@ namespace GlitchyEditor.EditWindows /// Creates a new entity that is a parent of the selected entities. private void CreateParent() { - if (_selectedEntities.IsEmpty || !AllSelectionsOnSameLevel()) + if (SelectionSize == 0 || !AllSelectionsOnSameLevel()) { Log.EngineLogger.Error("Cannot create parent entity."); return; } - var commonParent = _selectedEntities.Front.GetComponent(); + let commonParent = GetSelectedEntity(0).GetComponent(); - var newEntity = _scene.CreateEntity(); + let newEntity = _scene.CreateEntity(); if(commonParent != null) { // parent of selected entities is parent of the new entity. // (which is why this doesn't work if the entities don't have the same parent) - var newEntityTransform = newEntity.GetComponent(); + let newEntityTransform = newEntity.GetComponent(); newEntityTransform.Parent = commonParent.Parent; } - + // new entity is parent of all selected entities. - for(var selectedEntity in _selectedEntities) + for (int i < SelectionSize) { - var selectedTransform = selectedEntity.GetComponent(); - selectedTransform.Parent = newEntity.Handle; + let selectedTransform = GetSelectedEntity(i).GetComponent(); + selectedTransform?.Parent = newEntity.Handle; } } @@ -254,11 +285,11 @@ namespace GlitchyEditor.EditWindows { if(ImGui.MenuItem("Empty Entity")) { - if (_selectedEntities.IsEmpty) + if (SelectionSize == 0) _scene.CreateEntity(); else { - Entity? parent = _selectedEntities.Back.Parent; + Entity? parent = GetSelectedEntity(-1).Parent; CreateChild(parent); } } @@ -271,9 +302,10 @@ namespace GlitchyEditor.EditWindows if (allowChild) { - if(ImGui.MenuItem("Empty Child", null, false, !_selectedEntities.IsEmpty)) + if(ImGui.MenuItem("Empty Child", null, false, SelectionSize != 0)) { - CreateChild(_selectedEntities.Back); + Entity selectedEntity = GetSelectedEntity(-1); + CreateChild(selectedEntity); } if(ImGui.IsItemHovered()) @@ -282,7 +314,7 @@ namespace GlitchyEditor.EditWindows if (allowParent) { - if(ImGui.MenuItem("Parent", null, false, !_selectedEntities.IsEmpty && AllSelectionsOnSameLevel())) + if(ImGui.MenuItem("Parent", null, false, SelectionSize != 0 && AllSelectionsOnSameLevel())) { CreateParent(); } @@ -302,7 +334,7 @@ namespace GlitchyEditor.EditWindows { bool deleted = false; - if(ImGui.MenuItem("Delete", null, false, !_selectedEntities.IsEmpty)) + if(ImGui.MenuItem("Delete", null, false, SelectionSize != 0)) { DeleteSelectedEntities(); diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index ddcc5fb..a48bf90 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -492,7 +492,7 @@ namespace GlitchyEditor for (var (entity, transform, camera) in _activeScene.GetEntities()) { - if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene))) + if (_editor.EntityHierarchyWindow.IsEntitySelected(.(entity, _activeScene))) { DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, .White); } @@ -506,7 +506,7 @@ namespace GlitchyEditor for (var (entity, transform, light) in _activeScene.GetEntities()) { - if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene))) + if (_editor.EntityHierarchyWindow.IsEntitySelected(.(entity, _activeScene))) { Renderer.DrawRay(.Zero, .(0, 0, 20), ColorRGBA(light.SceneLight.Color, 1.0f), transform.WorldTransform);