From 97113b5df67d2645fe30768f874f10ed2b88ad3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Mon, 31 Jul 2023 17:40:05 +0200 Subject: [PATCH] Start of Create Asset Context Menu + Asset Hierarchy: Fixed Assets in Folder-Root not being shown --- GlitchyEditor/src/Assets/AssetHierarchy.bf | 16 +-- .../src/EditWindows/ContentBrowserWindow.bf | 106 ++++++++++++++++++ GlitchyEditor/src/EditorLayer.bf | 84 +++++++++++--- 3 files changed, 181 insertions(+), 25 deletions(-) diff --git a/GlitchyEditor/src/Assets/AssetHierarchy.bf b/GlitchyEditor/src/Assets/AssetHierarchy.bf index 94884eb..1b8e48b 100644 --- a/GlitchyEditor/src/Assets/AssetHierarchy.bf +++ b/GlitchyEditor/src/Assets/AssetHierarchy.bf @@ -248,15 +248,7 @@ class AssetHierarchy fsw.OnRenamed.Add(new (oldName, newName) => { Log.EngineLogger.Trace($"File renamed (From \"{oldName}\" to \"{newName}\")"); - //_fileSystemDirty = true; FileRenamed(oldName, newName); - /*String contentFilePath = scope String(); - - Path.InternalCombine(contentFilePath, ContentDirectory, oldName); - - //_fileSystemDirty = true; - TreeNode fileNode = GetNodeFromPath(contentFilePath); - fileNode->*/ }); fsw.StartRaisingEvents(); @@ -473,6 +465,9 @@ class AssetHierarchy AddDirectoryToTree(directoryNameBuffer, _assetsDirectoryNode); } + + RemoveOrphanedEntries(_assetsDirectoryNode); + AddFilesOfDirectory(_assetsDirectoryNode); } if (!ResourcesDirectory.IsWhiteSpace) @@ -487,8 +482,9 @@ class AssetHierarchy AddDirectoryToTree(directoryNameBuffer, _resourcesDirectoryNode); } - - RemoveOrphanedEntries(_assetRootNode); + + RemoveOrphanedEntries(_resourcesDirectoryNode); + AddFilesOfDirectory(_resourcesDirectoryNode); } //*String filter = scope $"{AssetsDirectory}/*"; diff --git a/GlitchyEditor/src/EditWindows/ContentBrowserWindow.bf b/GlitchyEditor/src/EditWindows/ContentBrowserWindow.bf index b17d376..7d06228 100644 --- a/GlitchyEditor/src/EditWindows/ContentBrowserWindow.bf +++ b/GlitchyEditor/src/EditWindows/ContentBrowserWindow.bf @@ -13,8 +13,35 @@ namespace GlitchyEditor.EditWindows { using internal GlitchyEditor.EditorContentManager; + class AssetCreator + { + private String _name ~ delete _; + private String _defaultFileName ~ delete _; + private CreateAssetFunc _doCreateAsset ~ delete _; + + public delegate void CreateAssetFunc(StringView outputPath); + + public StringView Name => _name; + public StringView DefaultFileName => _defaultFileName; + + public CreateAssetFunc CreateAsset => _doCreateAsset; + + public this(StringView name, StringView defaultFileName, CreateAssetFunc createAsset) + { + _name = new String(name); + _defaultFileName = new String(defaultFileName); + _doCreateAsset = createAsset; + } + } + class ContentBrowserWindow : EditorWindow { + private append List _assetCreators = .() ~ ClearAndDeleteItems!(_); + + private typealias AssetCreatorTree = TreeNode<(StringView Name, AssetCreator Creator)>; + + private AssetCreatorTree _creatorTree = new AssetCreatorTree(("Create new Asset", null)) ~ delete _; + public const String s_WindowTitle = "Content Browser"; private append String _currentDirectory = .(); @@ -33,6 +60,28 @@ namespace GlitchyEditor.EditWindows _manager = contentManager; } + public void RegisterAssetCreator(AssetCreator assetCreator) + { + _assetCreators.Add(assetCreator); + + AssetCreatorTree tree = _creatorTree; + + for (StringView entryName in assetCreator.Name.Split('/')) + { + AssetCreatorTree nextNode = tree.Children.Where(scope (node) => node->Name == entryName).FirstOrDefault(); + + // Create new node if we didn't find it + nextNode ??= tree.AddChild((entryName, null)); + + tree = nextNode; + } + + if (tree->Creator == null) + { + tree->Creator = assetCreator; + } + } + protected override void InternalShow() { _manager.Update(); @@ -121,6 +170,63 @@ namespace GlitchyEditor.EditWindows if (Path.OpenFolder(_currentDirectory) case .Err) Log.EngineLogger.Error("Failed to open directory in file browser."); } + + ImGui.Separator(); + + ShowCreateContextMenu(_creatorTree); + } + + /// Shows the menu for the given asset creator tree. + private void ShowCreateContextMenu(AssetCreatorTree subtree) + { + if (subtree.Children.Count == 0) + { + if (ImGui.MenuItem(subtree->Name.ToScopeCStr!())) + { + CreateAsset(subtree->Creator); + } + } + else + { + if (ImGui.BeginMenu(subtree->Name.ToScopeCStr!())) + { + for (let node in subtree.Children) + { + ShowCreateContextMenu(node); + } + + ImGui.EndMenu(); + } + } + } + + /// Creates a new asset with the given creator + private void CreateAsset(AssetCreator creator) + { + if (!Directory.Exists(_currentDirectory)) + { + Log.EngineLogger.Error($"Directory {_currentDirectory} doesn't exist."); + return; + } + + String currentFile = scope String(); + Path.Combine(currentFile, _currentDirectory, creator.DefaultFileName); + + String fileExtension = scope String(); + Path.GetExtension(currentFile, fileExtension); + + StringView fileWithoutExtension = currentFile[0...^(fileExtension.Length + 1)]; + + int i = 0; + while (File.Exists(currentFile)) + { + i++; + currentFile.Set(fileWithoutExtension); + currentFile.AppendF($"({i})"); + currentFile.Append(fileExtension); + } + + creator.CreateAsset(currentFile); } /// Renders a sidebar that shows a tree of all directories in the asset folder. diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 322dcb6..d720b99 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -120,6 +120,8 @@ namespace GlitchyEditor InitEditor(); + RegisterAssetCreators(); + if (args.Count >= 1) { Result result = OpenProject(args[0]); @@ -137,6 +139,17 @@ namespace GlitchyEditor NewScene(); } + private void RegisterAssetCreators() + { + Editor.Instance.ContentBrowserWindow.RegisterAssetCreator(new AssetCreator("Scene", "New Scene.scene", new (path) => + { + using (Scene newScene = CreateNewScene()) + { + SaveScene(newScene, path); + } + })); + } + private void InitGraphics() { _context = Application.Get().Window.Context..AddRef(); @@ -893,12 +906,12 @@ namespace GlitchyEditor SceneFilePath = null; - using (Scene newScene = new Scene()) + using (Scene newScene = CreateNewScene()) { _camera.Position = .(-1.5f, 1.5f, -2.5f); _camera.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0); - // Create a default camera + /*// Create a default camera { let cameraEntity = newScene.CreateEntity("Camera"); let transform = cameraEntity.Transform; @@ -922,13 +935,46 @@ namespace GlitchyEditor let light = lightEntity.AddComponent(); light.SceneLight.Illuminance = 10.0f; light.SceneLight.Color = .(1.0f, 0.95f, 0.8f); - } + }*/ SetReference!(_editorScene, newScene); _editor.CurrentScene = _editorScene; SetReference!(_activeScene, _editorScene); } } + + private static Scene CreateNewScene() + { + Scene newScene = new Scene(); + + // Create a default camera + { + let cameraEntity = newScene.CreateEntity("Camera"); + let transform = cameraEntity.Transform; + transform.Position = float3(0, 2, -5); + transform.RotationEuler = float3(0, MathHelper.ToRadians(25), 0); + + let camera = cameraEntity.AddComponent(); + camera.Primary = true; + camera.Camera.ProjectionType = .InfinitePerspective; + camera.Camera.PerspectiveFovY = MathHelper.ToRadians(75); + camera.Camera.PerspectiveNearPlane = 0.1f; + } + + // Create a default light source + { + let lightEntity = newScene.CreateEntity("Light"); + let transform = lightEntity.Transform; + transform.Position = .(-3, 4, -1.5f); + transform.RotationEuler = .(MathHelper.ToRadians(20), MathHelper.ToRadians(75), MathHelper.ToRadians(20)); + + let light = lightEntity.AddComponent(); + light.SceneLight.Illuminance = 10.0f; + light.SceneLight.Color = .(1.0f, 0.95f, 0.8f); + } + + return newScene; + } /// Saves the scene in the file that is was loaded from or saved to last. If there is no such path (i.e. it is a new scene) the save file dialog will open. private void SaveScene() @@ -942,6 +988,12 @@ namespace GlitchyEditor SceneSerializer serializer = scope .(_editorScene); serializer.Serialize(SceneFilePath); } + + private static void SaveScene(Scene scene, StringView fileName) + { + SceneSerializer serializer = scope .(scene); + serializer.Serialize(fileName); + } /// Opens a save file dialog and saves the scene at the user specified location. private void SaveSceneAs() @@ -1009,7 +1061,7 @@ namespace GlitchyEditor if (ImGui.MenuItem(scope $"{i}: {name} ({path})")) { - LoadSceneFile(path); + //LoadSceneFile(path); } } } @@ -1020,25 +1072,27 @@ namespace GlitchyEditor if(ImGui.BeginMenu("File", true)) { - if (ImGui.MenuItem("Create new Project...", "Ctrl+N")) - _openCreateProjectModal = true; - - if (ImGui.MenuItem("Open Project...", "Ctrl+O")) - ShowOpenProjectDialog(); - - if (ImGui.MenuItem("New", "Ctrl+N")) + if (ImGui.MenuItem("New Scene...", "Ctrl+N")) NewScene(); - if (ImGui.MenuItem("Save", "Ctrl+S")) + if (ImGui.MenuItem("Save Scene", "Ctrl+S")) SaveScene(); - if (ImGui.MenuItem("Save as...", "Ctrl+Shift+S")) + if (ImGui.MenuItem("Save Scene as...", "Ctrl+Shift+S")) SaveSceneAs(); - if (ImGui.MenuItem("Open...", "Ctrl+O")) + if (ImGui.MenuItem("Open Scene...", "Ctrl+O")) OpenScene(); + + ImGui.Separator(); - if (ImGui.BeginMenu("Open Recent")) + if (ImGui.MenuItem("Create new Project...", "Ctrl+ALT+N")) + _openCreateProjectModal = true; + + if (ImGui.MenuItem("Open Project...", "Ctrl+ALT+O")) + ShowOpenProjectDialog(); + + if (ImGui.BeginMenu("Open recent project")) { DrawOpenRecentProjectMenu();