Keep Entities selected when switching between Play- and Edit-Mode

- Fixed the check whether all selected entities have the same parent
This commit is contained in:
Simon Lübeß
2023-11-29 14:16:36 +01:00
parent 0257b93c7b
commit b68bad5bda
4 changed files with 71 additions and 40 deletions
@@ -46,10 +46,9 @@ namespace GlitchyEditor.EditWindows
return; return;
} }
if(_entityHierarchyWindow.SelectedEntities.Count == 1) if (_entityHierarchyWindow.SelectionSize == 1)
{ {
Entity entity = _entityHierarchyWindow.SelectedEntities.Front; Entity entity = _entityHierarchyWindow.GetSelectedEntity(0);
ShowComponents(entity); ShowComponents(entity);
} }
@@ -323,10 +323,10 @@ namespace GlitchyEditor.EditWindows
Handles.SetViewProjection(view, projection); Handles.SetViewProjection(view, projection);
if(_editor.EntityHierarchyWindow.SelectedEntities.Count == 0) if(_editor.EntityHierarchyWindow.SelectionSize == 0)
return false; return false;
var entity = _editor.EntityHierarchyWindow.SelectedEntities.Back; Entity entity = _editor.EntityHierarchyWindow.GetSelectedEntity(-1);
var transformCmp = entity.GetComponent<TransformComponent>(); var transformCmp = entity.GetComponent<TransformComponent>();
@@ -4,6 +4,8 @@ using ImGui;
using System; using System;
using System.Collections; using System.Collections;
using GlitchyEngine; using GlitchyEngine;
using GlitchyEngine.Core;
using System.Diagnostics;
namespace GlitchyEditor.EditWindows namespace GlitchyEditor.EditWindows
{ {
@@ -19,14 +21,38 @@ namespace GlitchyEditor.EditWindows
private Scene _scene; private Scene _scene;
private List<Entity> _selectedEntities = new .() ~ delete _; private List<UUID> _selectedEntityIds = new .() ~ delete _;
private Entity _entityToHighlight; private Entity _entityToHighlight;
public List<Entity> SelectedEntities => _selectedEntities; /// Gets a list of selected entity IDs.
public List<UUID> SelectedEntityIds => _selectedEntityIds;
private List<Entity> _entitiesToUnfold = new .() ~ delete _; private List<Entity> _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<Entity> 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) public void HighlightEntity(Entity e)
{ {
_entityToHighlight = e; _entityToHighlight = e;
@@ -49,7 +75,9 @@ namespace GlitchyEditor.EditWindows
public void SetContext(Scene scene) 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; _scene = scene;
} }
@@ -66,7 +94,7 @@ namespace GlitchyEditor.EditWindows
/// Deselects all entities. /// Deselects all entities.
public void ClearEntitySelection() public void ClearEntitySelection()
{ {
_selectedEntities.Clear(); _selectedEntityIds.Clear();
} }
/// Selects the given entity. /// Selects the given entity.
@@ -77,20 +105,20 @@ namespace GlitchyEditor.EditWindows
if (clearOldSelection) if (clearOldSelection)
ClearEntitySelection(); ClearEntitySelection();
_selectedEntities.Add(entity); _selectedEntityIds.Add(entity.UUID);
} }
/// Deselects the given entity. /// Deselects the given entity.
/// @param entity The entity to deselect. /// @param entity The entity to deselect.
public bool DeselectEntity(Entity entity) public bool DeselectEntity(Entity entity)
{ {
return _selectedEntities.Remove(entity); return _selectedEntityIds.Remove(entity.UUID);
} }
/// Returns whether or not the given entity is currently selected. /// Returns whether or not the given entity is currently selected.
public bool IsEntitySelected(Entity entity) public bool IsEntitySelected(Entity entity)
{ {
return _selectedEntities.Contains(entity); return _selectedEntityIds.Contains(entity.UUID);
} }
protected override void InternalShow() protected override void InternalShow()
@@ -137,13 +165,15 @@ namespace GlitchyEditor.EditWindows
/// Returns whether or not all selected entities have the same parent. /// Returns whether or not all selected entities have the same parent.
internal bool AllSelectionsOnSameLevel() internal bool AllSelectionsOnSameLevel()
{ {
EcsEntity? parent = .InvalidEntity; EcsEntity? parent = null;
for(var selectedEntity in _selectedEntities) for (int i < SelectionSize)
{ {
var transformComponent = selectedEntity.GetComponent<TransformComponent>(); Entity entity = GetSelectedEntity(i);
if(parent == .InvalidEntity) var transformComponent = entity.GetComponent<TransformComponent>();
if(parent == null)
{ {
parent = transformComponent.Parent; parent = transformComponent.Parent;
} }
@@ -174,12 +204,13 @@ namespace GlitchyEditor.EditWindows
/// Deletes all selected entities and their children. /// Deletes all selected entities and their children.
internal void DeleteSelectedEntities() 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() private void ShowEntityHierarchyMenuBar()
@@ -190,7 +221,7 @@ namespace GlitchyEditor.EditWindows
Show_ContextMenu_Delete(); Show_ContextMenu_Delete();
if(ImGui.MenuItem("Delete", null, false, !_selectedEntities.IsEmpty) || if(ImGui.MenuItem("Delete", null, false, SelectionSize != 0) ||
(Input.IsKeyPressed(.Delete) && ImGui.IsWindowHovered())) (Input.IsKeyPressed(.Delete) && ImGui.IsWindowHovered()))
{ {
DeleteSelectedEntities(); DeleteSelectedEntities();
@@ -210,9 +241,9 @@ namespace GlitchyEditor.EditWindows
/// Creates a new entity that is a child of the given entity. /// Creates a new entity that is a child of the given entity.
private void CreateChild(Entity? entity) private void CreateChild(Entity? entity)
{ {
var newEntity = _scene.CreateEntity(); let newEntity = _scene.CreateEntity();
var transformCmp = newEntity.GetComponent<TransformComponent>(); let transformCmp = newEntity.GetComponent<TransformComponent>();
// Last entity in list is the entity that has been selected last. // Last entity in list is the entity that has been selected last.
transformCmp.Parent = entity?.Handle ?? .InvalidEntity; transformCmp.Parent = entity?.Handle ?? .InvalidEntity;
} }
@@ -220,29 +251,29 @@ namespace GlitchyEditor.EditWindows
/// Creates a new entity that is a parent of the selected entities. /// Creates a new entity that is a parent of the selected entities.
private void CreateParent() private void CreateParent()
{ {
if (_selectedEntities.IsEmpty || !AllSelectionsOnSameLevel()) if (SelectionSize == 0 || !AllSelectionsOnSameLevel())
{ {
Log.EngineLogger.Error("Cannot create parent entity."); Log.EngineLogger.Error("Cannot create parent entity.");
return; return;
} }
var commonParent = _selectedEntities.Front.GetComponent<TransformComponent>(); let commonParent = GetSelectedEntity(0).GetComponent<TransformComponent>();
var newEntity = _scene.CreateEntity(); let newEntity = _scene.CreateEntity();
if(commonParent != null) if(commonParent != null)
{ {
// parent of selected entities is parent of the new entity. // 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) // (which is why this doesn't work if the entities don't have the same parent)
var newEntityTransform = newEntity.GetComponent<TransformComponent>(); let newEntityTransform = newEntity.GetComponent<TransformComponent>();
newEntityTransform.Parent = commonParent.Parent; newEntityTransform.Parent = commonParent.Parent;
} }
// new entity is parent of all selected entities. // new entity is parent of all selected entities.
for(var selectedEntity in _selectedEntities) for (int i < SelectionSize)
{ {
var selectedTransform = selectedEntity.GetComponent<TransformComponent>(); let selectedTransform = GetSelectedEntity(i).GetComponent<TransformComponent>();
selectedTransform.Parent = newEntity.Handle; selectedTransform?.Parent = newEntity.Handle;
} }
} }
@@ -254,11 +285,11 @@ namespace GlitchyEditor.EditWindows
{ {
if(ImGui.MenuItem("Empty Entity")) if(ImGui.MenuItem("Empty Entity"))
{ {
if (_selectedEntities.IsEmpty) if (SelectionSize == 0)
_scene.CreateEntity(); _scene.CreateEntity();
else else
{ {
Entity? parent = _selectedEntities.Back.Parent; Entity? parent = GetSelectedEntity(-1).Parent;
CreateChild(parent); CreateChild(parent);
} }
} }
@@ -271,9 +302,10 @@ namespace GlitchyEditor.EditWindows
if (allowChild) 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()) if(ImGui.IsItemHovered())
@@ -282,7 +314,7 @@ namespace GlitchyEditor.EditWindows
if (allowParent) if (allowParent)
{ {
if(ImGui.MenuItem("Parent", null, false, !_selectedEntities.IsEmpty && AllSelectionsOnSameLevel())) if(ImGui.MenuItem("Parent", null, false, SelectionSize != 0 && AllSelectionsOnSameLevel()))
{ {
CreateParent(); CreateParent();
} }
@@ -302,7 +334,7 @@ namespace GlitchyEditor.EditWindows
{ {
bool deleted = false; bool deleted = false;
if(ImGui.MenuItem("Delete", null, false, !_selectedEntities.IsEmpty)) if(ImGui.MenuItem("Delete", null, false, SelectionSize != 0))
{ {
DeleteSelectedEntities(); DeleteSelectedEntities();
+2 -2
View File
@@ -492,7 +492,7 @@ namespace GlitchyEditor
for (var (entity, transform, camera) in _activeScene.GetEntities<TransformComponent, CameraComponent>()) for (var (entity, transform, camera) in _activeScene.GetEntities<TransformComponent, CameraComponent>())
{ {
if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _activeScene))) if (_editor.EntityHierarchyWindow.IsEntitySelected(.(entity, _activeScene)))
{ {
DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, .White); DebugRenderer.DrawViewFrustum(transform.WorldTransform, camera.Camera.Projection, .White);
} }
@@ -506,7 +506,7 @@ namespace GlitchyEditor
for (var (entity, transform, light) in _activeScene.GetEntities<TransformComponent, LightComponent>()) for (var (entity, transform, light) in _activeScene.GetEntities<TransformComponent, LightComponent>())
{ {
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); Renderer.DrawRay(.Zero, .(0, 0, 20), ColorRGBA(light.SceneLight.Color, 1.0f), transform.WorldTransform);