Files
GhostEngine/Ghost.Editor.Core/Controls/Internal/ComponentDataView.cs
Misaki 5ae4128baf Enhance graphics engine and code organization
Added `InternalsVisibleTo` attribute for "Ghost.Graphics" and "Ghost.Editor" in `AssemblyInfo.cs`.
Added a new `EngineAssemblyAttribute` in `EngineAssemblyAttribute.cs`.
Added a reference to `Misaki.HighPerformance.Unsafe` in `Ghost.Core.csproj`.
Added a new `Bounds` struct to represent axis-aligned bounding boxes in `Bounds.cs`.
Added new `Color32` and `Color128` structs for color representation in `Color.cs`.

Changed the namespace from `Ghost.Editor.Controls` to `Ghost.Editor.Core.Controls` in multiple files.
Changed the implicit conversion operator in `ConstPtr<T>` to use a more descriptive parameter name in `ConstPtr.cs`.
Changed the `Mesh` class to use `Color128` instead of `Color32` for color representation.

Enhanced the `TypeCache` class to load types from assemblies marked with `EngineAssemblyAttribute`.
Enhanced the `ProjectService` class to improve the `GetAllProjectAsync` method by filtering out bad projects.
Enhanced the `GraphicsPipeline` class to support both DX12 and D3D12 graphics APIs.
Enhanced the `Shader` class to include methods for compiling HLSL shaders and managing root signatures.
Enhanced the `MeshRenderPass` class to utilize the new shader compilation methods.

Refactored the `AppStateMachine` class to use private fields instead of static fields for state management.
Refactored the `ComponentDataView` class to use the new namespace and improve organization.
Refactored project references in `Ghost.Graphics.csproj` to include new dependencies and remove outdated ones.

Made various adjustments to ensure consistency and improve code quality across multiple files.
2025-07-02 21:30:10 +09:00

140 lines
3.9 KiB
C#

using Ghost.Core;
using Ghost.Editor.Core.Inspector;
using Ghost.Editor.Core.Resources;
using Ghost.Editor.Core.Utilities;
using Ghost.Entities;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Reflection;
namespace Ghost.Editor.Core.Controls.Internal;
internal unsafe sealed partial class ComponentDataView : Control
{
private delegate void EditorUpdate();
private StackPanel? _contentContainer;
private readonly World? _world;
private readonly Entity _entity = Entity.Invalid;
private readonly Type? _componentType;
private ComponentEditor? _customEditor;
private PropertyField[]? _propertyFields;
private EditorUpdate? _editorUpdate;
public string HeaderText
{
get => (string)GetValue(HeaderTextProperty);
set => SetValue(HeaderTextProperty, value);
}
public static readonly DependencyProperty HeaderTextProperty =
DependencyProperty.Register(nameof(HeaderText), typeof(string), typeof(ComponentDataView), new PropertyMetadata(string.Empty));
internal ComponentDataView()
{
DefaultStyleKey = typeof(ComponentDataView);
Unloaded += (s, e) =>
{
_customEditor?.Destroy();
_contentContainer = null;
_customEditor = null;
_propertyFields = null;
};
}
public ComponentDataView(string header, World world, Entity entity, Type componentType) : this()
{
HeaderText = header;
_world = world;
_entity = entity;
_componentType = componentType;
}
protected override void OnApplyTemplate()
{
_contentContainer = (StackPanel)GetTemplateChild("ContentContainer");
base.OnApplyTemplate();
ReBuild();
}
private void ReflectionUpdate()
{
if (_propertyFields == null)
{
return;
}
foreach (var propertyField in _propertyFields)
{
propertyField.UpdateValue();
}
}
private void CustomEditorUpdate()
{
_customEditor!.Update();
}
public void ReBuild()
{
if (_contentContainer == null)
{
return;
}
_contentContainer.Children.Clear();
if (_world == null || _componentType == null || _entity == Entity.Invalid)
{
return;
}
var componentObject = new ComponentObject(_world, _entity);
var editorType = TypeCache.GetTypes().FirstOrDefault(t =>
typeof(ComponentEditor).IsAssignableFrom(t) &&
t.GetCustomAttribute<CustomEditorAttribute>()?.TargetType.IsAssignableFrom(_componentType) == true);
if (editorType != null)
{
_customEditor = (ComponentEditor)Activator.CreateInstance(editorType)!;
_customEditor.Initialize(componentObject);
_customEditor.Create(_contentContainer);
}
else
{
var fields = _componentType.GetFields(StaticResource.componentPropertyBindingFlags);
_propertyFields = new PropertyField[fields.Length];
for (var i = 0; i < fields.Length; i++)
{
var field = fields[i];
var component = _world.ComponentStorage.ComponentPools[TypeHandle.Get(_componentType)].Get(_entity);
var propertyField = PropertyField.Create(field.Name, field, component);
_propertyFields[i] = propertyField;
_contentContainer.Children.Add(propertyField);
}
}
_editorUpdate = _customEditor == null ? ReflectionUpdate : CustomEditorUpdate;
_editorUpdate();
_world.ComponentChanged += OnComponentChanged;
}
private void OnComponentChanged(World world, Entity entity, Type type)
{
if (world != _world
|| entity != _entity
|| type != _componentType)
{
return;
}
_editorUpdate?.Invoke();
}
}