Content browser

This commit is contained in:
Simon Lübeß
2022-07-25 17:03:28 +02:00
parent 0339ae4422
commit bff4418b84
21 changed files with 481 additions and 44 deletions
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,272 @@
using ImGui;
using System;
using System.IO;
using GlitchyEngine.Collections;
using System.Collections;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
namespace GlitchyEditor.EditWindows
{
class ContentBrowserWindow : EditorWindow
{
// TODO: Get from project
const String ContentDirectory = "./content";
FileSystemWatcher fsw ~ {
_.StopRaisingEvents();
delete _;
};
private String _currentDirectory ~ delete _;
public static SubTexture2D s_FolderTexture;
public static SubTexture2D s_FileTexture;
public this()
{
fsw = new FileSystemWatcher(ContentDirectory);
fsw.IncludeSubdirectories = true;
fsw.OnChanged.Add(new (filename) => {
_fileSystemDirty = true;
_currentDirectoryDirty = true;
});
fsw.OnCreated.Add(new (filename) => {
_fileSystemDirty = true;
_currentDirectoryDirty = true;
});
fsw.OnDeleted.Add(new (filename) => {
_fileSystemDirty = true;
_currentDirectoryDirty = true;
});
fsw.OnRenamed.Add(new (newName, oldName) => {
_fileSystemDirty = true;
_currentDirectoryDirty = true;
});
fsw.StartRaisingEvents();
}
protected override void InternalShow()
{
if(!ImGui.Begin("Content Browser", &_open, .None))
{
ImGui.End();
return;
}
if (_fileSystemDirty)
{
BuildDirectoryTree();
_fileSystemDirty = false;
}
if (_currentDirectoryDirty)
{
BuildCurrentDirectory();
}
ImGui.Columns(2);
DrawDirectorySideBar();
ImGui.NextColumn();
DrawCurrentDirectory();
ImGui.Columns(1);
ImGui.End();
}
private bool _fileSystemDirty = true;
private bool _currentDirectoryDirty = true;
class DirectoryNode
{
public String Name ~ delete _;
public String Path ~ delete _;
}
TreeNode<DirectoryNode> directoryNames = new TreeNode<DirectoryNode>() ~ DeleteTreeAndChildren!(_);
class Entry
{
public String Name ~ delete _;
public bool IsDirectory;
}
List<Entry> _currentDirContent = new .() ~ DeleteContainerAndItems!(_);
private void BuildDirectoryTree()
{
DeleteTreeAndChildren!(directoryNames);
directoryNames = new TreeNode<DirectoryNode>();
String str = scope .(ContentDirectory);
void AddDirectoryToTree(String path, TreeNode<DirectoryNode> parentNode)
{
DirectoryNode node = new DirectoryNode();
node.Path = new String(path);
node.Name = new String();
Path.GetFileName(node.Path, node.Name);
var newNode = parentNode.AddChild(node);
String filter = scope $"{path}/*";
for (var directory in Directory.Enumerate(filter, .Directories))
{
directory.GetFilePath(str..Clear());
AddDirectoryToTree(str, newNode);
}
}
String filter = scope $"{ContentDirectory}/*";
for (var directory in Directory.Enumerate(filter, .Directories))
{
directory.GetFilePath(str..Clear());
AddDirectoryToTree(str, directoryNames);
}
}
private void BuildCurrentDirectory()
{
ClearAndDeleteItems!(_currentDirContent);
String filter = scope $"{_currentDirectory}/*";
String buffer = scope String();
for (var entry in Directory.Enumerate(filter, .Directories | .Files))
{
entry.GetFilePath(buffer..Clear());
Entry e = new Entry();
e.Name = new String();
Path.GetFileName(buffer, e.Name);
e.IsDirectory = entry.IsDirectory;
_currentDirContent.Add(e);
}
}
private void DrawDirectorySideBar()
{
for(var child in directoryNames.Children)
{
ImGuiPrintEntityTree(child);
}
}
private void ImGuiPrintEntityTree(TreeNode<DirectoryNode> tree)
{
String name = tree.Value.Name;
ImGui.TreeNodeFlags flags = .OpenOnArrow | .SpanAvailWidth;
if(tree.Children.Count == 0)
flags |= .Leaf;
if (tree.Value.Path == _currentDirectory)
{
flags |= .Selected;
}
bool isOpen = ImGui.TreeNodeEx(name, flags, $"{name}");
if (ImGui.IsItemClicked(.Left))
{
if (_currentDirectory != null)
delete _currentDirectory;
_currentDirectory = new String(tree.Value.Path);
}
if(isOpen)
{
for(var child in tree.Children)
{
ImGuiPrintEntityTree(child);
}
ImGui.TreePop();
}
}
private static Vector2 DirectoryItemSize = .(100, 100);
const Vector2 padding = .(24, 24);
private void DrawCurrentDirectory()
{
ImGui.Style* style = ImGui.GetStyle();
float window_visible_x2 = ImGui.GetWindowPos().x + ImGui.GetWindowContentRegionMax().x;
for (var entry in _currentDirContent)
{
ImGui.PushID(entry.Name);
DrawDirectoryItem(entry);
float last_button_x2 = ImGui.GetItemRectMax().x;
float next_button_x2 = last_button_x2 + style.ItemSpacing.x + DirectoryItemSize.X; // Expected position if next button was on same line
if (entry != _currentDirContent.Back && next_button_x2 < window_visible_x2)
ImGui.SameLine();
ImGui.PopID();
}
}
private void DrawDirectoryItem(Entry entry)
{
ImGui.BeginChild("item", (.)DirectoryItemSize);
SubTexture2D image = entry.IsDirectory ? s_FolderTexture : s_FileTexture;
ImGui.PushStyleColor(.Button, ImGui.Vec4(0, 0, 0, 0));
ImGui.ImageButton(image, (.)(DirectoryItemSize - padding));
if (ImGui.BeginDragDropSource())
{
String fullpath = scope $"{_currentDirectory}{Path.DirectorySeparatorChar}{entry.Name}";
ImGui.SetDragDropPayload("CONTENT_BROWSER_ITEM", fullpath.CStr(), (.)fullpath.Length, .Once);
ImGui.EndDragDropSource();
}
if (ImGui.IsItemHovered() && ImGui.IsMouseDoubleClicked(.Left))
{
EntryDoubleClicked(entry);
}
ImGui.PopStyleColor();
ImGui.TextUnformatted(entry.Name);
ImGui.EndChild();
}
private void EntryDoubleClicked(Entry entry)
{
if (entry.IsDirectory)
{
_currentDirectory.Append(Path.DirectorySeparatorChar);
_currentDirectory.Append(entry.Name);
}
}
}
}
@@ -35,12 +35,14 @@ namespace GlitchyEditor.EditWindows
_editor = editor;
}
private ImGui.Vec2 oldViewportSize;
private ImGui.Vec2 oldViewportSize = .(100, 100);
private bool viewPortChanged;
public uint32 SelectedEntityId;
public bool SelectionChanged;
public Vector2 ViewportSize => (Vector2)oldViewportSize;
protected override void InternalShow()
{
ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1));
@@ -88,6 +90,21 @@ namespace GlitchyEditor.EditWindows
//ImGui.Image(_editor.CurrentCamera.RenderTarget.GetViewBinding(0), viewportSize);
//ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize);
}
if (ImGui.BeginDragDropTarget())
{
ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM");
if (payload != null)
{
Log.EngineLogger.Warning("");
StringView path = .((char8*)payload.Data, (int)payload.DataSize);
_editor.RequestOpenScene(this, path);
}
ImGui.EndDragDropTarget();
}
bool gizmoUsed = DrawImGuizmo(viewportSize);
+5
View File
@@ -15,10 +15,12 @@ namespace GlitchyEditor
private EntityHierarchyWindow _entityHierarchyWindow ~ delete _;
private ComponentEditWindow _componentEditWindow ~ delete _;
private SceneViewportWindow _sceneViewportWindow = new .(this) ~ delete _;
private ContentBrowserWindow _contentBrowserWindow = new .() ~ delete _;
public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow;
public ComponentEditWindow ComponentEditWindow => _componentEditWindow;
public SceneViewportWindow SceneViewportWindow => _sceneViewportWindow;
public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow;
public Scene CurrentScene
{
@@ -32,6 +34,8 @@ namespace GlitchyEditor
public EditorCamera* CurrentCamera { get; set; }
public Event<EventHandler<StringView>> RequestOpenScene ~ _.Dispose();
/// Creates a new editor for the given world
public this(Scene scene)
{
@@ -46,6 +50,7 @@ namespace GlitchyEditor
_entityHierarchyWindow.Show();
_componentEditWindow.Show();
_sceneViewportWindow.Show();
_contentBrowserWindow.Show();
}
}
}
+52
View File
@@ -0,0 +1,52 @@
using System;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using GlitchyEngine;
namespace GlitchyEditor
{
class EditorIcons : RefCounted
{
Texture2D _texture ~ _.ReleaseRef();
public SubTexture2D DirectionalLight ~ _.ReleaseRef();
public SubTexture2D Camera ~ _.ReleaseRef();
public SubTexture2D Folder ~ _.ReleaseRef();
public SubTexture2D File ~ _.ReleaseRef();
public SamplerState SamplerState
{
get => _texture.SamplerState;
set => _texture.SamplerState = value;
}
public this(String texturePath, Vector2 iconSize)
{
_texture = new Texture2D(texturePath);
Vector2 pen = .();
DirectionalLight = GetNextGridTexture(ref pen, iconSize);
Camera = GetNextGridTexture(ref pen, iconSize);
Folder = GetNextGridTexture(ref pen, iconSize);
File = GetNextGridTexture(ref pen, iconSize);
}
private SubTexture2D GetNextGridTexture(ref Vector2 pen, Vector2 iconSize)
{
SubTexture2D subTexture = .CreateFromGrid(_texture, pen, iconSize);
pen.X += 1.0f;
if (pen.X >= (_texture.Width / iconSize.X))
{
pen.X = 0;
pen.Y += 1.0f;
}
Log.EngineLogger.AssertDebug(pen.Y <=(_texture.Height / iconSize.Y));
return subTexture;
}
}
}
+42 -17
View File
@@ -50,9 +50,11 @@ namespace GlitchyEditor
EditorCamera _camera ~ _.Dispose();
Texture2D _editorIcons ~ _.ReleaseRef();
/*Texture2D _editorIcons ~ _.ReleaseRef();
SubTexture2D _iconDirectionalLight ~ _.ReleaseRef();
SubTexture2D _iconCamera ~ _.ReleaseRef();
SubTexture2D _iconCamera ~ _.ReleaseRef();*/
EditorIcons _editorIcons ~ _.ReleaseRef();
public this() : base("Example")
{
@@ -62,10 +64,10 @@ namespace GlitchyEditor
_camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1);
_camera.RenderTarget = _cameraTarget;
InitEditor();
NewScene();
InitEditor();
}
private void InitGraphics()
@@ -104,10 +106,16 @@ namespace GlitchyEditor
.(.R8G8B8A8_UNorm))
});
_editorIcons = new Texture2D("Textures/EditorIcons.dds");
_editorIcons = new EditorIcons("Textures/EditorIcons.dds", .(64, 64));
_editorIcons.SamplerState = SamplerStateManager.AnisotropicClamp;
ContentBrowserWindow.s_FolderTexture = _editorIcons.Folder;
ContentBrowserWindow.s_FileTexture = _editorIcons.File;
/*_editorIcons = new Texture2D("Textures/EditorIcons.dds");
_editorIcons.SamplerState = SamplerStateManager.AnisotropicClamp;
_iconDirectionalLight = .CreateFromGrid(_editorIcons, .(0, 0), .(64, 64));
_iconCamera = .CreateFromGrid(_editorIcons, .(1, 0), .(64, 64));
_iconCamera = .CreateFromGrid(_editorIcons, .(1, 0), .(64, 64));*/
}
private void InitEditor()
@@ -115,6 +123,10 @@ namespace GlitchyEditor
_editor = new Editor(_scene);
_editor.SceneViewportWindow.ViewportSizeChangedEvent.Add(new (s, e) => ViewportSizeChanged(s, e));
_editor.CurrentCamera = &_camera;
_editor.RequestOpenScene.Add(new (s, fileName) => {
LoadSceneFile(fileName);
});
}
public override void Update(GameTime gameTime)
@@ -178,7 +190,7 @@ namespace GlitchyEditor
Matrix world = Billboard(transform.WorldTransform);
float alpha = CalculateAlpha(transform.WorldTransform.Translation);
Renderer2D.DrawQuad(world, _iconCamera, ColorRGBA(alpha, alpha, alpha, alpha), .(0, 0, 1, 1), entity.Index);
Renderer2D.DrawQuad(world, _editorIcons.Camera, ColorRGBA(alpha, alpha, alpha, alpha), .(0, 0, 1, 1), entity.Index);
//Renderer2D.DrawQuad(world, _iconCamera, .White, .(0, 0, 1, 1), entity.Index);
}
@@ -199,7 +211,7 @@ namespace GlitchyEditor
Matrix world = Billboard(transform.WorldTransform);
float alpha = CalculateAlpha(transform.WorldTransform.Translation);
Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color.R * alpha, light.SceneLight.Color.G * alpha, light.SceneLight.Color.B * alpha, alpha), .(0, 0, 1, 1), entity.Index);
Renderer2D.DrawQuad(world, _editorIcons.DirectionalLight, ColorRGBA(light.SceneLight.Color.R * alpha, light.SceneLight.Color.G * alpha, light.SceneLight.Color.B * alpha, alpha), .(0, 0, 1, 1), entity.Index);
//Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color, alpha), .(0, 0, 1, 1), entity.Index);
}
}
@@ -366,6 +378,12 @@ namespace GlitchyEditor
private void NewScene()
{
SceneFilePath = null;
delete _scene;
_scene = new Scene();
_editor.CurrentScene = _scene;
var vpSize = _editor.SceneViewportWindow.ViewportSize;
_scene.OnViewportResize((.)vpSize.X, (.)vpSize.Y);
_camera.Position = .(-1.5f, 1.5f, -2.5f);
_camera.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0);
@@ -421,19 +439,26 @@ namespace GlitchyEditor
{
if (val == .OK)
{
SceneFilePath = ofd.FileNames[0];
delete _scene;
_scene = new Scene();
SceneSerializer serializer = scope .(_scene);
serializer.Deserialize(SceneFilePath);
_editor.CurrentScene = _scene;
LoadSceneFile(ofd.FileNames[0]);
}
}
}
/// Loads the given scene file.
private void LoadSceneFile(StringView filename)
{
SceneFilePath = scope String(filename);
delete _scene;
_scene = new Scene();
_editor.CurrentScene = _scene;
var vpSize = _editor.SceneViewportWindow.ViewportSize;
_scene.OnViewportResize((.)vpSize.X, (.)vpSize.Y);
SceneSerializer serializer = scope .(_scene);
serializer.Deserialize(SceneFilePath);
}
private void DrawMainMenuBar()
{
ImGui.BeginMainMenuBar();