From deea3f85443a85b4b18fa6c3408024c7821bb094 Mon Sep 17 00:00:00 2001 From: Mathew O'Dwyer Date: Mon, 4 Dec 2023 04:04:34 +1100 Subject: [PATCH 1/4] [WIP] Add Entity Component to Entities via `EntityInspectorView` From 067101d9a6c4c37d13837b7231137317cafac0d5 Mon Sep 17 00:00:00 2001 From: Mathew O'Dwyer Date: Mon, 4 Dec 2023 05:46:07 +1100 Subject: [PATCH 2/4] Getting there --- .../Core/TagComponent.cs | 15 +++-- .../Core/TransformComponent.cs | 66 ++++++++++--------- .../FinalEngine.ECS.Components.csproj | 1 - FinalEngine.Editor.Desktop/App.xaml.cs | 25 +++---- .../Views/Inspectors/EntityInspectorView.xaml | 26 +++++++- .../EntityComponentCategoryViewModel.cs | 28 ++++++++ .../EntityComponentTypeViewModel.cs | 63 ++++++++++++++++++ .../Inspectors/EntityInspectorViewModel.cs | 45 ++++++++++++- .../IEntityComponentCategoryViewModel.cs | 14 ++++ .../IEntityComponentTypeViewModel.cs | 14 ++++ .../Inspectors/IEntityInspectorViewModel.cs | 10 +-- .../Inspectors/PropertiesToolViewModel.cs | 43 ++++++------ .../Entities/EntityComponentTypeRetriever.cs | 47 +++++++++++++ .../Entities/IEntityComponentTypeRetriever.cs | 14 ++++ 14 files changed, 334 insertions(+), 77 deletions(-) create mode 100644 FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs create mode 100644 FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs create mode 100644 FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentCategoryViewModel.cs create mode 100644 FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentTypeViewModel.cs create mode 100644 FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeRetriever.cs create mode 100644 FinalEngine.Editor.ViewModels/Services/Entities/IEntityComponentTypeRetriever.cs diff --git a/FinalEngine.ECS.Components/Core/TagComponent.cs b/FinalEngine.ECS.Components/Core/TagComponent.cs index b38f48df..68a23dfb 100644 --- a/FinalEngine.ECS.Components/Core/TagComponent.cs +++ b/FinalEngine.ECS.Components/Core/TagComponent.cs @@ -1,5 +1,5 @@ // -// Copyright (c) Software Antics. All rights reserved. +// Copyright (c) Software Antics. All rights reserved. // namespace FinalEngine.ECS.Components.Core; @@ -7,26 +7,27 @@ namespace FinalEngine.ECS.Components.Core; using System.ComponentModel; /// -/// Provides a component that represents a name or tag for an . +/// Provides a component that represents a name or tag for an . /// -/// +/// +[Category("Core")] public sealed class TagComponent : IEntityComponent, INotifyPropertyChanged { /// - /// The tag. + /// The tag. /// private string? tag; /// - /// Occurs when a property value changes. + /// Occurs when a property value changes. /// public event PropertyChangedEventHandler? PropertyChanged; /// - /// Gets or sets the tag. + /// Gets or sets the tag. /// /// - /// The tag. + /// The tag. /// public string? Tag { diff --git a/FinalEngine.ECS.Components/Core/TransformComponent.cs b/FinalEngine.ECS.Components/Core/TransformComponent.cs index b85eb0bd..db2dcf33 100644 --- a/FinalEngine.ECS.Components/Core/TransformComponent.cs +++ b/FinalEngine.ECS.Components/Core/TransformComponent.cs @@ -4,16 +4,18 @@ namespace FinalEngine.ECS.Components.Core; +using System.ComponentModel; using System.Numerics; /// -/// Provides a component that represents the translation, rotation and scale of an entity. +/// Provides a component that represents the translation, rotation and scale of an entity. /// -/// +/// +[Category("Core")] public sealed class TransformComponent : IEntityComponent { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public TransformComponent() { @@ -23,10 +25,10 @@ public TransformComponent() } /// - /// Gets a normalized vector representing the negative Z-axis of the transform in world space. + /// Gets a normalized vector representing the negative Z-axis of the transform in world space. /// /// - /// The normalized vector representing the Z-axis of the transform in world space.. + /// The normalized vector representing the Z-axis of the transform in world space.. /// public Vector3 Backward { @@ -34,10 +36,10 @@ public Vector3 Backward } /// - /// Gets a normalized vector representing the negative Y-axis of the transform in world space. + /// Gets a normalized vector representing the negative Y-axis of the transform in world space. /// /// - /// The normalized vector representing the negative Y-axis of the transform in world space. + /// The normalized vector representing the negative Y-axis of the transform in world space. /// public Vector3 Down { @@ -45,10 +47,10 @@ public Vector3 Down } /// - /// Gets a normalized vector representing the Z-axis of the transform in world space. + /// Gets a normalized vector representing the Z-axis of the transform in world space. /// /// - /// The normalized vector representing the Z-axis of the transform in world space.. + /// The normalized vector representing the Z-axis of the transform in world space.. /// public Vector3 Forward { @@ -56,10 +58,10 @@ public Vector3 Forward } /// - /// Gets a normalized vector representing the negative X-axis of the transform in world space. + /// Gets a normalized vector representing the negative X-axis of the transform in world space. /// /// - /// The normalized vector representing the negative X-axis of the transform in world space. + /// The normalized vector representing the negative X-axis of the transform in world space. /// public Vector3 Left { @@ -67,18 +69,18 @@ public Vector3 Left } /// - /// Gets or sets the position of the transform. + /// Gets or sets the position of the transform. /// /// - /// The position of the transform. + /// The position of the transform. /// public Vector3 Position { get; set; } /// - /// Gets a normalized vector representing the X-axis of the transform in world space. + /// Gets a normalized vector representing the X-axis of the transform in world space. /// /// - /// The normalized vector representing the negative X-axis of the transform in world space. + /// The normalized vector representing the negative X-axis of the transform in world space. /// public Vector3 Right { @@ -86,26 +88,26 @@ public Vector3 Right } /// - /// Gets or sets the rotation of this transform. + /// Gets or sets the rotation of this transform. /// /// - /// The rotation of this transform. + /// The rotation of this transform. /// public Quaternion Rotation { get; set; } /// - /// Gets or sets the scale. + /// Gets or sets the scale. /// /// - /// The scale. + /// The scale. /// public Vector3 Scale { get; set; } /// - /// Gets a normalized vector representing the Y-axis of the transform in world space. + /// Gets a normalized vector representing the Y-axis of the transform in world space. /// /// - /// The normalized vector representing the negative Y-axis of the transform in world space. + /// The normalized vector representing the negative Y-axis of the transform in world space. /// public Vector3 Up { @@ -113,10 +115,10 @@ public Vector3 Up } /// - /// Creates the transformation matrix for this transform. + /// Creates the transformation matrix for this transform. /// /// - /// The newly create that represents the transformation matrix for this transform. + /// The newly create that represents the transformation matrix for this transform. /// public Matrix4x4 CreateTransformationMatrix() { @@ -126,13 +128,13 @@ public Matrix4x4 CreateTransformationMatrix() } /// - /// Creates the view matrix for this transform. + /// Creates the view matrix for this transform. /// /// - /// The camera up vector. + /// The camera up vector. /// /// - /// The newly created that represents the view matrix for this transform. + /// The newly created that represents the view matrix for this transform. /// public Matrix4x4 CreateViewMatrix(Vector3 cameraUp) { @@ -140,13 +142,13 @@ public Matrix4x4 CreateViewMatrix(Vector3 cameraUp) } /// - /// Rotates this transform on the specified by the specified . + /// Rotates this transform on the specified by the specified . /// /// - /// The axis to rotate. + /// The axis to rotate. /// /// - /// The radians that represents the amount to rotate by. + /// The radians that represents the amount to rotate by. /// public void Rotate(Vector3 axis, float radians) { @@ -155,13 +157,13 @@ public void Rotate(Vector3 axis, float radians) } /// - /// Translates this transform in the specified by the specified . + /// Translates this transform in the specified by the specified . /// /// - /// The direction to translate. + /// The direction to translate. /// /// - /// The amount to translate. + /// The amount to translate. /// public void Translate(Vector3 direction, float amount) { diff --git a/FinalEngine.ECS.Components/FinalEngine.ECS.Components.csproj b/FinalEngine.ECS.Components/FinalEngine.ECS.Components.csproj index aea1b33e..5bc917a1 100644 --- a/FinalEngine.ECS.Components/FinalEngine.ECS.Components.csproj +++ b/FinalEngine.ECS.Components/FinalEngine.ECS.Components.csproj @@ -8,7 +8,6 @@ false true x64 - true diff --git a/FinalEngine.Editor.Desktop/App.xaml.cs b/FinalEngine.Editor.Desktop/App.xaml.cs index 47a7ea24..d3e27993 100644 --- a/FinalEngine.Editor.Desktop/App.xaml.cs +++ b/FinalEngine.Editor.Desktop/App.xaml.cs @@ -1,5 +1,5 @@ // -// Copyright (c) Software Antics. All rights reserved. +// Copyright (c) Software Antics. All rights reserved. // namespace FinalEngine.Editor.Desktop; @@ -28,6 +28,7 @@ namespace FinalEngine.Editor.Desktop; using FinalEngine.Editor.ViewModels.Scenes; using FinalEngine.Editor.ViewModels.Services; using FinalEngine.Editor.ViewModels.Services.Actions; +using FinalEngine.Editor.ViewModels.Services.Entities; using FinalEngine.Editor.ViewModels.Services.Interactions; using FinalEngine.Editor.ViewModels.Services.Layout; using FinalEngine.Rendering; @@ -37,12 +38,12 @@ namespace FinalEngine.Editor.Desktop; using Microsoft.Extensions.Logging; /// -/// Interaction logic for App.xaml. +/// Interaction logic for App.xaml. /// public partial class App : Application { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public App() { @@ -52,18 +53,18 @@ public App() } /// - /// Gets or sets the application host. + /// Gets or sets the application host. /// /// - /// The application host. + /// The application host. /// private static IHost? AppHost { get; set; } /// - /// Exits the main application, disposing of any existing resources. + /// Exits the main application, disposing of any existing resources. /// /// - /// The instance containing the event data. + /// The instance containing the event data. /// protected override async void OnExit(ExitEventArgs e) { @@ -72,7 +73,7 @@ protected override async void OnExit(ExitEventArgs e) } /// - /// Starts up the main application on the current platform. + /// Starts up the main application on the current platform. /// /// /// A that contains the event data. @@ -94,13 +95,13 @@ protected override async void OnStartup(StartupEventArgs e) } /// - /// Configures the services to be consumed by the application. + /// Configures the services to be consumed by the application. /// /// - /// The application host builder context. + /// The application host builder context. /// /// - /// The services to be consumed by the application. + /// The services to be consumed by the application. /// private static void ConfigureServices(HostBuilderContext context, IServiceCollection services) { @@ -141,6 +142,8 @@ private static void ConfigureServices(HostBuilderContext context, IServiceCollec services.AddTransient, ManageWindowLayoutsView>(); services.AddTransient, CreateEntityView>(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); diff --git a/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml b/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml index ffa15617..c4412acc 100644 --- a/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml +++ b/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml @@ -8,7 +8,7 @@ d:DataContext="{d:DesignInstance Type=vm:EntityInspectorViewModel}" mc:Ignorable="d"> - + - + + + diff --git a/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs new file mode 100644 index 00000000..1b0166c1 --- /dev/null +++ b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Software Antics. All rights reserved. +// + +namespace FinalEngine.Editor.ViewModels.Inspectors; + +using System; +using System.Collections.Generic; +using CommunityToolkit.Mvvm.ComponentModel; + +public sealed class EntityComponentCategoryViewModel : ObservableObject, IEntityComponentCategoryViewModel +{ + private string? name; + + public EntityComponentCategoryViewModel(string name, IEnumerable componentTypes) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.ComponentTypes = componentTypes ?? throw new ArgumentNullException(nameof(componentTypes)); + } + + public IEnumerable ComponentTypes { get; } + + public string Name + { + get { return this.name ?? string.Empty; } + private set { this.SetProperty(ref this.name, value); } + } +} diff --git a/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs new file mode 100644 index 00000000..b5a5c9a2 --- /dev/null +++ b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs @@ -0,0 +1,63 @@ +// +// Copyright (c) Software Antics. All rights reserved. +// + +namespace FinalEngine.Editor.ViewModels.Inspectors; + +using System; +using System.Windows.Input; +using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; +using CommunityToolkit.Mvvm.Messaging; +using FinalEngine.ECS; +using FinalEngine.Editor.ViewModels.Messages.Entities; + +public sealed class EntityComponentTypeViewModel : ObservableObject, IEntityComponentTypeViewModel +{ + private readonly Entity entity; + + private readonly IMessenger messenger; + + private readonly Type type; + + private ICommand? addCommand; + + private string? name; + + public EntityComponentTypeViewModel(IMessenger messenger, Entity entity, Type type) + { + this.messenger = messenger ?? throw new ArgumentNullException(nameof(messenger)); + this.entity = entity ?? throw new ArgumentNullException(nameof(entity)); + this.type = type ?? throw new ArgumentNullException(nameof(type)); + + this.Name = this.type.Name; + } + + public ICommand AddCommand + { + get { return this.addCommand ??= new RelayCommand(this.AddComponent, this.CanAddComponent); } + } + + public string Name + { + get { return this.name ?? string.Empty; } + private set { this.SetProperty(ref this.name, value); } + } + + private void AddComponent() + { + //// TODO: Throw exception for non-parameterless constructors. + object? instance = Activator.CreateInstance(this.type); + + if (instance is not null and IEntityComponent component) + { + this.entity.AddComponent(component); + this.messenger.Send(new EntityModifiedMessage(this.entity)); + } + } + + private bool CanAddComponent() + { + return !this.entity.ContainsComponent(this.type); + } +} diff --git a/FinalEngine.Editor.ViewModels/Inspectors/EntityInspectorViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/EntityInspectorViewModel.cs index 65b88fb9..12bf4132 100644 --- a/FinalEngine.Editor.ViewModels/Inspectors/EntityInspectorViewModel.cs +++ b/FinalEngine.Editor.ViewModels/Inspectors/EntityInspectorViewModel.cs @@ -7,10 +7,14 @@ namespace FinalEngine.Editor.ViewModels.Inspectors; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; +using System.Reflection; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using FinalEngine.ECS; +using FinalEngine.ECS.Components.Core; using FinalEngine.Editor.ViewModels.Messages.Entities; +using FinalEngine.Editor.ViewModels.Services.Entities; /// /// Provides a standard implementation of an . @@ -19,6 +23,8 @@ namespace FinalEngine.Editor.ViewModels.Inspectors; /// public sealed class EntityInspectorViewModel : ObservableObject, IEntityInspectorViewModel { + private readonly ObservableCollection categorizedComponentTypes; + /// /// The component view models. /// @@ -34,6 +40,8 @@ public sealed class EntityInspectorViewModel : ObservableObject, IEntityInspecto /// private readonly IMessenger messenger; + private readonly IEntityComponentTypeRetriever typeRetriever; + /// /// Initializes a new instance of the class. /// @@ -46,15 +54,25 @@ public sealed class EntityInspectorViewModel : ObservableObject, IEntityInspecto /// /// The specified parameter cannot be null. /// - public EntityInspectorViewModel(IMessenger messenger, Entity entity) + public EntityInspectorViewModel(IMessenger messenger, IEntityComponentTypeRetriever typeRetriever, Entity entity) { this.messenger = messenger ?? throw new ArgumentNullException(nameof(messenger)); + this.typeRetriever = typeRetriever ?? throw new ArgumentNullException(nameof(typeRetriever)); this.entity = entity ?? throw new ArgumentNullException(nameof(entity)); + this.componentViewModels = new ObservableCollection(); + this.categorizedComponentTypes = new ObservableCollection(); this.messenger.Register(this, this.HandleEntityModified); this.InitializeEntityComponents(); + this.IntializeComponentTypes(); + } + + /// + public ICollection CategorizedComponentTypes + { + get { return this.categorizedComponentTypes; } } /// @@ -80,6 +98,7 @@ private void HandleEntityModified(object recipient, EntityModifiedMessage messag } this.InitializeEntityComponents(); + this.IntializeComponentTypes(); } /// @@ -94,4 +113,28 @@ private void InitializeEntityComponents() this.componentViewModels.Add(new EntityComponentViewModel(this.messenger, this.entity, component)); } } + + private void IntializeComponentTypes() + { + this.categorizedComponentTypes.Clear(); + + var assembly = Assembly.GetAssembly(typeof(TagComponent)); + + if (assembly is null) + { + return; + } + + var categoryToTypeMap = this.typeRetriever.GetCategorizedTypes(assembly); + + foreach (var kvp in categoryToTypeMap) + { + var typesViewModels = kvp.Value.Select(x => + { + return new EntityComponentTypeViewModel(this.messenger, this.entity, x); + }); + + this.categorizedComponentTypes.Add(new EntityComponentCategoryViewModel(kvp.Key, typesViewModels)); + } + } } diff --git a/FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentCategoryViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentCategoryViewModel.cs new file mode 100644 index 00000000..230c3b62 --- /dev/null +++ b/FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentCategoryViewModel.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Software Antics. All rights reserved. +// + +namespace FinalEngine.Editor.ViewModels.Inspectors; + +using System.Collections.Generic; + +public interface IEntityComponentCategoryViewModel +{ + IEnumerable ComponentTypes { get; } + + string Name { get; } +} diff --git a/FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentTypeViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentTypeViewModel.cs new file mode 100644 index 00000000..86d3bcff --- /dev/null +++ b/FinalEngine.Editor.ViewModels/Inspectors/IEntityComponentTypeViewModel.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Software Antics. All rights reserved. +// + +namespace FinalEngine.Editor.ViewModels.Inspectors; + +using System.Windows.Input; + +public interface IEntityComponentTypeViewModel +{ + ICommand AddCommand { get; } + + string Name { get; } +} diff --git a/FinalEngine.Editor.ViewModels/Inspectors/IEntityInspectorViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/IEntityInspectorViewModel.cs index f87b7781..a5e4ecf8 100644 --- a/FinalEngine.Editor.ViewModels/Inspectors/IEntityInspectorViewModel.cs +++ b/FinalEngine.Editor.ViewModels/Inspectors/IEntityInspectorViewModel.cs @@ -1,5 +1,5 @@ // -// Copyright (c) Software Antics. All rights reserved. +// Copyright (c) Software Antics. All rights reserved. // namespace FinalEngine.Editor.ViewModels.Inspectors; @@ -7,15 +7,17 @@ namespace FinalEngine.Editor.ViewModels.Inspectors; using System.Collections.Generic; /// -/// Defines an interface that represents a model of the entity inspector view. +/// Defines an interface that represents a model of the entity inspector view. /// public interface IEntityInspectorViewModel { + ICollection CategorizedComponentTypes { get; } + /// - /// Gets the component view models. + /// Gets the component view models. /// /// - /// The component view models. + /// The component view models. /// ICollection ComponentViewModels { get; } } diff --git a/FinalEngine.Editor.ViewModels/Inspectors/PropertiesToolViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/PropertiesToolViewModel.cs index f81e5839..1f83126d 100644 --- a/FinalEngine.Editor.ViewModels/Inspectors/PropertiesToolViewModel.cs +++ b/FinalEngine.Editor.ViewModels/Inspectors/PropertiesToolViewModel.cs @@ -1,5 +1,5 @@ // -// Copyright (c) Software Antics. All rights reserved. +// Copyright (c) Software Antics. All rights reserved. // namespace FinalEngine.Editor.ViewModels.Inspectors; @@ -9,44 +9,49 @@ namespace FinalEngine.Editor.ViewModels.Inspectors; using CommunityToolkit.Mvvm.Messaging; using FinalEngine.Editor.ViewModels.Docking.Tools; using FinalEngine.Editor.ViewModels.Messages.Entities; +using FinalEngine.Editor.ViewModels.Services.Entities; using Microsoft.Extensions.Logging; /// -/// Provides a standard implementation of an . +/// Provides a standard implementation of an . /// -/// -/// +/// +/// public sealed class PropertiesToolViewModel : ToolViewModelBase, IPropertiesToolViewModel { /// - /// The logger. + /// The logger. /// private readonly ILogger logger; /// - /// The messenger. + /// The messenger. /// private readonly IMessenger messenger; + private readonly IEntityComponentTypeRetriever typeRetriever; + /// - /// The current view model to be shown in the properties view. + /// The current view model to be shown in the properties view. /// private ObservableObject? currentViewModel; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// - /// The logger. + /// The logger. /// /// - /// The messenger. + /// The messenger. /// public PropertiesToolViewModel( ILogger logger, + IEntityComponentTypeRetriever typeRetriever, IMessenger messenger) { this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); + this.typeRetriever = typeRetriever ?? throw new ArgumentNullException(nameof(typeRetriever)); this.messenger = messenger ?? throw new ArgumentNullException(nameof(messenger)); this.Title = "Properties"; @@ -66,13 +71,13 @@ public ObservableObject? CurrentViewModel } /// - /// Handles the and resets the view. + /// Handles the and resets the view. /// /// - /// The recipient. + /// The recipient. /// /// - /// The message. + /// The message. /// private void HandleEntityDeleted(object recipient, EntityDeletedMessage message) { @@ -80,27 +85,27 @@ private void HandleEntityDeleted(object recipient, EntityDeletedMessage message) } /// - /// Handles the and updates the view. + /// Handles the and updates the view. /// /// - /// The recipient. + /// The recipient. /// /// - /// The message. + /// The message. /// /// - /// The specified parameter cannot be null. + /// The specified parameter cannot be null. /// private void HandleEntitySelected(object recipient, EntitySelectedMessage message) { this.logger.LogInformation($"Changing properties view to: '{nameof(EntityInspectorViewModel)}'."); this.Title = "Entity Inspector"; - this.CurrentViewModel = new EntityInspectorViewModel(this.messenger, message.Entity); + this.CurrentViewModel = new EntityInspectorViewModel(this.messenger, this.typeRetriever, message.Entity); } /// - /// Resets the current view model. + /// Resets the current view model. /// private void ResetCurrentViewModel() { diff --git a/FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeRetriever.cs b/FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeRetriever.cs new file mode 100644 index 00000000..125122dc --- /dev/null +++ b/FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeRetriever.cs @@ -0,0 +1,47 @@ +// +// Copyright (c) Software Antics. All rights reserved. +// + +namespace FinalEngine.Editor.ViewModels.Services.Entities; + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using FinalEngine.ECS; + +public sealed class EntityComponentTypeRetriever : IEntityComponentTypeRetriever +{ + public IReadOnlyDictionary> GetCategorizedTypes(Assembly assembly) + { + if (assembly == null) + { + throw new ArgumentNullException(nameof(assembly)); + } + + var categoryToTypeMap = new Dictionary>(); + + var componentTypes = assembly.GetTypes() + .Where(x => + { + return typeof(IEntityComponent).IsAssignableFrom(x) && x.GetConstructor(Type.EmptyTypes) != null; + }); + + foreach (var componentType in componentTypes) + { + var categoryAttribute = componentType.GetCustomAttribute(); + string category = categoryAttribute?.Category ?? "Uncategorized"; + + if (!categoryToTypeMap.TryGetValue(category, out var types)) + { + types = new List(); + categoryToTypeMap.Add(category, types); + } + + types.Add(componentType); + } + + return categoryToTypeMap; + } +} diff --git a/FinalEngine.Editor.ViewModels/Services/Entities/IEntityComponentTypeRetriever.cs b/FinalEngine.Editor.ViewModels/Services/Entities/IEntityComponentTypeRetriever.cs new file mode 100644 index 00000000..1f3030ac --- /dev/null +++ b/FinalEngine.Editor.ViewModels/Services/Entities/IEntityComponentTypeRetriever.cs @@ -0,0 +1,14 @@ +// +// Copyright (c) Software Antics. All rights reserved. +// + +namespace FinalEngine.Editor.ViewModels.Services.Entities; + +using System; +using System.Collections.Generic; +using System.Reflection; + +public interface IEntityComponentTypeRetriever +{ + IReadOnlyDictionary> GetCategorizedTypes(Assembly assembly); +} From e70abc406a43540e58fb321b4fbe978c2939c645 Mon Sep 17 00:00:00 2001 From: Mathew O'Dwyer Date: Mon, 4 Dec 2023 05:53:22 +1100 Subject: [PATCH 3/4] Fixed styling issue --- .../FinalEngine.Editor.Common.csproj | 1 - .../Models/Scenes/Scene.cs | 59 +++++++++++++++---- .../Views/Inspectors/EntityInspectorView.xaml | 47 +++++++-------- 3 files changed, 72 insertions(+), 35 deletions(-) diff --git a/FinalEngine.Editor.Common/FinalEngine.Editor.Common.csproj b/FinalEngine.Editor.Common/FinalEngine.Editor.Common.csproj index 40cbd522..4b6a8f87 100644 --- a/FinalEngine.Editor.Common/FinalEngine.Editor.Common.csproj +++ b/FinalEngine.Editor.Common/FinalEngine.Editor.Common.csproj @@ -8,7 +8,6 @@ false true x64 - true diff --git a/FinalEngine.Editor.Common/Models/Scenes/Scene.cs b/FinalEngine.Editor.Common/Models/Scenes/Scene.cs index 632e7b25..0f79ac46 100644 --- a/FinalEngine.Editor.Common/Models/Scenes/Scene.cs +++ b/FinalEngine.Editor.Common/Models/Scenes/Scene.cs @@ -1,5 +1,5 @@ // -// Copyright (c) Software Antics. All rights reserved. +// Copyright (c) Software Antics. All rights reserved. // namespace FinalEngine.Editor.Common.Models.Scenes; @@ -8,42 +8,78 @@ namespace FinalEngine.Editor.Common.Models.Scenes; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Numerics; using FinalEngine.ECS; using FinalEngine.ECS.Components.Core; using FinalEngine.Editor.Common.Exceptions.Entities; using Microsoft.Extensions.Logging; +public class SomeComponent : IEntityComponent +{ + public string Float { get; set; } + + public string Float2 { get; set; } + + public Vector2 Vector10 { get; set; } + + public Vector2 Vector11 { get; set; } + + public Vector2 Vector12 { get; set; } + + public Vector2 Vector13 { get; set; } + + public Vector2 Vector14 { get; set; } + + public Vector2 Vector15 { get; set; } + + public Vector2 Vector2 { get; set; } + + public Vector2 Vector3 { get; set; } + + public Vector2 Vector4 { get; set; } + + public Vector2 Vector5 { get; set; } + + public Vector2 Vector6 { get; set; } + + public Vector2 Vector7 { get; set; } + + public Vector2 Vector8 { get; set; } + + public Vector2 Vector9 { get; set; } +} + /// -/// Represents a scene that contains a collection of entities and systems. +/// Represents a scene that contains a collection of entities and systems. /// public sealed class Scene : IScene { /// - /// The entities contained within the scene. + /// The entities contained within the scene. /// private readonly ObservableCollection entities; /// - /// The logger. + /// The logger. /// private readonly ILogger logger; /// - /// The underlying entity world that contains all the scenes entities and systems. + /// The underlying entity world that contains all the scenes entities and systems. /// private readonly IEntityWorld world; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// - /// The logger. + /// The logger. /// /// - /// The entity world to be associated with this scene. + /// The entity world to be associated with this scene. /// /// - /// The specified or parameter cannot be null. + /// The specified or parameter cannot be null. /// public Scene(ILogger logger, IEntityWorld world) { @@ -60,7 +96,7 @@ public IReadOnlyCollection Entities /// /// - /// The specified parameter cannot be null or whitespace. + /// The specified parameter cannot be null or whitespace. /// public void AddEntity(string tag, Guid uniqueID) { @@ -79,6 +115,7 @@ public void AddEntity(string tag, Guid uniqueID) }); entity.AddComponent(new TransformComponent()); + entity.AddComponent(new SomeComponent()); this.world.AddEntity(entity); this.entities.Add(entity); @@ -88,7 +125,7 @@ public void AddEntity(string tag, Guid uniqueID) /// /// - /// Failed to locate an that matches the specified . + /// Failed to locate an that matches the specified . /// public void RemoveEntity(Guid uniqueIdentifier) { diff --git a/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml b/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml index c4412acc..91d35aea 100644 --- a/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml +++ b/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml @@ -8,28 +8,8 @@ d:DataContext="{d:DesignInstance Type=vm:EntityInspectorViewModel}" mc:Ignorable="d"> - - - - - - - - - - - - - - - - - - -