Refactor project structure and enhance functionality

Changed the project namespace from `Ghost.Editor` to `Ghost.App` across multiple files.
Changed the `InternalsVisibleTo` attribute in `AssemblyInfo.cs` to include `Ghost.App`.
Changed the `ProjectRepository` class to add new asynchronous methods for retrieving projects by ID, name, and metadata path.
Changed the `ProjectService` class to utilize the new asynchronous project loading methods.
Changed the `SceneGraph` classes to improve node management and serialization.
Changed the `EntityManager` class to enhance entity management with new component handling methods.
Added new test classes, `EntityTest` and `SerializationTest`, to ensure reliability in entity and serialization systems.
Added the `Ghost.App` project file to establish a modular project structure.
Added the `Ghost.Generator` project for automated component serialization code generation.
Updated UI components to reflect the new namespace for proper functionality.
This commit is contained in:
2025-06-07 20:54:07 +09:00
parent bab3be2508
commit 40d333b004
123 changed files with 1441 additions and 740 deletions

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Ghost.App.View.Pages.EngineEditor.ConsolePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Ghost.App.View.Pages.EngineEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource LayerFillColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Toolbar -->
<Grid
Grid.Row="0"
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
BorderThickness="0,0,0,1">
<CommandBar Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}" DefaultLabelPosition="Collapsed">
<CommandBar.PrimaryCommands>
<AppBarButton Command="{x:Bind ViewModel.ClearLogsCommand}" Content="Clear" />
<AppBarSeparator />
<AppBarToggleButton Width="45" IsChecked="{x:Bind ViewModel.ShowInfo, Mode=TwoWay}">
<AppBarToggleButton.Icon>
<FontIcon Glyph="&#xF167;" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton Width="45" IsChecked="{x:Bind ViewModel.ShowWarning, Mode=TwoWay}">
<AppBarToggleButton.Icon>
<FontIcon Glyph="&#xE814;" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
<AppBarToggleButton Width="45" IsChecked="{x:Bind ViewModel.ShowError, Mode=TwoWay}">
<AppBarToggleButton.Icon>
<FontIcon Glyph="&#xEB90;" />
</AppBarToggleButton.Icon>
</AppBarToggleButton>
</CommandBar.PrimaryCommands>
<CommandBar.SecondaryCommands>
<AppBarToggleButton BorderThickness="0" Label="Clear On Play" />
<AppBarToggleButton
BorderThickness="0"
IsChecked="{x:Bind ViewModel.ShowStackTrace, Mode=TwoWay}"
Label="Show Stack Trace" />
</CommandBar.SecondaryCommands>
</CommandBar>
</Grid>
<!-- Log Content -->
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<ListView
x:Name="LogListView"
Grid.Row="0"
ItemsSource="{x:Bind ViewModel.Logs, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedLog, Mode=TwoWay}" />
<Grid
Grid.Row="1"
Padding="4"
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
BorderThickness="0,1,0,0">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<TextBlock
IsTextSelectionEnabled="True"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind ViewModel.SelectedLog.ToStringWithStackTrace(), Mode=OneWay}"
TextWrapping="Wrap" />
</ScrollViewer>
</Grid>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,19 @@
using Ghost.Editor.ViewModels.Pages.EngineEditor;
using Microsoft.UI.Xaml.Controls;
namespace Ghost.App.View.Pages.EngineEditor;
internal sealed partial class ConsolePage : Page
{
public ConsoleViewModel ViewModel
{
get;
}
public ConsolePage()
{
ViewModel = GhostApplication.GetService<ConsoleViewModel>();
InitializeComponent();
}
}

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Ghost.App.View.Pages.EngineEditor.HierarchyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Ghost.App.View.Pages.EngineEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sg="using:Ghost.Editor.SceneGraph"
mc:Ignorable="d">
<Page.Resources>
<DataTemplate x:Key="SceneTemplate" x:DataType="sg:SceneGraphNode">
<TreeViewItem
AutomationProperties.Name="{x:Bind Name}"
Background="{ThemeResource ControlSolidFillColorDefaultBrush}"
IsExpanded="True"
ItemsSource="{x:Bind Children}">
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="14" Glyph="&#xF159;" />
<TextBlock Margin="10,0" Text="{x:Bind Name}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
<DataTemplate x:Key="EntityTemplate" x:DataType="sg:SceneGraphNode">
<TreeViewItem AutomationProperties.Name="{x:Bind Name}" ItemsSource="{x:Bind Children}">
<StackPanel Orientation="Horizontal">
<FontIcon FontSize="14" Glyph="&#xF158;" />
<TextBlock Margin="10,0" Text="{x:Bind Name}" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
</Page.Resources>
<Grid Padding="4,6" Background="{ThemeResource LayerFillColorDefaultBrush}">
<TreeView ItemsSource="{x:Bind ViewModel.SceneList}">
<TreeView.ItemTemplateSelector>
<local:HierarchyTemplateSector EntityTemplate="{StaticResource EntityTemplate}" WorldTemplate="{StaticResource SceneTemplate}" />
</TreeView.ItemTemplateSelector>
</TreeView>
</Grid>
</Page>

