Files
GhostEngine/Ghost.Editor/ViewModels/Pages/EngineEditor/ProjectViewModel.cs
Misaki bab3be2508 Refactor project structure and improve performance
Changed the `ProjectRepository` class to be static for easier usage.
Changed `ProjectService` constants to public properties for accessibility.
Changed `App.xaml` to consolidate theme resources into `Override.xaml`.
Changed `App.xaml.cs` to implement an `AppStateMachine` for better state management.
Changed `ConsolePage` and `HierarchyPage` to utilize the new ViewModel structure.
Changed `ProjectPage` to use the `ExplorerItem` model for asset display.
Changed `Entity` and `EntityManager` to enhance component management with a new `IComponentData` interface.
Changed the `Logger` class to introduce structured logging functionality.
Changed the system architecture to support dependency management for better organization.
Changed the `QueryEnumerable` class to allow for more flexible entity queries.
Changed the `TypeHandle` class to improve efficiency in retrieving type handles.
Changed the `World` class to support robust world management and multiple worlds.
Updated the `Test` class to demonstrate the new entity and component management system.
2025-06-05 21:45:50 +09:00

142 lines
3.7 KiB
C#

using CommunityToolkit.Mvvm.ComponentModel;
using Ghost.Data.Services;
using Ghost.Editor.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
namespace Ghost.Editor.ViewModels.Pages.EngineEditor;
internal partial class ProjectViewModel : ObservableObject
{
public ObservableCollection<ExplorerItem> SubDirectories
{
get;
} = new();
[ObservableProperty]
public partial ObservableCollection<ExplorerItem> DirectoryAssets
{
get;
set;
} = new();
[ObservableProperty]
public partial ExplorerItem? SelectedDirectory
{
get;
set;
}
[ObservableProperty]
public partial ExplorerItem? SelectedAsset
{
get;
set;
}
public ProjectViewModel()
{
if (ProjectService.CurrentProject.Metadata == null)
{
throw new InvalidOperationException("Current project is not set.");
}
var assetsItem = new ExplorerItem("Assets", Path.Combine(Path.GetDirectoryName(ProjectService.CurrentProject.Path)!, ProjectService.ASSETS_FOLDER), true);
LoadSubFolderRecursive(ref assetsItem);
SubDirectories.Add(assetsItem);
}
private void LoadSubFolderRecursive(ref ExplorerItem parentItem)
{
foreach (var directory in Directory.EnumerateDirectories(parentItem.Path))
{
var item = new ExplorerItem(Path.GetFileName(directory), directory, true);
LoadSubFolderRecursive(ref item);
parentItem.Children ??= new();
parentItem.Children.Add(item);
}
}
public static Task<ExplorerItem?> FindNodeIterative(ExplorerItem root, Func<ExplorerItem, bool> predicate)
{
var stack = new Stack<ExplorerItem>();
stack.Push(root);
return Task.Run(() =>
{
while (stack.Count > 0)
{
var node = stack.Pop();
if (predicate(node))
{
return node;
}
if (node.Children == null || node.Children.Count == 0)
{
continue;
}
for (var i = node.Children.Count - 1; i >= 0; i--)
{
stack.Push(node.Children[i]);
}
}
return null;
});
}
private void NavigateToDirectory(string? path)
{
App.Window?.DispatcherQueue.TryEnqueue(async () =>
{
DirectoryAssets.Clear();
if (!Directory.Exists(path))
{
return;
}
foreach (var directory in Directory.EnumerateDirectories(path))
{
var directoryItem = new ExplorerItem(Path.GetFileName(directory), directory, true);
DirectoryAssets.Add(directoryItem);
}
foreach (var file in Directory.EnumerateFiles(path))
{
var fileItem = new ExplorerItem(Path.GetFileName(file), file, false);
DirectoryAssets.Add(fileItem);
}
SelectedDirectory = await FindNodeIterative(SubDirectories[0], x => x.Path == path);
});
}
public void NavigateToSelected()
{
if (SelectedAsset == null || !SelectedAsset.IsDirectory)
{
return;
}
NavigateToDirectory(SelectedAsset.Path);
}
partial void OnSelectedDirectoryChanged(ExplorerItem? value)
{
DirectoryAssets.Clear();
if (value == null)
{
return;
}
NavigateToDirectory(value.Path);
}
}