forked from Misaki/GhostEngine
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.
140 lines
3.9 KiB
C#
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();
|
|
}
|
|
} |