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 @@
falsetruex64
- true
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 @@
falsetruex64
- true
diff --git a/FinalEngine.Editor.Common/Models/Scenes/Scene.cs b/FinalEngine.Editor.Common/Models/Scenes/Scene.cs
index 632e7b25..982cca59 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;
@@ -14,36 +14,36 @@ namespace FinalEngine.Editor.Common.Models.Scenes;
using Microsoft.Extensions.Logging;
///
-/// 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 +60,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)
{
@@ -88,7 +88,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/App.xaml.cs b/FinalEngine.Editor.Desktop/App.xaml.cs
index 47a7ea24..6f6e446e 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..91d35aea 100644
--- a/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml
+++ b/FinalEngine.Editor.Desktop/Views/Inspectors/EntityInspectorView.xaml
@@ -8,8 +8,31 @@
d:DataContext="{d:DesignInstance Type=vm:EntityInspectorViewModel}"
mc:Ignorable="d">
-
-
+
+
+
@@ -28,5 +51,5 @@
-
+
diff --git a/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs
new file mode 100644
index 00000000..d17ff0c5
--- /dev/null
+++ b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentCategoryViewModel.cs
@@ -0,0 +1,27 @@
+//
+// 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
+{
+ public EntityComponentCategoryViewModel(string name, IEnumerable componentTypes)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ throw new ArgumentException($"'{nameof(name)}' cannot be null or whitespace.", nameof(name));
+ }
+
+ this.Name = name;
+ this.ComponentTypes = componentTypes ?? throw new ArgumentNullException(nameof(componentTypes));
+ }
+
+ public IEnumerable ComponentTypes { get; }
+
+ public string Name { get; }
+}
diff --git a/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs
new file mode 100644
index 00000000..ed32bf52
--- /dev/null
+++ b/FinalEngine.Editor.ViewModels/Inspectors/EntityComponentTypeViewModel.cs
@@ -0,0 +1,73 @@
+//
+// 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;
+
+ public EntityComponentTypeViewModel(IMessenger messenger, Entity entity, Type type)
+ {
+ this.messenger = messenger ?? throw new ArgumentNullException(nameof(messenger));
+ this.entity = entity ?? throw new ArgumentNullException(nameof(entity));
+
+ if (type == null)
+ {
+ throw new ArgumentNullException(nameof(type));
+ }
+
+ if (!typeof(IEntityComponent).IsAssignableFrom(type))
+ {
+ throw new ArgumentException($"The specified {nameof(type)} parameter does not implement {nameof(IEntityComponent)}.");
+ }
+
+ this.type = type;
+ this.Name = this.type.Name;
+ }
+
+ public ICommand AddCommand
+ {
+ get { return this.addCommand ??= new RelayCommand(this.AddComponent, this.CanAddComponent); }
+ }
+
+ public string Name { get; }
+
+ private void AddComponent()
+ {
+ object? instance = Activator.CreateInstance(this.type) ?? throw new InvalidOperationException($"The entity component couldn't be instantiated for the specified type: '{this.type}'. Please ensure the component contains a default empty constructor.");
+
+ if (instance is not IEntityComponent component)
+ {
+ throw new InvalidCastException($"The created instance of type '{instance.GetType()}' does not implement the {nameof(IEntityComponent)} interface.");
+ }
+
+ if (this.entity.ContainsComponent(this.type))
+ {
+ return;
+ }
+
+ 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..4b1ff215 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 IEntityComponentTypeResolver typeResolver;
+
///
/// 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, IEntityComponentTypeResolver typeResolver, Entity entity)
{
this.messenger = messenger ?? throw new ArgumentNullException(nameof(messenger));
+ this.typeResolver = typeResolver ?? throw new ArgumentNullException(nameof(typeResolver));
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,23 @@ 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)) ?? throw new TypeAccessException("Failed to initialize core engine components.");
+
+ var categoryToTypeMap = this.typeResolver.GetCategorizedTypes(assembly);
+
+ foreach (var kvp in categoryToTypeMap)
+ {
+ var typeViewModels = kvp.Value.Select(x =>
+ {
+ return new EntityComponentTypeViewModel(this.messenger, this.entity, x);
+ });
+
+ this.categorizedComponentTypes.Add(new EntityComponentCategoryViewModel(kvp.Key, typeViewModels));
+ }
+ }
}
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..4001876d 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 IEntityComponentTypeResolver typeResolver;
+
///
- /// 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,
+ IEntityComponentTypeResolver typeResolver,
IMessenger messenger)
{
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ this.typeResolver = typeResolver ?? throw new ArgumentNullException(nameof(typeResolver));
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.typeResolver, message.Entity);
}
///
- /// Resets the current view model.
+ /// Resets the current view model.
///
private void ResetCurrentViewModel()
{
diff --git a/FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeResolver.cs b/FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeResolver.cs
new file mode 100644
index 00000000..a28a9d97
--- /dev/null
+++ b/FinalEngine.Editor.ViewModels/Services/Entities/EntityComponentTypeResolver.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 EntityComponentTypeResolver : IEntityComponentTypeResolver
+{
+ 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/IEntityComponentTypeResolver.cs b/FinalEngine.Editor.ViewModels/Services/Entities/IEntityComponentTypeResolver.cs
new file mode 100644
index 00000000..dbcbf793
--- /dev/null
+++ b/FinalEngine.Editor.ViewModels/Services/Entities/IEntityComponentTypeResolver.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 IEntityComponentTypeResolver
+{
+ IReadOnlyDictionary> GetCategorizedTypes(Assembly assembly);
+}