View File

@@ -0,0 +1,57 @@
using Ghost.Editor.SceneGraph;
using Ghost.Editor.ViewModels.Pages.EngineEditor;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace Ghost.App.View.Pages.EngineEditor;
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
internal sealed partial class HierarchyPage : Page
{
public HierarchyViewModel ViewModel
{
get;
}
public HierarchyPage()
{
ViewModel = GhostApplication.GetService<HierarchyViewModel>();
InitializeComponent();
}
}
internal partial class HierarchyTemplateSector : DataTemplateSelector
{
public DataTemplate? WorldTemplate
{
get;
set;
}
public DataTemplate? EntityTemplate
{
get;
set;
}
protected override DataTemplate SelectTemplateCore(object item)
{
if (WorldTemplate == null || EntityTemplate == null)
{
return base.SelectTemplateCore(item);
}
var node = (SceneGraphNode)item;
return node.NodeType switch
{
SceneGraphNodeType.Scene => WorldTemplate,
SceneGraphNodeType.Entity => EntityTemplate,
_ => base.SelectTemplateCore(item)
};
}
}

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Ghost.App.View.Pages.EngineEditor.ProjectPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="using:Ghost.Editor.Utilities.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Ghost.App.View.Pages.EngineEditor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:Ghost.App.Models"
mc:Ignorable="d">
<Page.Resources>
<converter:AssetPathToGlyphConverter x:Key="AssetPathToGlyphConverter" />
</Page.Resources>
<Grid Background="{ThemeResource LayerFillColorDefaultBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Folder Tree View -->
<Grid
Grid.Column="0"
Padding="4"
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
BorderThickness="0,0,1,0">
<TreeView
x:Name="DirectoryTreeView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{x:Bind ViewModel.SubDirectories}"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedItem="{x:Bind ViewModel.SelectedDirectory, Mode=TwoWay}">
<TreeView.ItemTemplate>
<DataTemplate x:DataType="model:ExplorerItem">
<TreeViewItem ItemsSource="{x:Bind Children}">
<StackPanel Orientation="Horizontal">
<FontIcon
VerticalAlignment="Center"
FontSize="14"
Glyph="&#xE8B7;" />
<TextBlock
Margin="8,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Name}"
TextTrimming="CharacterEllipsis" />
</StackPanel>
</TreeViewItem>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
<!-- Files -->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid
Grid.Row="0"
Padding="4"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
BorderThickness="0,0,0,1">
<BreadcrumbBar Height="15" />
</Grid>
<ScrollViewer
Grid.Row="1"
Padding="8"
VerticalAlignment="Stretch"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<GridView
x:Name="AssetsGridView"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{x:Bind ViewModel.DirectoryAssets, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedAsset, Mode=TwoWay}">
<GridView.ItemContainerStyle>
<Style BasedOn="{StaticResource DefaultGridViewItemStyle}" TargetType="GridViewItem">
<Setter Property="Margin" Value="2" />
</Style>
</GridView.ItemContainerStyle>
<GridView.ItemTemplate>
<DataTemplate x:DataType="model:ExplorerItem">
<Grid
Width="100"
Height="100"
Padding="8"
DoubleTapped="GridViewItem_DoubleTapped"
IsDoubleTapEnabled="True">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="0.25*" />
</Grid.RowDefinitions>
<FontIcon FontSize="42" Glyph="{x:Bind Path, Converter={StaticResource AssetPathToGlyphConverter}}" />
<TextBlock
Grid.Row="1"
Margin="8,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Name}"
TextTrimming="CharacterEllipsis" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</ScrollViewer>
<Grid
Grid.Row="2"
Padding="4"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
BorderThickness="0,1,0,0">
<TextBlock
VerticalAlignment="Center"
HorizontalTextAlignment="Left"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind ViewModel.SelectedAsset.Path, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
</Grid>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,25 @@
using Ghost.Editor.ViewModels.Pages.EngineEditor;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
namespace Ghost.App.View.Pages.EngineEditor;
internal sealed partial class ProjectPage : Page
{
public ProjectViewModel ViewModel
{
get;
}
public ProjectPage()
{
ViewModel = GhostApplication.GetService<ProjectViewModel>();
InitializeComponent();
}
private void GridViewItem_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
ViewModel.NavigateToSelected();
}
}