Files
GhostEngine/Ghost.App/Core/SceneGraph/EntityNode.cs
Misaki 1724072f7e Add component editors and UI controls
Added the `HierarchyEditor` and `LocalToWorldEditor` classes to implement custom component editing functionality.
Added the `Vector3Field` control for 3D vector manipulation and its corresponding XAML definition.
Added the `ComponentDataView` and `ComponentObject` classes to manage component data display and access.
Added the `CustomEditorAttribute` to mark classes as custom editors for specific components.

Changed the `IInspectable` interface to use properties for `Icon`, `HeaderContent`, and `InspectorContent`.
Changed the `PropertyField` class to enhance UI control binding capabilities.
Changed the `EditorWorldManager` to improve world data loading and deserialization processes.
Changed the `EntityNode` and `WorldNode` classes to update entity construction and component querying.
Changed the `StaticResource` class to include new binding flags for component properties.
Changed the `InspectorService` to remove old contract references and adopt new interfaces.
Changed the `QueryEnumerable` and related files to update generic constraints for improved type safety.
Changed the `QueryItem` class to reflect new generic constraints and enhance deconstruction.
Changed the `World.Query` methods to utilize the updated generic constraints.

Updated the `SerializationTest` to align with new entity creation and management practices.
2025-06-20 20:19:14 +09:00

102 lines
2.9 KiB
C#

using Ghost.Editor.Controls.Internal;
using Ghost.Editor.Core.Inspector;
using Ghost.Editor.Resources;
using Ghost.Engine.Editor;
using Ghost.Entities;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Data;
using System.Reflection;
namespace Ghost.Editor.Core.SceneGraph;
public partial class EntityNode : SceneGraphNode
{
private WorldNode _owner;
private readonly Entity _entity;
public Entity Entity => _entity;
public override SceneGraphNodeType NodeType => SceneGraphNodeType.Entity;
public EntityNode(WorldNode owner, Entity entity, string name)
{
_owner = owner;
_entity = entity;
Name = name;
}
}
public partial class EntityNode : IInspectable
{
public IconSource? Icon => EditorIconSource.entity_24;
public UIElement? HeaderContent
{
get
{
var root = new StackPanel()
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Center
};
var nameText = new TextBox
{
Text = Name,
FontWeight = FontWeights.Bold,
};
var idText = new TextBlock
{
Text = $"ID: {_entity.ID} Generation: {_entity.Generation}",
Margin = new Thickness(5, 7, 0, 0),
Opacity = 0.75,
Style = Application.Current.Resources["CaptionTextBlockStyle"] as Style
};
nameText.SetBinding(TextBox.TextProperty, new Binding
{
Source = this,
Path = new PropertyPath(nameof(Name)),
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus,
});
root.Children.Add(nameText);
root.Children.Add(idText);
return root;
}
}
public UIElement? InspectorContent
{
get
{
var root = new StackPanel()
{
HorizontalAlignment = HorizontalAlignment.Stretch,
VerticalAlignment = VerticalAlignment.Top
};
foreach (var (typeHandle, componentPtr) in _owner.World.EntityManager.GetComponentsUnsafe(_entity))
{
if (componentPtr == IntPtr.Zero)
{
continue;
}
var type = Type.GetTypeFromHandle(RuntimeTypeHandle.FromIntPtr(typeHandle));
if (type == null || type.GetCustomAttribute<HideEditorAttribute>() != null)
{
continue;
}
var dataView = new ComponentDataView(type.Name, _owner.World, _entity, type);
root.Children.Add(dataView);
}
return root;
}
}
}