Refactor project from Ghost.App to Ghost.Editor
Changed the project structure to reflect a shift from `Ghost.App` to `Ghost.Editor`, updating namespaces and class names throughout. Changed the application class in `App.xaml` and `App.xaml.cs` from `GhostApplication` to `EditorApplication`. Changed several service interfaces to reside under `Ghost.Editor.Services.Contracts`, including `IInspectorService`, `INotificationService`, and `IProgressService`. Added `InspectorView` and `InspectorViewModel` classes to manage inspector functionality. Added `NavigationTabView` and `NavigationTabPage` classes to facilitate navigation within the editor. Enhanced `WorldNode` and `EntityNode` classes to support scene graph functionality, including serialization and entity management. Updated the project file `Ghost.Editor.csproj` to reflect the new structure and removed old references. Modified the solution file `GhostEngine.sln` to remove references to `Ghost.App` and include `Ghost.Editor`. Updated unit tests to align with the new namespaces and project structure.
This commit is contained in:
@@ -3,7 +3,7 @@ using Ghost.Data.Services;
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace Ghost.App;
|
namespace Ghost.Editor;
|
||||||
|
|
||||||
internal static class ActivationHandler
|
internal static class ActivationHandler
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Application
|
<Application
|
||||||
x:Class="Ghost.App.GhostApplication"
|
x:Class="Ghost.Editor.EditorApplication"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:Ghost.App">
|
xmlns:local="using:Ghost.Editor">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
|||||||
@@ -1,31 +1,30 @@
|
|||||||
using Ghost.App.Infrastructures.AppState;
|
using Ghost.Editor.Core.AppState;
|
||||||
using Ghost.App.Services;
|
using Ghost.Editor.Services;
|
||||||
using Ghost.App.Utilities;
|
|
||||||
using Ghost.Editor.Services.Contracts;
|
using Ghost.Editor.Services.Contracts;
|
||||||
|
using Ghost.Editor.Utilities;
|
||||||
using Ghost.Engine.Services;
|
using Ghost.Engine.Services;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using System;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
namespace Ghost.App;
|
namespace Ghost.Editor;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides application-specific behavior to supplement the default Application class.
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class GhostApplication : Application
|
public partial class EditorApplication : Application
|
||||||
{
|
{
|
||||||
private Window? _window;
|
private Window? _window;
|
||||||
|
|
||||||
internal static Window? Window
|
internal static Window? Window
|
||||||
{
|
{
|
||||||
get => (Current as GhostApplication)!._window;
|
get => (Current as EditorApplication)!._window;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (Current is GhostApplication app)
|
if (Current is EditorApplication app)
|
||||||
{
|
{
|
||||||
app._window = value;
|
app._window = value;
|
||||||
}
|
}
|
||||||
@@ -41,7 +40,7 @@ public partial class GhostApplication : Application
|
|||||||
/// Initializes the singleton application object. This is the first line of authored code
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal GhostApplication()
|
internal EditorApplication()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
@@ -56,6 +55,7 @@ public partial class GhostApplication : Application
|
|||||||
services.AddSingleton<AppStateMachine>();
|
services.AddSingleton<AppStateMachine>();
|
||||||
services.AddSingleton<INotificationService, NotificationService>();
|
services.AddSingleton<INotificationService, NotificationService>();
|
||||||
services.AddSingleton<IProgressService, ProgressService>();
|
services.AddSingleton<IProgressService, ProgressService>();
|
||||||
|
services.AddSingleton<IInspectorService, InspectorService>();
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@@ -64,12 +64,12 @@ public partial class GhostApplication : Application
|
|||||||
|
|
||||||
internal static IServiceScope CreateScope()
|
internal static IServiceScope CreateScope()
|
||||||
{
|
{
|
||||||
return (Current as GhostApplication)!.Host.Services.CreateScope();
|
return (Current as EditorApplication)!.Host.Services.CreateScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T GetService<T>() where T : class
|
public static T GetService<T>() where T : class
|
||||||
{
|
{
|
||||||
if ((Current as GhostApplication)!.Host.Services.GetService(typeof(T)) is not T service)
|
if ((Current as EditorApplication)!.Host.Services.GetService(typeof(T)) is not T service)
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs.");
|
throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices within App.xaml.cs.");
|
||||||
}
|
}
|
||||||
|
|||||||
3
Ghost.App/AssemblyInfo.cs
Normal file
3
Ghost.App/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Ghost.UnitTest")]
|
||||||
15
Ghost.App/Contracts/IInspectable.cs
Normal file
15
Ghost.App/Contracts/IInspectable.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Contracts;
|
||||||
|
|
||||||
|
public interface IInspectable
|
||||||
|
{
|
||||||
|
public IconSource? Icon
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIElement? HeaderContent();
|
||||||
|
public UIElement? InspectorContent();
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ghost.App.Contracts;
|
namespace Ghost.Editor.Contracts;
|
||||||
|
|
||||||
public interface INavigationAware
|
public interface INavigationAware
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
using Microsoft.UI.Xaml;
|
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
|
|
||||||
namespace Ghost.Editor.Controls.Internal;
|
|
||||||
|
|
||||||
internal sealed partial class InspectorView : ContentControl
|
|
||||||
{
|
|
||||||
public UIElement? Header
|
|
||||||
{
|
|
||||||
get => (UIElement)GetValue(HeaderProperty);
|
|
||||||
set => SetValue(HeaderProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
|
||||||
nameof(Header),
|
|
||||||
typeof(UIElement),
|
|
||||||
typeof(InspectorView),
|
|
||||||
new PropertyMetadata(null));
|
|
||||||
|
|
||||||
public InspectorView()
|
|
||||||
{
|
|
||||||
DefaultStyleKey = typeof(InspectorView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<ResourceDictionary
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:local="using:Ghost.Editor.Controls.Internal">
|
|
||||||
<Style TargetType="local:InspectorView">
|
|
||||||
<Setter Property="Template">
|
|
||||||
<Setter.Value>
|
|
||||||
<ControlTemplate TargetType="local:InspectorView">
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="50" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<!-- Header -->
|
|
||||||
<Grid Grid.Row="0">
|
|
||||||
<ContentPresenter
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
Content="{TemplateBinding Header}"
|
|
||||||
ContentTemplate="{TemplateBinding HeaderTemplate}" />
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<!-- Content -->
|
|
||||||
<Grid Grid.Row="1">
|
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
|
||||||
<ContentPresenter
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
Content="{TemplateBinding Content}"
|
|
||||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
|
||||||
ContentTransitions="{TemplateBinding ContentTransitions}" />
|
|
||||||
</ScrollViewer>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</ControlTemplate>
|
|
||||||
</Setter.Value>
|
|
||||||
</Setter>
|
|
||||||
</Style>
|
|
||||||
</ResourceDictionary>
|
|
||||||
39
Ghost.App/Controls/Internal/NavigationTabView.cs
Normal file
39
Ghost.App/Controls/Internal/NavigationTabView.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Controls.Internal;
|
||||||
|
|
||||||
|
public partial class NavigationTabPage : TabViewItem, INavigationAware
|
||||||
|
{
|
||||||
|
public virtual void OnNavigatedTo(object? parameter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnNavigatedFrom()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed partial class NavigationTabView : TabView
|
||||||
|
{
|
||||||
|
public NavigationTabView()
|
||||||
|
{
|
||||||
|
this.SelectionChanged += NavigationTabView_SelectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavigationTabView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
foreach (var oldItem in e.RemovedItems)
|
||||||
|
{
|
||||||
|
if (oldItem is NavigationTabPage oldPage)
|
||||||
|
{
|
||||||
|
oldPage.OnNavigatedFrom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SelectedItem is NavigationTabPage newPage)
|
||||||
|
{
|
||||||
|
newPage.OnNavigatedTo(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
Ghost.App/Controls/Internal/NavigationTabView.xaml
Normal file
5
Ghost.App/Controls/Internal/NavigationTabView.xaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:Ghost.Editor.Controls.Internal" />
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.App.Contracts;
|
using Ghost.Editor.Contracts;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
|
|
||||||
namespace Ghost.App.Controls;
|
namespace Ghost.Editor.Controls;
|
||||||
|
|
||||||
public abstract partial class ViewModelPage<VM> : Page
|
public abstract partial class ViewModelPage<VM> : Page
|
||||||
where VM : ObservableObject
|
where VM : ObservableObject
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
namespace Ghost.Editor.Core.AppState;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ghost.App.Infrastructures.AppState;
|
|
||||||
|
|
||||||
internal class AppStateMachine
|
internal class AppStateMachine
|
||||||
{
|
{
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
using Ghost.App.View.Windows;
|
using Ghost.Data.Models;
|
||||||
using Ghost.Data.Models;
|
|
||||||
using Ghost.Data.Services;
|
using Ghost.Data.Services;
|
||||||
using Ghost.Editor;
|
using Ghost.Editor.Core.AssetHandle;
|
||||||
|
using Ghost.Editor.View.Windows;
|
||||||
using Ghost.Engine;
|
using Ghost.Engine;
|
||||||
using Microsoft.UI.Xaml;
|
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ghost.App.Infrastructures.AppState;
|
namespace Ghost.Editor.Core.AppState;
|
||||||
|
|
||||||
internal class EditorState : IAppState
|
internal class EditorState : IAppState
|
||||||
{
|
{
|
||||||
@@ -16,9 +13,9 @@ internal class EditorState : IAppState
|
|||||||
|
|
||||||
public Task OnExitingAsync()
|
public Task OnExitingAsync()
|
||||||
{
|
{
|
||||||
if (GhostApplication.Window == _window)
|
if (EditorApplication.Window == _window)
|
||||||
{
|
{
|
||||||
GhostApplication.Window = null;
|
EditorApplication.Window = null;
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@@ -32,13 +29,13 @@ internal class EditorState : IAppState
|
|||||||
|
|
||||||
ProjectService.CurrentProject = metadataInfo;
|
ProjectService.CurrentProject = metadataInfo;
|
||||||
|
|
||||||
_engineCore = GhostApplication.GetService<EngineCore>();
|
_engineCore = EditorApplication.GetService<EngineCore>();
|
||||||
await _engineCore.StartAsync(new Engine.Models.LaunchArgument());
|
await _engineCore.StartAsync(new Engine.Models.LaunchArgument());
|
||||||
|
|
||||||
_window = GhostApplication.GetService<EngineEditorWindow>();
|
_window = EditorApplication.GetService<EngineEditorWindow>();
|
||||||
_window.Activate();
|
_window.Activate();
|
||||||
|
|
||||||
GhostApplication.Window = _window;
|
EditorApplication.Window = _window;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnExitedAsync()
|
public async Task OnExitedAsync()
|
||||||
@@ -48,9 +45,9 @@ internal class EditorState : IAppState
|
|||||||
await _engineCore.ShutDownAsync();
|
await _engineCore.ShutDownAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GhostApplication.Window == _window)
|
if (EditorApplication.Window == _window)
|
||||||
{
|
{
|
||||||
GhostApplication.Window = null;
|
EditorApplication.Window = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_window?.Close();
|
_window?.Close();
|
||||||
@@ -59,7 +56,7 @@ internal class EditorState : IAppState
|
|||||||
|
|
||||||
public Task OnEnteredAsync(object? parameter)
|
public Task OnEnteredAsync(object? parameter)
|
||||||
{
|
{
|
||||||
EditorApplication.Activate(parameter, ((GhostApplication)(Application.Current)).Host.Services);
|
AssetDatabase.Initialize();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ghost.App.Infrastructures.AppState;
|
namespace Ghost.Editor.Core.AppState;
|
||||||
|
|
||||||
internal interface IAppState
|
internal interface IAppState
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
using Ghost.App.View.Windows;
|
using Ghost.Editor;
|
||||||
|
using Ghost.Editor.View.Windows;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ghost.App.Infrastructures.AppState;
|
namespace Ghost.Editor.Core.AppState;
|
||||||
|
|
||||||
internal class LandingState : IAppState
|
internal class LandingState : IAppState
|
||||||
{
|
{
|
||||||
@@ -9,17 +10,17 @@ internal class LandingState : IAppState
|
|||||||
|
|
||||||
public Task OnExitingAsync()
|
public Task OnExitingAsync()
|
||||||
{
|
{
|
||||||
if (GhostApplication.Window == _window)
|
if (EditorApplication.Window == _window)
|
||||||
{
|
{
|
||||||
GhostApplication.Window = null;
|
EditorApplication.Window = null;
|
||||||
}
|
}
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task OnEnteringAsync(object? parameter)
|
public Task OnEnteringAsync(object? parameter)
|
||||||
{
|
{
|
||||||
_window = GhostApplication.GetService<LandingWindow>();
|
_window = EditorApplication.GetService<LandingWindow>();
|
||||||
GhostApplication.Window = _window;
|
EditorApplication.Window = _window;
|
||||||
|
|
||||||
_window.Activate();
|
_window.Activate();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
@@ -27,9 +28,9 @@ internal class LandingState : IAppState
|
|||||||
|
|
||||||
public Task OnExitedAsync()
|
public Task OnExitedAsync()
|
||||||
{
|
{
|
||||||
if (GhostApplication.Window == _window)
|
if (EditorApplication.Window == _window)
|
||||||
{
|
{
|
||||||
GhostApplication.Window = null;
|
EditorApplication.Window = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_window?.Close();
|
_window?.Close();
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ghost.App.Infrastructures.AppState;
|
namespace Ghost.Editor.Core.AppState;
|
||||||
|
|
||||||
internal enum StateKey
|
internal enum StateKey
|
||||||
{
|
{
|
||||||
24
Ghost.App/Core/AssetHandle/Asset.cs
Normal file
24
Ghost.App/Core/AssetHandle/Asset.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace Ghost.Editor.Core.AssetHandle;
|
||||||
|
|
||||||
|
public abstract class Asset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the Guid of the asset.
|
||||||
|
/// </summary>
|
||||||
|
public Guid GUID
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
} = Guid.NewGuid();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if the asset is a folder, false if it is a file.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFolder
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void GenerateMetadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
60
Ghost.App/Core/AssetHandle/AssetDatabase.cs
Normal file
60
Ghost.App/Core/AssetHandle/AssetDatabase.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.AssetHandle;
|
||||||
|
|
||||||
|
public static class AssetDatabase
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<string, Action<string>> _assetOpenHandlers = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
static AssetDatabase()
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void Initialize()
|
||||||
|
{
|
||||||
|
RegisterAssetHandles();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RegisterAssetHandles()
|
||||||
|
{
|
||||||
|
var methods = AppDomain.CurrentDomain.GetAssemblies()
|
||||||
|
.SelectMany(a => a.GetTypes())
|
||||||
|
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
|
||||||
|
.Where(m => m.GetCustomAttribute<AssetOpenHandlerAttribute>() != null &&
|
||||||
|
m.GetParameters().Length == 1 &&
|
||||||
|
m.GetParameters()[0].ParameterType == typeof(string));
|
||||||
|
|
||||||
|
foreach (var method in methods)
|
||||||
|
{
|
||||||
|
var attr = method.GetCustomAttribute<AssetOpenHandlerAttribute>()!;
|
||||||
|
var del = (Action<string>)Delegate.CreateDelegate(typeof(Action<string>), method);
|
||||||
|
foreach (var ext in attr.Extensions)
|
||||||
|
{
|
||||||
|
if (_assetOpenHandlers.ContainsKey(ext))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Duplicate handler for extension '{ext}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
_assetOpenHandlers[ext] = del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OpenAsset(string path)
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(path);
|
||||||
|
if (_assetOpenHandlers.TryGetValue(extension, out var handler))
|
||||||
|
{
|
||||||
|
handler(path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo(path)
|
||||||
|
{
|
||||||
|
UseShellExecute = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Ghost.App/Core/AssetHandle/AssetOpenHandlerAttribute .cs
Normal file
15
Ghost.App/Core/AssetHandle/AssetOpenHandlerAttribute .cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Ghost.Editor.Core.AssetHandle;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
public class AssetOpenHandlerAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string[] Extensions
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AssetOpenHandlerAttribute(params string[] extensions)
|
||||||
|
{
|
||||||
|
Extensions = extensions.Select(e => e.StartsWith('.') ? e.ToLowerInvariant() : '.' + e.ToLowerInvariant()).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
53
Ghost.App/Core/SceneGraph/EditorWorldManager.cs
Normal file
53
Ghost.App/Core/SceneGraph/EditorWorldManager.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using Ghost.Editor.Resources;
|
||||||
|
using Ghost.Editor.Services.Contracts;
|
||||||
|
using Ghost.Engine.Resources;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.SceneGraph;
|
||||||
|
|
||||||
|
public enum OpenWorldMode
|
||||||
|
{
|
||||||
|
Single,
|
||||||
|
Additive,
|
||||||
|
AdditiveWithoutLoading
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EditorWorldManager
|
||||||
|
{
|
||||||
|
// TODO: Use guid keys instead of string paths for better performance and uniqueness
|
||||||
|
private static readonly Dictionary<string, WorldNode> _loadedWorlds = new();
|
||||||
|
public static IEnumerable<WorldNode> LoadedWorlds => _loadedWorlds.Values;
|
||||||
|
|
||||||
|
public static event Action<WorldNode>? OnWorldLoaded;
|
||||||
|
public static event Action<WorldNode>? OnWorldUnloaded;
|
||||||
|
|
||||||
|
public static async Task LoadWorld(string worldPath)
|
||||||
|
{
|
||||||
|
if (_loadedWorlds.ContainsKey(worldPath)
|
||||||
|
|| !File.Exists(worldPath)
|
||||||
|
|| Path.GetExtension(worldPath) != FileExtensions.SCENE_FILE_EXTENSION)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var progressService = EditorApplication.GetService<IProgressService>();
|
||||||
|
progressService.ShowIndeterminateProgress("Loading world...");
|
||||||
|
|
||||||
|
foreach (var world in _loadedWorlds)
|
||||||
|
{
|
||||||
|
world.Value.Unload();
|
||||||
|
OnWorldUnloaded?.Invoke(world.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var readStream = new FileStream(worldPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
var deserializedScene = await JsonSerializer.DeserializeAsync<WorldNode>(readStream, StaticResource.defaultSerializerOptions) ?? throw new Exception("Deserialization failed.");
|
||||||
|
|
||||||
|
_loadedWorlds.Clear();
|
||||||
|
|
||||||
|
_loadedWorlds[worldPath] = deserializedScene;
|
||||||
|
await deserializedScene.LoadAsync();
|
||||||
|
|
||||||
|
progressService.HideProgress();
|
||||||
|
OnWorldLoaded?.Invoke(deserializedScene);
|
||||||
|
}
|
||||||
|
}
|
||||||
70
Ghost.App/Core/SceneGraph/EntityNode.cs
Normal file
70
Ghost.App/Core/SceneGraph/EntityNode.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Resources;
|
||||||
|
using Ghost.Entities;
|
||||||
|
using Microsoft.UI.Text;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.SceneGraph;
|
||||||
|
|
||||||
|
public partial class EntityNode : SceneGraphNode
|
||||||
|
{
|
||||||
|
private readonly Entity _entity;
|
||||||
|
|
||||||
|
public Entity Entity => _entity;
|
||||||
|
public override SceneGraphNodeType NodeType => SceneGraphNodeType.Entity;
|
||||||
|
|
||||||
|
public EntityNode(Entity entity, string name)
|
||||||
|
{
|
||||||
|
_entity = entity;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal EntityNode()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class EntityNode : IInspectable
|
||||||
|
{
|
||||||
|
public IconSource? Icon => EditorIconSource.entity_24;
|
||||||
|
|
||||||
|
public UIElement? HeaderContent()
|
||||||
|
{
|
||||||
|
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}",
|
||||||
|
Margin = new Thickness(0, 5, 0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
112
Ghost.App/Core/SceneGraph/SceneGraphHelpers.cs
Normal file
112
Ghost.App/Core/SceneGraph/SceneGraphHelpers.cs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
using Ghost.Engine.Components;
|
||||||
|
using Ghost.Entities;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.SceneGraph;
|
||||||
|
|
||||||
|
public class SceneGraphHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="EntityNode"/> entity with default components.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">The world context where the entity will be created.</param>
|
||||||
|
/// <param name="entity">The entity to be wrapped in the <see cref="EntityNode"/>.</param>
|
||||||
|
public static EntityNode CreateEntityNode(World world, Entity entity, string name)
|
||||||
|
{
|
||||||
|
world.EntityManager.AddComponent(entity, LocalToWorld.Identity);
|
||||||
|
world.EntityManager.AddComponent(entity, Hierarchy.Root);
|
||||||
|
return new EntityNode(entity, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="Entity"/> and <see cref="EntityNode"/> entity with default components.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">The world context where the entity will be created.</param>
|
||||||
|
public static EntityNode CreateEntityNode(World world, string name)
|
||||||
|
{
|
||||||
|
var entity = world.EntityManager.CreateEntity();
|
||||||
|
return CreateEntityNode(world, entity, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attaches childEntity to parentEntity in the scene graph.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">The world context where the entities exist.</param>
|
||||||
|
/// <param name="parentNode">The parent entity to which the child will be attached.</param>
|
||||||
|
/// <param name="childNode">The child entity to be attached.</param>
|
||||||
|
public static void AttachChild(WorldNode scene, EntityNode parentNode, EntityNode childNode)
|
||||||
|
{
|
||||||
|
// 1) If the child already has a parent, detach it first
|
||||||
|
var childHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(childNode.Entity);
|
||||||
|
if (childHierarchy.ValueRO.parent != Entity.Invalid)
|
||||||
|
{
|
||||||
|
DetachFromParent(scene, childNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Link child to new parent
|
||||||
|
childHierarchy.ValueRW.parent = parentNode.Entity;
|
||||||
|
|
||||||
|
// 3) Insert child at the head of parent's child list
|
||||||
|
var parentHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(parentNode.Entity);
|
||||||
|
|
||||||
|
childHierarchy.ValueRW.nextSibling = parentHierarchy.ValueRO.firstChild;
|
||||||
|
parentHierarchy.ValueRW.firstChild = childNode.Entity;
|
||||||
|
|
||||||
|
// 4) Write back
|
||||||
|
scene.World.EntityManager.SetComponent(parentNode.Entity, in parentHierarchy.ValueRO);
|
||||||
|
scene.World.EntityManager.SetComponent(childNode.Entity, in childHierarchy.ValueRO);
|
||||||
|
|
||||||
|
// 5) Update children list in parent node
|
||||||
|
parentNode.AddChild(childNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Detaches the specified entity from its parent in the scene graph.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">The world context where the entities exist.</param>
|
||||||
|
/// <param name="node">The entity to detach from its parent.</param>
|
||||||
|
public static void DetachFromParent(WorldNode scene, EntityNode node)
|
||||||
|
{
|
||||||
|
var hierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(node.Entity);
|
||||||
|
var parent = hierarchy.ValueRO.parent;
|
||||||
|
if (parent == Entity.Invalid)
|
||||||
|
{
|
||||||
|
return; // already root
|
||||||
|
}
|
||||||
|
|
||||||
|
var parentHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(parent);
|
||||||
|
|
||||||
|
// If entity is the first child, simply move head
|
||||||
|
if (parentHierarchy.ValueRO.firstChild == node.Entity)
|
||||||
|
{
|
||||||
|
parentHierarchy.ValueRW.firstChild = hierarchy.ValueRO.nextSibling;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise, find the previous sibling in the linked list
|
||||||
|
var prevSibling = parentHierarchy.ValueRO.firstChild;
|
||||||
|
while (prevSibling != Entity.Invalid)
|
||||||
|
{
|
||||||
|
var prevHierarchy = scene.World.EntityManager.GetComponent<Hierarchy>(prevSibling);
|
||||||
|
if (prevHierarchy.ValueRW.nextSibling == node.Entity)
|
||||||
|
{
|
||||||
|
prevHierarchy.ValueRW.nextSibling = hierarchy.ValueRO.nextSibling;
|
||||||
|
scene.World.EntityManager.SetComponent(prevSibling, in prevHierarchy.ValueRO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevSibling = prevHierarchy.ValueRO.nextSibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear child's references
|
||||||
|
hierarchy.ValueRW.parent = Entity.Invalid;
|
||||||
|
hierarchy.ValueRW.nextSibling = Entity.Invalid;
|
||||||
|
|
||||||
|
// Write back
|
||||||
|
scene.World.EntityManager.SetComponent(parent, in parentHierarchy.ValueRO);
|
||||||
|
scene.World.EntityManager.SetComponent(node.Entity, in hierarchy.ValueRO);
|
||||||
|
|
||||||
|
// Remove from parent's children list
|
||||||
|
scene.EntityNodeLookup[parent].RemoveChild(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
Ghost.App/Core/SceneGraph/SceneGraphNode.cs
Normal file
54
Ghost.App/Core/SceneGraph/SceneGraphNode.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.SceneGraph;
|
||||||
|
|
||||||
|
public enum SceneGraphNodeType
|
||||||
|
{
|
||||||
|
Scene,
|
||||||
|
Entity,
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract partial class SceneGraphNode : ObservableObject
|
||||||
|
{
|
||||||
|
public ObservableCollection<SceneGraphNode>? Children
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract SceneGraphNodeType NodeType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ChildCount => Children?.Count ?? 0;
|
||||||
|
|
||||||
|
public virtual void AddChild(SceneGraphNode child)
|
||||||
|
{
|
||||||
|
Children ??= new();
|
||||||
|
Children.Add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool RemoveChild(SceneGraphNode child)
|
||||||
|
{
|
||||||
|
return Children?.Remove(child) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SceneGraphNode GetChild(int index)
|
||||||
|
{
|
||||||
|
if (Children == null || index < 0 || index >= Children.Count)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(index), "Index is out of range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Children[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
195
Ghost.App/Core/SceneGraph/WorldNode.cs
Normal file
195
Ghost.App/Core/SceneGraph/WorldNode.cs
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Core.AssetHandle;
|
||||||
|
using Ghost.Editor.Core.Serializer;
|
||||||
|
using Ghost.Editor.Resources;
|
||||||
|
using Ghost.Engine.Components;
|
||||||
|
using Ghost.Entities;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.SceneGraph;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(WorldNodeSerializer))]
|
||||||
|
public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
|
||||||
|
{
|
||||||
|
private World _world;
|
||||||
|
private Dictionary<Entity, EntityNode> _entityNodeLookup = new();
|
||||||
|
|
||||||
|
public World World => _world;
|
||||||
|
public Dictionary<Entity, EntityNode> EntityNodeLookup => _entityNodeLookup;
|
||||||
|
|
||||||
|
public override SceneGraphNodeType NodeType => SceneGraphNodeType.Scene;
|
||||||
|
|
||||||
|
public WorldNode(World world, string name)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal WorldNode()
|
||||||
|
{
|
||||||
|
_world = World.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLookup(Entity key, EntityNode value)
|
||||||
|
{
|
||||||
|
_entityNodeLookup[key] = value;
|
||||||
|
if (value.Children == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var child in value.Children)
|
||||||
|
{
|
||||||
|
if (child is EntityNode entityChild)
|
||||||
|
{
|
||||||
|
UpdateLookup(entityChild.Entity, entityChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddChild(SceneGraphNode child)
|
||||||
|
{
|
||||||
|
if (child is not EntityNode entityNode)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Child must be of type EntityNode.", nameof(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
base.AddChild(entityNode);
|
||||||
|
UpdateLookup(entityNode.Entity, entityNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool RemoveChild(SceneGraphNode child)
|
||||||
|
{
|
||||||
|
if (child is not EntityNode entityNode)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Child must be of type EntityNode.", nameof(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = base.RemoveChild(child);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
_entityNodeLookup.Remove(entityNode.Entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityNode BuildNodeRecursive(Entity entity, World world)
|
||||||
|
{
|
||||||
|
if (!_entityNodeLookup.TryGetValue(entity, out var node))
|
||||||
|
{
|
||||||
|
node = new EntityNode(entity, "New Entity");
|
||||||
|
_entityNodeLookup[entity] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hc = world.EntityManager.GetComponent<Hierarchy>(entity);
|
||||||
|
var child = hc.ValueRO.firstChild;
|
||||||
|
|
||||||
|
while (child != Entity.Invalid)
|
||||||
|
{
|
||||||
|
node.AddChild(BuildNodeRecursive(child, world));
|
||||||
|
var childHC = world.EntityManager.GetComponent<Hierarchy>(child);
|
||||||
|
child = childHC.ValueRO.nextSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildGraph()
|
||||||
|
{
|
||||||
|
foreach (var (entity, hierarchy) in _world.Query<Hierarchy>())
|
||||||
|
{
|
||||||
|
if (hierarchy.ValueRO.parent == Entity.Invalid)
|
||||||
|
{
|
||||||
|
var node = BuildNodeRecursive(entity, _world);
|
||||||
|
AddChild(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task LoadAsync()
|
||||||
|
{
|
||||||
|
return Task.Run(BuildGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Unload()
|
||||||
|
{
|
||||||
|
_world.Dispose();
|
||||||
|
_world = null!;
|
||||||
|
|
||||||
|
Children?.Clear();
|
||||||
|
_entityNodeLookup.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"WorldNode: {Name} (World ID: {_world.ID})";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(_world, Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is WorldNode other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(WorldNode? other)
|
||||||
|
{
|
||||||
|
if (other is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(this, other))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _world.Equals(other._world) && Name == other.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(WorldNode? left, WorldNode? right)
|
||||||
|
{
|
||||||
|
if (left is null)
|
||||||
|
{
|
||||||
|
return right is null;
|
||||||
|
}
|
||||||
|
return left.Equals(right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(WorldNode? left, WorldNode? right)
|
||||||
|
{
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class WorldNode : IInspectable
|
||||||
|
{
|
||||||
|
public IconSource? Icon => EditorIconSource.scene_24;
|
||||||
|
|
||||||
|
[AssetOpenHandler(FileExtensions.SCENE_FILE_EXTENSION)]
|
||||||
|
public static async void Open(string path)
|
||||||
|
{
|
||||||
|
await EditorWorldManager.LoadWorld(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIElement? HeaderContent()
|
||||||
|
{
|
||||||
|
return new TextBlock
|
||||||
|
{
|
||||||
|
Text = Name,
|
||||||
|
Style = Application.Current.Resources["SubtitleTextBlockStyle"] as Style,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIElement? InspectorContent()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
131
Ghost.App/Core/Serializer/WorldNodeSerializer.cs
Normal file
131
Ghost.App/Core/Serializer/WorldNodeSerializer.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using Ghost.Editor.Core.SceneGraph;
|
||||||
|
using Ghost.Engine.Utilities;
|
||||||
|
using Ghost.Entities;
|
||||||
|
using Ghost.Entities.Components;
|
||||||
|
using Ghost.Entities.Utilities;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Core.Serializer;
|
||||||
|
|
||||||
|
internal class WorldNodeSerializer : JsonConverter<WorldNode>
|
||||||
|
{
|
||||||
|
private static class Property
|
||||||
|
{
|
||||||
|
public const string NAME = "Name";
|
||||||
|
public const string ENTITIES = "Entities";
|
||||||
|
public const string ID = "ID";
|
||||||
|
public const string ENTITY_ID = "EntityID";
|
||||||
|
public const string COMPONENTS = "Components";
|
||||||
|
public const string DATA = "Data";
|
||||||
|
public const string SYSTEMS = "Systems";
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type typeToConvert)
|
||||||
|
{
|
||||||
|
return typeToConvert == typeof(WorldNode) || typeToConvert.IsSubclassOf(typeof(WorldNode));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override WorldNode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var element = JsonDocument.ParseValue(ref reader).RootElement;
|
||||||
|
var name = element.GetProperty(Property.NAME).GetString() ?? "New World";
|
||||||
|
|
||||||
|
var world = World.Create();
|
||||||
|
var result = new WorldNode(world, name);
|
||||||
|
|
||||||
|
foreach (var entityElement in element.GetProperty(Property.ENTITIES).EnumerateArray())
|
||||||
|
{
|
||||||
|
var entityName = entityElement.GetProperty(Property.NAME).GetString() ?? "New Entity";
|
||||||
|
var entityID = entityElement.GetProperty(Property.ID).GetInt32();
|
||||||
|
var entity = new Entity(entityID, 0);
|
||||||
|
var node = new EntityNode(entity, entityName);
|
||||||
|
|
||||||
|
world.EntityManager.AddEntityInternal(entity);
|
||||||
|
result.EntityNodeLookup[entity] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var componentElement in element.GetProperty(Property.COMPONENTS).EnumerateObject())
|
||||||
|
{
|
||||||
|
var typeName = componentElement.Name;
|
||||||
|
var type = Type.GetType(typeName) ?? throw new Exception($"Type {typeName} not found.");
|
||||||
|
|
||||||
|
foreach (var dataElement in componentElement.Value.EnumerateArray())
|
||||||
|
{
|
||||||
|
var entityID = dataElement.GetProperty(Property.ENTITY_ID).GetInt32();
|
||||||
|
var entity = new Entity(entityID, 0);
|
||||||
|
|
||||||
|
var dataProperty = dataElement.GetProperty(Property.DATA);
|
||||||
|
var component = JsonSerializer.Deserialize(dataProperty.GetRawText(), type, options);
|
||||||
|
if (component is IComponentData data)
|
||||||
|
{
|
||||||
|
world.EntityManager.AddComponent(entity, data, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var systemElement in element.GetProperty(Property.SYSTEMS).EnumerateArray())
|
||||||
|
{
|
||||||
|
var typeString = systemElement.GetString();
|
||||||
|
if (string.IsNullOrEmpty(typeString))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var systemType = Type.GetType(typeString);
|
||||||
|
if (systemType == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.SystemStorage.AddSystem(systemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, WorldNode value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteObject(() =>
|
||||||
|
{
|
||||||
|
writer.WriteString(Property.NAME, value.Name);
|
||||||
|
writer.WriteArray(Property.ENTITIES, value.World.EntityManager.Entities, entity =>
|
||||||
|
{
|
||||||
|
if (!entity.IsValid)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteObject(() =>
|
||||||
|
{
|
||||||
|
writer.WriteString(Property.NAME, value.EntityNodeLookup[entity].Name);
|
||||||
|
writer.WriteNumber(Property.ID, entity.ID);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
writer.WriteObject(Property.COMPONENTS, () =>
|
||||||
|
{
|
||||||
|
foreach (var kvp in value.World.ComponentStorage.ComponentPools)
|
||||||
|
{
|
||||||
|
var type = TypeHandle.ToType(kvp.Key) ?? throw new Exception($"Type {kvp.Key} not found.");
|
||||||
|
var typeName = type.AssemblyQualifiedName ?? type.Name;
|
||||||
|
|
||||||
|
writer.WriteArray(typeName, kvp.Value.Enumerate(), data =>
|
||||||
|
{
|
||||||
|
writer.WriteObject(() =>
|
||||||
|
{
|
||||||
|
writer.WriteNumber(Property.ENTITY_ID, data.entity.ID);
|
||||||
|
writer.WritePropertyName(Property.DATA);
|
||||||
|
JsonSerializer.Serialize(writer, data.component, type, options);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
writer.WriteArray(Property.SYSTEMS, value.World.SystemStorage.Systems, systemType =>
|
||||||
|
{
|
||||||
|
writer.WriteStringValue(systemType.AssemblyQualifiedName ?? systemType.Name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||||
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||||
<RootNamespace>Ghost.App</RootNamespace>
|
|
||||||
<Platforms>x86;x64;ARM64</Platforms>
|
<Platforms>x86;x64;ARM64</Platforms>
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||||
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
|
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
|
||||||
@@ -42,10 +41,11 @@
|
|||||||
<None Remove="Assets\Icon.targetsize-48_altform-unplated.png" />
|
<None Remove="Assets\Icon.targetsize-48_altform-unplated.png" />
|
||||||
<None Remove="Controls\BasicInput\PropertyField.xaml" />
|
<None Remove="Controls\BasicInput\PropertyField.xaml" />
|
||||||
<None Remove="Controls\EditorControls.xaml" />
|
<None Remove="Controls\EditorControls.xaml" />
|
||||||
<None Remove="Controls\Internal\InspectorView.xaml" />
|
|
||||||
<None Remove="Controls\Internal\InternalControls.xaml" />
|
<None Remove="Controls\Internal\InternalControls.xaml" />
|
||||||
|
<None Remove="Controls\Internal\NavigationTabView.xaml" />
|
||||||
<None Remove="View\Pages\EngineEditor\ConsolePage.xaml" />
|
<None Remove="View\Pages\EngineEditor\ConsolePage.xaml" />
|
||||||
<None Remove="View\Pages\EngineEditor\HierarchyPage.xaml" />
|
<None Remove="View\Pages\EngineEditor\HierarchyPage.xaml" />
|
||||||
|
<None Remove="View\Pages\EngineEditor\InspectorPage.xaml" />
|
||||||
<None Remove="View\Pages\EngineEditor\ProjectPage.xaml" />
|
<None Remove="View\Pages\EngineEditor\ProjectPage.xaml" />
|
||||||
<None Remove="View\Pages\Landing\CreateProjectPage.xaml" />
|
<None Remove="View\Pages\Landing\CreateProjectPage.xaml" />
|
||||||
<None Remove="View\Pages\Landing\OpenProjectPage.xaml" />
|
<None Remove="View\Pages\Landing\OpenProjectPage.xaml" />
|
||||||
@@ -89,7 +89,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ghost.Data\Ghost.Data.csproj" />
|
<ProjectReference Include="..\Ghost.Data\Ghost.Data.csproj" />
|
||||||
<ProjectReference Include="..\Ghost.Editor\Ghost.Editor.csproj" />
|
|
||||||
<ProjectReference Include="..\Ghost.Engine\Ghost.Engine.csproj" />
|
<ProjectReference Include="..\Ghost.Engine\Ghost.Engine.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -107,14 +106,16 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Resources\" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Misaki.HighPerformance.Unsafe">
|
<Reference Include="Misaki.HighPerformance.Unsafe">
|
||||||
<HintPath>..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.Unsafe\bin\Release\net9.0\Misaki.HighPerformance.Unsafe.dll</HintPath>
|
<HintPath>..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.Unsafe\bin\Release\net9.0\Misaki.HighPerformance.Unsafe.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="View\Pages\EngineEditor\InspectorPage.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="View\Pages\EngineEditor\HierarchyPage.xaml">
|
<Page Update="View\Pages\EngineEditor\HierarchyPage.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -140,11 +141,6 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Page Update="Controls\Internal\InspectorView.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="View\Windows\EngineEditorWindow.xaml">
|
<Page Update="View\Windows\EngineEditorWindow.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -160,6 +156,14 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Controls\Layout\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="Controls\Internal\NavigationTabView.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals" />
|
<PropertyGroup Label="Globals" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
@@ -181,5 +185,7 @@
|
|||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<PublishAot>False</PublishAot>
|
<PublishAot>False</PublishAot>
|
||||||
<PublishTrimmed>False</PublishTrimmed>
|
<PublishTrimmed>False</PublishTrimmed>
|
||||||
|
<RootNamespace>Ghost.Editor</RootNamespace>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ghost.App.Models;
|
namespace Ghost.Editor.Models;
|
||||||
|
|
||||||
internal struct AssetItem()
|
internal struct AssetItem()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace Ghost.App.Models;
|
namespace Ghost.Editor.Models;
|
||||||
|
|
||||||
internal class ExplorerItem(string name, string path, bool isDirectory)
|
internal class ExplorerItem(string name, string path, bool isDirectory)
|
||||||
{
|
{
|
||||||
|
|||||||
9
Ghost.App/Models/MessageType.cs
Normal file
9
Ghost.App/Models/MessageType.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ghost.Editor.Models;
|
||||||
|
|
||||||
|
public enum MessageType
|
||||||
|
{
|
||||||
|
Informational,
|
||||||
|
Success,
|
||||||
|
Warning,
|
||||||
|
Error
|
||||||
|
}
|
||||||
18
Ghost.App/Resources/EditorIconSource.cs
Normal file
18
Ghost.App/Resources/EditorIconSource.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Resources;
|
||||||
|
|
||||||
|
public static class EditorIconSource
|
||||||
|
{
|
||||||
|
public static readonly IconSource scene_24 = new FontIconSource
|
||||||
|
{
|
||||||
|
Glyph = "\uF159",
|
||||||
|
FontSize = 24
|
||||||
|
};
|
||||||
|
|
||||||
|
public static readonly IconSource entity_24 = new FontIconSource
|
||||||
|
{
|
||||||
|
Glyph = "\uF158",
|
||||||
|
FontSize = 24
|
||||||
|
};
|
||||||
|
}
|
||||||
11
Ghost.App/Resources/FileExtensions.cs
Normal file
11
Ghost.App/Resources/FileExtensions.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Ghost.Editor.Resources;
|
||||||
|
|
||||||
|
internal static class FileExtensions
|
||||||
|
{
|
||||||
|
public const string PROJECT_FILE_EXTENSION = ".ghostproj";
|
||||||
|
public const string TEMPLATE_FILE_EXTENSION = ".ghosttemplate";
|
||||||
|
public const string SCENE_FILE_EXTENSION = ".ghostscene";
|
||||||
|
public const string ASSET_FILE_EXTENSION = ".ghostasset";
|
||||||
|
public const string SHADER_FILE_EXTENSION = ".ghostshader";
|
||||||
|
public const string MATERIAL_FILE_EXTENSION = ".ghostmaterial";
|
||||||
|
}
|
||||||
14
Ghost.App/Services/Contracts/IInspectorService.cs
Normal file
14
Ghost.App/Services/Contracts/IInspectorService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Services.Contracts;
|
||||||
|
|
||||||
|
internal interface IInspectorService
|
||||||
|
{
|
||||||
|
public IInspectable? SelectedInspectable
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action? OnSelectionChanged;
|
||||||
|
}
|
||||||
8
Ghost.App/Services/Contracts/INotificationService.cs
Normal file
8
Ghost.App/Services/Contracts/INotificationService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using Ghost.Editor.Models;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Services.Contracts;
|
||||||
|
|
||||||
|
public interface INotificationService
|
||||||
|
{
|
||||||
|
public void ShowNotification(string? message, MessageType type, int duration = 5, string? title = null);
|
||||||
|
}
|
||||||
9
Ghost.App/Services/Contracts/IProgressService.cs
Normal file
9
Ghost.App/Services/Contracts/IProgressService.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ghost.Editor.Services.Contracts;
|
||||||
|
|
||||||
|
public interface IProgressService
|
||||||
|
{
|
||||||
|
public void ShowProgress(string message, double progress = 0.0);
|
||||||
|
public void ShowIndeterminateProgress(string message);
|
||||||
|
public void SetProgress(double progress);
|
||||||
|
public void HideProgress();
|
||||||
|
}
|
||||||
22
Ghost.App/Services/InspectorService.cs
Normal file
22
Ghost.App/Services/InspectorService.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Services.Contracts;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.Services;
|
||||||
|
|
||||||
|
public class InspectorService : IInspectorService
|
||||||
|
{
|
||||||
|
public IInspectable? SelectedInspectable
|
||||||
|
{
|
||||||
|
get => field;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (field != value)
|
||||||
|
{
|
||||||
|
field = value;
|
||||||
|
OnSelectionChanged?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action? OnSelectionChanged;
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ using Ghost.Editor.Services.Contracts;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ghost.App.Services;
|
namespace Ghost.Editor.Services;
|
||||||
|
|
||||||
public class NotificationService : INotificationService
|
public class NotificationService : INotificationService
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ghost.App.Services;
|
namespace Ghost.Editor.Services;
|
||||||
|
|
||||||
public class ProgressService : IProgressService
|
public class ProgressService : IProgressService
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<ResourceDictionary
|
<ResourceDictionary
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="using:Microsoft.UI.Xaml.Controls">
|
xmlns:controls="using:Microsoft.UI.Xaml.Controls"
|
||||||
|
xmlns:internal="using:Ghost.Editor.Controls.Internal">
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
<StaticResource x:Key="TabViewItemHeaderBackgroundSelected" ResourceKey="ControlFillColorSecondaryBrush" />
|
<StaticResource x:Key="TabViewItemHeaderBackgroundSelected" ResourceKey="ControlFillColorSecondaryBrush" />
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
<StaticResource x:Key="TabViewItemHeaderBackgroundSelected" ResourceKey="ControlFillColorSecondaryBrush" />
|
<StaticResource x:Key="TabViewItemHeaderBackgroundSelected" ResourceKey="ControlFillColorSecondaryBrush" />
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
<Style TargetType="TabView">
|
<Style TargetType="internal:NavigationTabView">
|
||||||
<Setter Property="TabWidthMode" Value="Compact" />
|
<Setter Property="TabWidthMode" Value="Compact" />
|
||||||
</Style>
|
</Style>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Ghost.App.Utilities;
|
namespace Ghost.Editor.Utilities;
|
||||||
|
|
||||||
public static class ComponentTypeCache
|
public static class ComponentTypeCache
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Ghost.App.View.Pages.EngineEditor;
|
using Ghost.Data.Services;
|
||||||
using Ghost.App.View.Pages.Landing;
|
using Ghost.Editor.View.Pages.EngineEditor;
|
||||||
using Ghost.App.View.Windows;
|
using Ghost.Editor.View.Pages.Landing;
|
||||||
using Ghost.Data.Services;
|
using Ghost.Editor.View.Windows;
|
||||||
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
using Ghost.Editor.ViewModels.Pages.Landing;
|
using Ghost.Editor.ViewModels.Pages.Landing;
|
||||||
using Ghost.Editor.ViewModels.Windows;
|
using Ghost.Editor.ViewModels.Windows;
|
||||||
@@ -9,7 +9,7 @@ using Ghost.Engine;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
namespace Ghost.App.Utilities;
|
namespace Ghost.Editor.Utilities;
|
||||||
|
|
||||||
internal static partial class HostHelper
|
internal static partial class HostHelper
|
||||||
{
|
{
|
||||||
@@ -41,5 +41,8 @@ internal static partial class HostHelper
|
|||||||
|
|
||||||
services.AddTransient<ConsolePage>();
|
services.AddTransient<ConsolePage>();
|
||||||
services.AddTransient<ConsoleViewModel>();
|
services.AddTransient<ConsoleViewModel>();
|
||||||
|
|
||||||
|
services.AddTransient<InspectorPage>();
|
||||||
|
services.AddTransient<InspectorViewModel>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
using System;
|
using Ghost.Editor;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.Storage.Pickers;
|
using Windows.Storage.Pickers;
|
||||||
using WinRT.Interop;
|
using WinRT.Interop;
|
||||||
|
|
||||||
namespace Ghost.App.Utilities;
|
namespace Ghost.Editor.Utilities;
|
||||||
|
|
||||||
public static class SystemUtilities
|
public static class SystemUtilities
|
||||||
{
|
{
|
||||||
public static async Task<StorageFolder?> OpenFolderPickerAsync(PickerLocationId startLocation = PickerLocationId.DocumentsLibrary, string settingsIdentifier = "")
|
public static async Task<StorageFolder?> OpenFolderPickerAsync(PickerLocationId startLocation = PickerLocationId.DocumentsLibrary, string settingsIdentifier = "")
|
||||||
{
|
{
|
||||||
var openPicker = new FolderPicker();
|
var openPicker = new FolderPicker();
|
||||||
var hWnd = WindowNative.GetWindowHandle(GhostApplication.Window);
|
var hWnd = WindowNative.GetWindowHandle(EditorApplication.Window);
|
||||||
InitializeWithWindow.Initialize(openPicker, hWnd);
|
InitializeWithWindow.Initialize(openPicker, hWnd);
|
||||||
|
|
||||||
openPicker.SuggestedStartLocation = startLocation;
|
openPicker.SuggestedStartLocation = startLocation;
|
||||||
@@ -26,7 +27,7 @@ public static class SystemUtilities
|
|||||||
public static async Task<StorageFile?> OpenFilePickerAsync(PickerLocationId startLocation = PickerLocationId.DocumentsLibrary, string settingsIdentifier = "", params IEnumerable<string> filter)
|
public static async Task<StorageFile?> OpenFilePickerAsync(PickerLocationId startLocation = PickerLocationId.DocumentsLibrary, string settingsIdentifier = "", params IEnumerable<string> filter)
|
||||||
{
|
{
|
||||||
var openPicker = new FileOpenPicker();
|
var openPicker = new FileOpenPicker();
|
||||||
var hWnd = WindowNative.GetWindowHandle(GhostApplication.Window);
|
var hWnd = WindowNative.GetWindowHandle(EditorApplication.Window);
|
||||||
InitializeWithWindow.Initialize(openPicker, hWnd);
|
InitializeWithWindow.Initialize(openPicker, hWnd);
|
||||||
|
|
||||||
openPicker.SuggestedStartLocation = startLocation;
|
openPicker.SuggestedStartLocation = startLocation;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Page
|
<Page
|
||||||
x:Class="Ghost.App.View.Pages.EngineEditor.ConsolePage"
|
x:Class="Ghost.Editor.View.Pages.EngineEditor.ConsolePage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="using:Ghost.App.View.Pages.EngineEditor"
|
xmlns:local="using:Ghost.Editor.View.Pages.EngineEditor"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
@@ -17,9 +17,10 @@
|
|||||||
<!-- Toolbar -->
|
<!-- Toolbar -->
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
|
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||||
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
|
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
|
||||||
BorderThickness="0,0,0,1">
|
BorderThickness="0,0,0,1">
|
||||||
<CommandBar Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}" DefaultLabelPosition="Collapsed">
|
<CommandBar DefaultLabelPosition="Collapsed">
|
||||||
<CommandBar.PrimaryCommands>
|
<CommandBar.PrimaryCommands>
|
||||||
<AppBarButton Command="{x:Bind ViewModel.ClearLogsCommand}" Content="Clear" />
|
<AppBarButton Command="{x:Bind ViewModel.ClearLogsCommand}" Content="Clear" />
|
||||||
<AppBarSeparator />
|
<AppBarSeparator />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
namespace Ghost.App.View.Pages.EngineEditor;
|
namespace Ghost.Editor.View.Pages.EngineEditor;
|
||||||
|
|
||||||
internal sealed partial class ConsolePage : Page
|
internal sealed partial class ConsolePage : Page
|
||||||
{
|
{
|
||||||
@@ -12,8 +12,8 @@ internal sealed partial class ConsolePage : Page
|
|||||||
|
|
||||||
public ConsolePage()
|
public ConsolePage()
|
||||||
{
|
{
|
||||||
ViewModel = GhostApplication.GetService<ConsoleViewModel>();
|
ViewModel = EditorApplication.GetService<ConsoleViewModel>();
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Page
|
<internal:NavigationTabPage
|
||||||
x:Class="Ghost.App.View.Pages.EngineEditor.HierarchyPage"
|
x:Class="Ghost.Editor.View.Pages.EngineEditor.HierarchyPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="using:Ghost.App.View.Pages.EngineEditor"
|
xmlns:internal="using:Ghost.Editor.Controls.Internal"
|
||||||
|
xmlns:local="using:Ghost.Editor.View.Pages.EngineEditor"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:sg="using:Ghost.Editor.SceneGraph"
|
xmlns:sg="using:Ghost.Editor.Core.SceneGraph"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<Page.Resources>
|
<internal:NavigationTabPage.Resources>
|
||||||
<DataTemplate x:Key="SceneTemplate" x:DataType="sg:SceneGraphNode">
|
<DataTemplate x:Key="SceneTemplate" x:DataType="sg:SceneGraphNode">
|
||||||
<TreeViewItem
|
<TreeViewItem
|
||||||
AutomationProperties.Name="{x:Bind Name}"
|
AutomationProperties.Name="{x:Bind Name}"
|
||||||
@@ -25,19 +26,19 @@
|
|||||||
|
|
||||||
<DataTemplate x:Key="EntityTemplate" x:DataType="sg:SceneGraphNode">
|
<DataTemplate x:Key="EntityTemplate" x:DataType="sg:SceneGraphNode">
|
||||||
<TreeViewItem AutomationProperties.Name="{x:Bind Name}" ItemsSource="{x:Bind Children}">
|
<TreeViewItem AutomationProperties.Name="{x:Bind Name}" ItemsSource="{x:Bind Children}">
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel Margin="10,0" Orientation="Horizontal">
|
||||||
<FontIcon FontSize="14" Glyph="" />
|
<FontIcon FontSize="14" Glyph="" />
|
||||||
<TextBlock Margin="10,0" Text="{x:Bind Name}" />
|
<TextBlock Margin="5,0,0,0" Text="{x:Bind Name}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TreeViewItem>
|
</TreeViewItem>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</Page.Resources>
|
</internal:NavigationTabPage.Resources>
|
||||||
|
|
||||||
<Grid Padding="4,6" Background="{ThemeResource LayerFillColorDefaultBrush}">
|
<Grid Padding="4,6" Background="{ThemeResource LayerFillColorDefaultBrush}">
|
||||||
<TreeView ItemsSource="{x:Bind ViewModel.SceneList}">
|
<TreeView ItemsSource="{x:Bind ViewModel.SceneList}" SelectionChanged="TreeView_SelectionChanged">
|
||||||
<TreeView.ItemTemplateSelector>
|
<TreeView.ItemTemplateSelector>
|
||||||
<local:HierarchyTemplateSector EntityTemplate="{StaticResource EntityTemplate}" WorldTemplate="{StaticResource SceneTemplate}" />
|
<local:HierarchyTemplateSector EntityTemplate="{StaticResource EntityTemplate}" WorldTemplate="{StaticResource SceneTemplate}" />
|
||||||
</TreeView.ItemTemplateSelector>
|
</TreeView.ItemTemplateSelector>
|
||||||
</TreeView>
|
</TreeView>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</internal:NavigationTabPage>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
using Ghost.Editor.SceneGraph;
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Controls.Internal;
|
||||||
|
using Ghost.Editor.Core.SceneGraph;
|
||||||
|
using Ghost.Editor.Services.Contracts;
|
||||||
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
namespace Ghost.Editor.View.Pages.EngineEditor;
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
|
||||||
|
|
||||||
namespace Ghost.App.View.Pages.EngineEditor;
|
internal sealed partial class HierarchyPage : NavigationTabPage
|
||||||
/// <summary>
|
|
||||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
|
||||||
/// </summary>
|
|
||||||
internal sealed partial class HierarchyPage : Page
|
|
||||||
{
|
{
|
||||||
|
private readonly IInspectorService _inspectorService;
|
||||||
|
|
||||||
public HierarchyViewModel ViewModel
|
public HierarchyViewModel ViewModel
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
@@ -19,9 +19,38 @@ internal sealed partial class HierarchyPage : Page
|
|||||||
|
|
||||||
public HierarchyPage()
|
public HierarchyPage()
|
||||||
{
|
{
|
||||||
ViewModel = GhostApplication.GetService<HierarchyViewModel>();
|
_inspectorService = EditorApplication.GetService<IInspectorService>();
|
||||||
|
ViewModel = EditorApplication.GetService<HierarchyViewModel>();
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
Header = "Hierarchy";
|
||||||
|
IconSource = new FontIconSource
|
||||||
|
{
|
||||||
|
Glyph = "\uE8A4"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNavigatedTo(object? parameter)
|
||||||
|
{
|
||||||
|
ViewModel.OnNavigatedTo(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNavigatedFrom()
|
||||||
|
{
|
||||||
|
ViewModel.OnNavigatedFrom();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TreeView_SelectionChanged(TreeView sender, TreeViewSelectionChangedEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.AddedItems.Count > 0 && args.AddedItems[0] is IInspectable inspectable)
|
||||||
|
{
|
||||||
|
_inspectorService.SelectedInspectable = inspectable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_inspectorService.SelectedInspectable = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
Ghost.App/View/Pages/EngineEditor/InspectorPage.xaml
Normal file
45
Ghost.App/View/Pages/EngineEditor/InspectorPage.xaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<internal:NavigationTabPage
|
||||||
|
x:Class="Ghost.Editor.View.Pages.EngineEditor.InspectorPage"
|
||||||
|
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:internal="using:Ghost.Editor.Controls.Internal"
|
||||||
|
xmlns:local="using:Ghost.Editor.View.Pages.EngineEditor"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Grid Background="{ThemeResource LayerFillColorDefaultBrush}">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="75" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<Grid
|
||||||
|
Grid.Row="0"
|
||||||
|
Padding="15,0,10,0"
|
||||||
|
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||||
|
BorderBrush="{ThemeResource CardStrokeColorDefaultSolid}"
|
||||||
|
BorderThickness="0,0,0,1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<IconSourceElement
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="0,0,15,0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IconSource="{x:Bind ViewModel.Inspectable.Icon, Mode=OneWay}" />
|
||||||
|
<ContentPresenter Grid.Column="1" Content="{x:Bind ViewModel.Inspectable.HeaderContent(), Mode=OneWay}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<Grid Grid.Row="1" Padding="10,0,10,0">
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||||
|
<ContentPresenter Content="{x:Bind ViewModel.Inspectable.InspectorContent(), Mode=OneWay}" />
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</internal:NavigationTabPage>
|
||||||
36
Ghost.App/View/Pages/EngineEditor/InspectorPage.xaml.cs
Normal file
36
Ghost.App/View/Pages/EngineEditor/InspectorPage.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Ghost.Editor.Controls.Internal;
|
||||||
|
using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.View.Pages.EngineEditor;
|
||||||
|
|
||||||
|
internal sealed partial class InspectorPage : NavigationTabPage
|
||||||
|
{
|
||||||
|
public InspectorViewModel ViewModel
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InspectorPage()
|
||||||
|
{
|
||||||
|
ViewModel = EditorApplication.GetService<InspectorViewModel>();
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Header = "Inspector";
|
||||||
|
IconSource = new FontIconSource
|
||||||
|
{
|
||||||
|
Glyph = "\uEC7A"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNavigatedTo(object? parameter)
|
||||||
|
{
|
||||||
|
ViewModel.OnNavigatedTo(parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnNavigatedFrom()
|
||||||
|
{
|
||||||
|
ViewModel.OnNavigatedFrom();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Page
|
<Page
|
||||||
x:Class="Ghost.App.View.Pages.EngineEditor.ProjectPage"
|
x:Class="Ghost.Editor.View.Pages.EngineEditor.ProjectPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:converter="using:Ghost.Editor.Utilities.Converters"
|
xmlns:converter="using:Ghost.Editor.Utilities.Converters"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="using:Ghost.App.View.Pages.EngineEditor"
|
xmlns:local="using:Ghost.Editor.View.Pages.EngineEditor"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:model="using:Ghost.App.Models"
|
xmlns:model="using:Ghost.Editor.Models"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Ghost.Editor.ViewModels.Pages.EngineEditor;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Input;
|
using Microsoft.UI.Xaml.Input;
|
||||||
|
|
||||||
namespace Ghost.App.View.Pages.EngineEditor;
|
namespace Ghost.Editor.View.Pages.EngineEditor;
|
||||||
|
|
||||||
internal sealed partial class ProjectPage : Page
|
internal sealed partial class ProjectPage : Page
|
||||||
{
|
{
|
||||||
@@ -13,13 +13,13 @@ internal sealed partial class ProjectPage : Page
|
|||||||
|
|
||||||
public ProjectPage()
|
public ProjectPage()
|
||||||
{
|
{
|
||||||
ViewModel = GhostApplication.GetService<ProjectViewModel>();
|
ViewModel = EditorApplication.GetService<ProjectViewModel>();
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void GridViewItem_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
|
private void GridViewItem_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
|
||||||
{
|
{
|
||||||
await ViewModel.OpenSelected();
|
ViewModel.OpenSelected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Page
|
<Page
|
||||||
x:Class="Ghost.App.View.Pages.Landing.CreateProjectPage"
|
x:Class="Ghost.Editor.View.Pages.Landing.CreateProjectPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:data="using:Ghost.Data.Models"
|
xmlns:data="using:Ghost.Data.Models"
|
||||||
xmlns:editor="using:Ghost.Editor.Controls"
|
xmlns:editor="using:Ghost.Editor.Controls"
|
||||||
xmlns:local="using:Ghost.App.View.Pages.Landing"
|
xmlns:local="using:Ghost.Editor.View.Pages.Landing"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
NavigationCacheMode="Enabled"
|
NavigationCacheMode="Enabled"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
|
|
||||||
namespace Ghost.App.View.Pages.Landing;
|
namespace Ghost.Editor.View.Pages.Landing;
|
||||||
|
|
||||||
internal sealed partial class CreateProjectPage : Page
|
internal sealed partial class CreateProjectPage : Page
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ internal sealed partial class CreateProjectPage : Page
|
|||||||
|
|
||||||
public CreateProjectPage()
|
public CreateProjectPage()
|
||||||
{
|
{
|
||||||
ViewModel = GhostApplication.GetService<CreateProjectViewModel>();
|
ViewModel = EditorApplication.GetService<CreateProjectViewModel>();
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<Page
|
<Page
|
||||||
x:Class="Ghost.App.View.Pages.Landing.OpenProjectPage"
|
x:Class="Ghost.Editor.View.Pages.Landing.OpenProjectPage"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:converters="using:Ghost.Editor.Utilities.Converters"
|
xmlns:converters="using:Ghost.Editor.Utilities.Converters"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:data="using:Ghost.Data.Models"
|
xmlns:data="using:Ghost.Data.Models"
|
||||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:local="using:Ghost.App.View.Pages.Landing"
|
xmlns:local="using:Ghost.Editor.View.Pages.Landing"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
NavigationCacheMode="Enabled"
|
NavigationCacheMode="Enabled"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using Ghost.Data.Models;
|
using Ghost.Editor.ViewModels.Pages.Landing;
|
||||||
using Ghost.Editor.ViewModels.Pages.Landing;
|
using Ghost.Data.Models;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
|
|
||||||
namespace Ghost.App.View.Pages.Landing;
|
namespace Ghost.Editor.View.Pages.Landing;
|
||||||
|
|
||||||
internal sealed partial class OpenProjectPage : Page
|
internal sealed partial class OpenProjectPage : Page
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ internal sealed partial class OpenProjectPage : Page
|
|||||||
|
|
||||||
public OpenProjectPage()
|
public OpenProjectPage()
|
||||||
{
|
{
|
||||||
ViewModel = GhostApplication.GetService<OpenProjectViewModel>();
|
ViewModel = EditorApplication.GetService<OpenProjectViewModel>();
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<winex:WindowEx
|
<winex:WindowEx
|
||||||
x:Class="Ghost.App.View.Windows.EngineEditorWindow"
|
x:Class="Ghost.Editor.View.Windows.EngineEditorWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
|
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
|
||||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:ee="using:Ghost.App.View.Pages.EngineEditor"
|
xmlns:ee="using:Ghost.Editor.View.Pages.EngineEditor"
|
||||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:local="using:Ghost.App.View.Windows"
|
xmlns:internal="using:Ghost.Editor.Controls.Internal"
|
||||||
|
xmlns:local="using:Ghost.Editor.View.Windows"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:winex="using:WinUIEx"
|
xmlns:winex="using:WinUIEx"
|
||||||
Activated="WindowEx_Activated"
|
Activated="WindowEx_Activated"
|
||||||
@@ -86,23 +87,18 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TabView
|
<internal:NavigationTabView
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Width="350"
|
Width="350"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch">
|
VerticalAlignment="Stretch">
|
||||||
<TabView.TabItems>
|
<internal:NavigationTabView.TabItems>
|
||||||
<TabViewItem Header="Hierarchy">
|
<ee:HierarchyPage />
|
||||||
<TabViewItem.IconSource>
|
</internal:NavigationTabView.TabItems>
|
||||||
<FontIconSource Glyph="" />
|
</internal:NavigationTabView>
|
||||||
</TabViewItem.IconSource>
|
|
||||||
<ee:HierarchyPage />
|
|
||||||
</TabViewItem>
|
|
||||||
</TabView.TabItems>
|
|
||||||
</TabView>
|
|
||||||
|
|
||||||
<TabView Grid.Column="1">
|
<internal:NavigationTabView Grid.Column="1">
|
||||||
<TabView.TabItems>
|
<internal:NavigationTabView.TabItems>
|
||||||
<TabViewItem Header="Scene">
|
<TabViewItem Header="Scene">
|
||||||
<TabViewItem.IconSource>
|
<TabViewItem.IconSource>
|
||||||
<FontIconSource Glyph="" />
|
<FontIconSource Glyph="" />
|
||||||
@@ -112,17 +108,22 @@
|
|||||||
Source="C:\Users\Misaki\OneDrive\Pictures\Screenshots\Screenshot 2024-07-20 021657.png"
|
Source="C:\Users\Misaki\OneDrive\Pictures\Screenshots\Screenshot 2024-07-20 021657.png"
|
||||||
Stretch="UniformToFill" />
|
Stretch="UniformToFill" />
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
</TabView.TabItems>
|
</internal:NavigationTabView.TabItems>
|
||||||
</TabView>
|
</internal:NavigationTabView>
|
||||||
|
|
||||||
<Grid
|
<internal:NavigationTabView
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Width="350"
|
Width="350"
|
||||||
Background="Bisque" />
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Stretch">
|
||||||
|
<internal:NavigationTabView.TabItems>
|
||||||
|
<ee:InspectorPage />
|
||||||
|
</internal:NavigationTabView.TabItems>
|
||||||
|
</internal:NavigationTabView>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<TabView Grid.Row="1" Height="350">
|
<internal:NavigationTabView Grid.Row="1" Height="350">
|
||||||
<TabView.TabItems>
|
<internal:NavigationTabView.TabItems>
|
||||||
<TabViewItem Header="Project">
|
<TabViewItem Header="Project">
|
||||||
<TabViewItem.IconSource>
|
<TabViewItem.IconSource>
|
||||||
<FontIconSource Glyph="" />
|
<FontIconSource Glyph="" />
|
||||||
@@ -135,8 +136,8 @@
|
|||||||
</TabViewItem.IconSource>
|
</TabViewItem.IconSource>
|
||||||
<ee:ConsolePage />
|
<ee:ConsolePage />
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
</TabView.TabItems>
|
</internal:NavigationTabView.TabItems>
|
||||||
</TabView>
|
</internal:NavigationTabView>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Status Bar -->
|
<!-- Status Bar -->
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Ghost.App.Services;
|
using Ghost.Data.Resources;
|
||||||
using Ghost.Data.Resources;
|
using Ghost.Editor.Services;
|
||||||
using Ghost.Editor.Services.Contracts;
|
using Ghost.Editor.Services.Contracts;
|
||||||
using Ghost.Editor.ViewModels.Windows;
|
using Ghost.Editor.ViewModels.Windows;
|
||||||
using Ghost.Engine.Resources;
|
using Ghost.Engine.Resources;
|
||||||
@@ -9,7 +9,7 @@ using WinUIEx;
|
|||||||
// To learn more about WinUI, the WinUI project structure,
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
namespace Ghost.App.View.Windows;
|
namespace Ghost.Editor.View.Windows;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An empty window that can be used on its own or navigated to within a Frame.
|
/// An empty window that can be used on its own or navigated to within a Frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -27,10 +27,10 @@ internal sealed partial class EngineEditorWindow : WindowEx
|
|||||||
|
|
||||||
public EngineEditorWindow()
|
public EngineEditorWindow()
|
||||||
{
|
{
|
||||||
ViewModel = GhostApplication.GetService<EngineEditorViewModel>();
|
ViewModel = EditorApplication.GetService<EngineEditorViewModel>();
|
||||||
|
|
||||||
_notificationService = (NotificationService)GhostApplication.GetService<INotificationService>();
|
_notificationService = (NotificationService)EditorApplication.GetService<INotificationService>();
|
||||||
_progressService = (ProgressService)GhostApplication.GetService<IProgressService>();
|
_progressService = (ProgressService)EditorApplication.GetService<IProgressService>();
|
||||||
|
|
||||||
AppWindow.SetIcon(AssetsPath.s_appIconPath);
|
AppWindow.SetIcon(AssetsPath.s_appIconPath);
|
||||||
Title = EngineData.ENGINE_NAME;
|
Title = EngineData.ENGINE_NAME;
|
||||||
@@ -46,7 +46,7 @@ internal sealed partial class EngineEditorWindow : WindowEx
|
|||||||
Bindings.Update();
|
Bindings.Update();
|
||||||
|
|
||||||
_editorScope?.Dispose();
|
_editorScope?.Dispose();
|
||||||
_editorScope = GhostApplication.CreateScope();
|
_editorScope = EditorApplication.CreateScope();
|
||||||
|
|
||||||
_notificationService.SetReference(InfoBar, NotificationQueue);
|
_notificationService.SetReference(InfoBar, NotificationQueue);
|
||||||
_progressService.SetReference(ProgressBarContainer);
|
_progressService.SetReference(ProgressBarContainer);
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<winex:WindowEx
|
<winex:WindowEx
|
||||||
x:Class="Ghost.App.View.Windows.LandingWindow"
|
x:Class="Ghost.Editor.View.Windows.LandingWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
|
xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:local="using:Ghost.App.View.Windows"
|
xmlns:local="using:Ghost.Editor.View.Windows"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:winex="using:WinUIEx"
|
xmlns:winex="using:WinUIEx"
|
||||||
Activated="WindowEx_Activated"
|
Activated="WindowEx_Activated"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Ghost.App.Services;
|
using Ghost.Editor.View.Pages.Landing;
|
||||||
using Ghost.App.View.Pages.Landing;
|
|
||||||
using Ghost.Data.Resources;
|
using Ghost.Data.Resources;
|
||||||
|
using Ghost.Editor.Services;
|
||||||
using Ghost.Editor.Services.Contracts;
|
using Ghost.Editor.Services.Contracts;
|
||||||
using Ghost.Engine.Resources;
|
using Ghost.Engine.Resources;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -8,7 +8,7 @@ using Microsoft.UI.Xaml.Controls;
|
|||||||
using Microsoft.UI.Xaml.Media.Animation;
|
using Microsoft.UI.Xaml.Media.Animation;
|
||||||
using WinUIEx;
|
using WinUIEx;
|
||||||
|
|
||||||
namespace Ghost.App.View.Windows;
|
namespace Ghost.Editor.View.Windows;
|
||||||
|
|
||||||
internal sealed partial class LandingWindow : WindowEx
|
internal sealed partial class LandingWindow : WindowEx
|
||||||
{
|
{
|
||||||
@@ -20,7 +20,7 @@ internal sealed partial class LandingWindow : WindowEx
|
|||||||
|
|
||||||
public LandingWindow()
|
public LandingWindow()
|
||||||
{
|
{
|
||||||
_notificationService = (NotificationService)GhostApplication.GetService<INotificationService>();
|
_notificationService = (NotificationService)EditorApplication.GetService<INotificationService>();
|
||||||
|
|
||||||
AppWindow.SetIcon(AssetsPath.s_appIconPath);
|
AppWindow.SetIcon(AssetsPath.s_appIconPath);
|
||||||
Title = EngineData.ENGINE_NAME;
|
Title = EngineData.ENGINE_NAME;
|
||||||
@@ -36,7 +36,7 @@ internal sealed partial class LandingWindow : WindowEx
|
|||||||
private void WindowEx_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
|
private void WindowEx_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
|
||||||
{
|
{
|
||||||
_landingScope?.Dispose();
|
_landingScope?.Dispose();
|
||||||
_landingScope = GhostApplication.CreateScope();
|
_landingScope = EditorApplication.CreateScope();
|
||||||
_notificationService.SetReference(InfoBar, NotificationQueue);
|
_notificationService.SetReference(InfoBar, NotificationQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.Editor.SceneGraph;
|
using Ghost.Editor.Contracts;
|
||||||
using System;
|
using Ghost.Editor.Core.SceneGraph;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
|
|
||||||
internal partial class HierarchyViewModel : ObservableObject, IDisposable
|
internal partial class HierarchyViewModel : ObservableObject, INavigationAware
|
||||||
{
|
{
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial ObservableCollection<WorldNode> SceneList
|
public partial ObservableCollection<WorldNode> SceneList
|
||||||
@@ -14,12 +14,6 @@ internal partial class HierarchyViewModel : ObservableObject, IDisposable
|
|||||||
private set;
|
private set;
|
||||||
} = new(EditorWorldManager.LoadedWorlds);
|
} = new(EditorWorldManager.LoadedWorlds);
|
||||||
|
|
||||||
public HierarchyViewModel()
|
|
||||||
{
|
|
||||||
EditorWorldManager.OnWorldLoaded += OnWorldLoaded;
|
|
||||||
EditorWorldManager.OnWorldUnloaded += OnWorldUnloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWorldLoaded(WorldNode node)
|
private void OnWorldLoaded(WorldNode node)
|
||||||
{
|
{
|
||||||
SceneList.Add(node);
|
SceneList.Add(node);
|
||||||
@@ -30,7 +24,13 @@ internal partial class HierarchyViewModel : ObservableObject, IDisposable
|
|||||||
SceneList.Remove(node);
|
SceneList.Remove(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void OnNavigatedTo(object? parameter)
|
||||||
|
{
|
||||||
|
EditorWorldManager.OnWorldLoaded += OnWorldLoaded;
|
||||||
|
EditorWorldManager.OnWorldUnloaded += OnWorldUnloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnNavigatedFrom()
|
||||||
{
|
{
|
||||||
EditorWorldManager.OnWorldLoaded -= OnWorldLoaded;
|
EditorWorldManager.OnWorldLoaded -= OnWorldLoaded;
|
||||||
EditorWorldManager.OnWorldUnloaded -= OnWorldUnloaded;
|
EditorWorldManager.OnWorldUnloaded -= OnWorldUnloaded;
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Services.Contracts;
|
||||||
|
|
||||||
|
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
|
|
||||||
|
internal partial class InspectorViewModel(IInspectorService inspectorService) : ObservableObject, INavigationAware
|
||||||
|
{
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial IInspectable? Inspectable
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnNavigatedTo(object? parameter)
|
||||||
|
{
|
||||||
|
inspectorService.OnSelectionChanged += OnSelectionChanged;
|
||||||
|
Inspectable = inspectorService.SelectedInspectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnNavigatedFrom()
|
||||||
|
{
|
||||||
|
inspectorService.OnSelectionChanged -= OnSelectionChanged;
|
||||||
|
Inspectable = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectionChanged()
|
||||||
|
{
|
||||||
|
Inspectable = inspectorService.SelectedInspectable;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,8 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.App;
|
|
||||||
using Ghost.App.Models;
|
|
||||||
using Ghost.Data.Services;
|
using Ghost.Data.Services;
|
||||||
using Ghost.Editor.AssetHandle;
|
using Ghost.Editor.Core.AssetHandle;
|
||||||
using System;
|
using Ghost.Editor.Models;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
|
||||||
|
|
||||||
@@ -96,7 +91,7 @@ internal partial class ProjectViewModel : ObservableObject
|
|||||||
|
|
||||||
private void NavigateToDirectory(string? path)
|
private void NavigateToDirectory(string? path)
|
||||||
{
|
{
|
||||||
GhostApplication.Window?.DispatcherQueue.TryEnqueue(async () =>
|
EditorApplication.Window?.DispatcherQueue.TryEnqueue(async () =>
|
||||||
{
|
{
|
||||||
DirectoryAssets.Clear();
|
DirectoryAssets.Clear();
|
||||||
|
|
||||||
@@ -121,7 +116,7 @@ internal partial class ProjectViewModel : ObservableObject
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OpenSelected()
|
public void OpenSelected()
|
||||||
{
|
{
|
||||||
if (SelectedAsset == null)
|
if (SelectedAsset == null)
|
||||||
{
|
{
|
||||||
@@ -134,7 +129,7 @@ internal partial class ProjectViewModel : ObservableObject
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await AssetDatabase.OpenAsset(SelectedAsset.FullName);
|
AssetDatabase.OpenAsset(SelectedAsset.FullName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Ghost.App.Contracts;
|
|
||||||
using Ghost.App.Infrastructures.AppState;
|
|
||||||
using Ghost.App.Services;
|
|
||||||
using Ghost.App.Utilities;
|
|
||||||
using Ghost.Data.Models;
|
using Ghost.Data.Models;
|
||||||
using Ghost.Data.Services;
|
using Ghost.Data.Services;
|
||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Core.AppState;
|
||||||
using Ghost.Editor.Models;
|
using Ghost.Editor.Models;
|
||||||
|
using Ghost.Editor.Services;
|
||||||
|
using Ghost.Editor.Utilities;
|
||||||
using Ghost.Engine.Resources;
|
using Ghost.Engine.Resources;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using Ghost.App.Contracts;
|
|
||||||
using Ghost.App.Infrastructures.AppState;
|
|
||||||
using Ghost.Data.Models;
|
using Ghost.Data.Models;
|
||||||
using Ghost.Data.Services;
|
using Ghost.Data.Services;
|
||||||
|
using Ghost.Editor.Contracts;
|
||||||
|
using Ghost.Editor.Core.AppState;
|
||||||
using Ghost.Editor.Models;
|
using Ghost.Editor.Models;
|
||||||
using Ghost.Editor.Services.Contracts;
|
using Ghost.Editor.Services.Contracts;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using System;
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Windows.ApplicationModel.DataTransfer;
|
using Windows.ApplicationModel.DataTransfer;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Ghost.App")]
|
[assembly: InternalsVisibleTo("Ghost.Editor")]
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ghost.Editor.Models;
|
namespace Ghost.Editor.AssetHandle;
|
||||||
|
|
||||||
public abstract class Asset
|
public abstract class Asset
|
||||||
{
|
{
|
||||||
@@ -3,5 +3,6 @@
|
|||||||
namespace Ghost.Editor.Contracts;
|
namespace Ghost.Editor.Contracts;
|
||||||
internal interface IInspectable
|
internal interface IInspectable
|
||||||
{
|
{
|
||||||
public UIElement OnInspectorDraw();
|
public UIElement HeaderContent();
|
||||||
|
public UIElement InspectorContent();
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,12 @@ public partial class WorldNode : SceneGraphNode, IEquatable<WorldNode>
|
|||||||
|
|
||||||
public partial class WorldNode : IInspectable
|
public partial class WorldNode : IInspectable
|
||||||
{
|
{
|
||||||
public UIElement OnInspectorDraw()
|
public UIElement HeaderContent()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UIElement InspectorContent()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,4 +9,6 @@ internal interface IInspectorService
|
|||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event Action? OnSelectionChanged;
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Ghost.App")]
|
[assembly: InternalsVisibleTo("Ghost.Editor")]
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ global using WorldID = System.UInt16;
|
|||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Ghost.App")]
|
|
||||||
[assembly: InternalsVisibleTo("Ghost.Engine")]
|
[assembly: InternalsVisibleTo("Ghost.Engine")]
|
||||||
[assembly: InternalsVisibleTo("Ghost.Editor")]
|
[assembly: InternalsVisibleTo("Ghost.Editor")]
|
||||||
[assembly: InternalsVisibleTo("Ghost.UnitTest")]
|
[assembly: InternalsVisibleTo("Ghost.UnitTest")]
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
<PackageReference Include="MSTest.TestFramework" Version="3.9.1" />
|
<PackageReference Include="MSTest.TestFramework" Version="3.9.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ghost.Editor\Ghost.Editor.csproj" />
|
<ProjectReference Include="..\Ghost.App\Ghost.Editor.csproj" />
|
||||||
<ProjectReference Include="..\Ghost.Engine\Ghost.Engine.csproj" />
|
<ProjectReference Include="..\Ghost.Engine\Ghost.Engine.csproj" />
|
||||||
<ProjectReference Include="..\Ghost.Entities\Ghost.Entities.csproj" />
|
<ProjectReference Include="..\Ghost.Entities\Ghost.Entities.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using Ghost.Entities;
|
using Ghost.Entities;
|
||||||
using Ghost.Entities.Components;
|
using Ghost.Entities.Components;
|
||||||
using Ghost.Entities.Systems;
|
using Ghost.Entities.Systems;
|
||||||
using Ghost.Test.TestFramework;
|
using Ghost.UnitTest.TestFramework;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ghost.Test;
|
namespace Ghost.UnitTest;
|
||||||
|
|
||||||
public partial class EntityTest : ITest
|
public partial class EntityTest : ITest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using Ghost.Editor.SceneGraph;
|
using Ghost.Editor.Core.SceneGraph;
|
||||||
using Ghost.Entities;
|
using Ghost.Entities;
|
||||||
using Ghost.Test.TestFramework;
|
using Ghost.UnitTest.TestFramework;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Ghost.Test;
|
namespace Ghost.UnitTest.Test;
|
||||||
|
|
||||||
internal class SerializationTest : ITest
|
internal class SerializationTest : ITest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ghost.Test.TestFramework;
|
namespace Ghost.UnitTest.TestFramework;
|
||||||
|
|
||||||
internal interface ITest
|
internal interface ITest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Ghost.Test.TestFramework;
|
namespace Ghost.UnitTest.TestFramework;
|
||||||
|
|
||||||
internal class TestRunner
|
internal class TestRunner
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,21 +1,5 @@
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
|
||||||
using Microsoft.UI.Xaml.Input;
|
|
||||||
using Microsoft.UI.Xaml.Media;
|
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
|
||||||
using Microsoft.UI.Xaml.Shapes;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
|
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
|
||||||
using Windows.ApplicationModel.Activation;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
@@ -41,7 +25,7 @@ public partial class UnitTestApp : Application
|
|||||||
/// Invoked when the application is launched.
|
/// Invoked when the application is launched.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="args">Details about the launch request and process.</param>
|
/// <param name="args">Details about the launch request and process.</param>
|
||||||
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||||
{
|
{
|
||||||
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
|
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
|
||||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
|
||||||
using Microsoft.UI.Xaml.Input;
|
|
||||||
using Microsoft.UI.Xaml.Media;
|
|
||||||
using Microsoft.UI.Xaml.Navigation;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
|
|
||||||
// To learn more about WinUI, the WinUI project structure,
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
|
using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Ghost.UnitTest;
|
namespace Ghost.UnitTest;
|
||||||
[TestClass]
|
[TestClass]
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.14.35906.104
|
VisualStudioVersion = 17.14.35906.104
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.App", "Ghost.App\Ghost.App.csproj", "{15AFE3A1-0CAF-4B36-8835-121C4D683BBF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Editor", "Ghost.App\Ghost.Editor.csproj", "{15AFE3A1-0CAF-4B36-8835-121C4D683BBF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Engine", "Ghost.Engine\Ghost.Engine.csproj", "{1ED62E09-8F36-4671-896B-16C1C1530202}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Engine", "Ghost.Engine\Ghost.Engine.csproj", "{1ED62E09-8F36-4671-896B-16C1C1530202}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -15,8 +15,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Graphics", "Ghost.Gra
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Generator", "Ghost.Generator\Ghost.Generator.csproj", "{996ABECC-1C5A-4F07-B8AC-D063F91962CB}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Generator", "Ghost.Generator\Ghost.Generator.csproj", "{996ABECC-1C5A-4F07-B8AC-D063F91962CB}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.Editor", "Ghost.Editor\Ghost.Editor.csproj", "{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}"
|
|
||||||
EndProject
|
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.UnitTest", "Ghost.UnitTest\Ghost.UnitTest.csproj", "{4179873E-8174-4D17-9584-8C223BA71366}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghost.UnitTest", "Ghost.UnitTest\Ghost.UnitTest.csproj", "{4179873E-8174-4D17-9584-8C223BA71366}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
@@ -107,18 +105,6 @@ Global
|
|||||||
{996ABECC-1C5A-4F07-B8AC-D063F91962CB}.Release|x64.Build.0 = Release|Any CPU
|
{996ABECC-1C5A-4F07-B8AC-D063F91962CB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{996ABECC-1C5A-4F07-B8AC-D063F91962CB}.Release|x86.ActiveCfg = Release|Any CPU
|
{996ABECC-1C5A-4F07-B8AC-D063F91962CB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{996ABECC-1C5A-4F07-B8AC-D063F91962CB}.Release|x86.Build.0 = Release|Any CPU
|
{996ABECC-1C5A-4F07-B8AC-D063F91962CB}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Debug|ARM64.Build.0 = Debug|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Release|ARM64.ActiveCfg = Release|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Release|ARM64.Build.0 = Release|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{CC6E1FCB-A80E-4F6C-B519-C8CADB6D5650}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{4179873E-8174-4D17-9584-8C223BA71366}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
{4179873E-8174-4D17-9584-8C223BA71366}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
{4179873E-8174-4D17-9584-8C223BA71366}.Debug|ARM64.Build.0 = Debug|ARM64
|
{4179873E-8174-4D17-9584-8C223BA71366}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
{4179873E-8174-4D17-9584-8C223BA71366}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
{4179873E-8174-4D17-9584-8C223BA71366}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||||
|
|||||||
13
Test/Class1.cs
Normal file
13
Test/Class1.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace Test;
|
||||||
|
public partial class Class1
|
||||||
|
{
|
||||||
|
}
|
||||||
17
Test/Test.csproj
Normal file
17
Test/Test.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||||
|
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
|
||||||
|
<RootNamespace>Test</RootNamespace>
|
||||||
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||||
|
<UseWinUI>true</UseWinUI>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
|
||||||
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250606001" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ghost.Editor\Ghost.Editor.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Reference in New Issue
Block a user