mirror of
https://github.com/antopilo/Nuake.git
synced 2026-01-03 14:09:46 +03:00
Multi-scene editing refactor
This commit is contained in:
33
Editor/src/Events/EditorRequests.h
Normal file
33
Editor/src/Events/EditorRequests.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <src/Core/Core.h>
|
||||
#include <src/Core/MulticastDelegate.h>
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Scene;
|
||||
class File;
|
||||
}
|
||||
|
||||
// This is all the commands that the editor can receive from anywhere in the UI
|
||||
class EditorRequests
|
||||
{
|
||||
private:
|
||||
MulticastDelegate<Ref<Nuake::File>> requestLoadScene;
|
||||
|
||||
EditorRequests() = default;
|
||||
~EditorRequests() = default;
|
||||
|
||||
public:
|
||||
static EditorRequests& Get()
|
||||
{
|
||||
static EditorRequests instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public:
|
||||
void RequestLoadScene(Ref<Nuake::File> sceneFile)
|
||||
{
|
||||
requestLoadScene.Broadcast(sceneFile);
|
||||
}
|
||||
|
||||
auto& OnRequestLoadScene() { return requestLoadScene; }
|
||||
};
|
||||
26
Editor/src/Misc/ImGuiTextHelper.cpp
Normal file
26
Editor/src/Misc/ImGuiTextHelper.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "ImGuiTextHelper.h"
|
||||
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
|
||||
void ImGuiTextSTD(const std::string& label, std::string& value)
|
||||
{
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy_s(buffer, value.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputText(label.c_str(), buffer, sizeof(buffer)))
|
||||
{
|
||||
|
||||
value = std::string(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiTextMultiline(const std::string& label, std::string& value)
|
||||
{
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy_s(buffer, value.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputTextMultiline(label.c_str(), buffer, sizeof(buffer)))
|
||||
{
|
||||
value = std::string(buffer);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,6 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <src/Vendors/imgui/imgui.h>
|
||||
|
||||
void ImGuiTextSTD(const std::string& label, std::string& value)
|
||||
{
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy_s(buffer, value.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputText(label.c_str(), buffer, sizeof(buffer)))
|
||||
{
|
||||
|
||||
value = std::string(buffer);
|
||||
}
|
||||
}
|
||||
void ImGuiTextSTD(const std::string& label, std::string& value);
|
||||
|
||||
void ImGuiTextMultiline(const std::string& label, std::string& value)
|
||||
{
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
strncpy_s(buffer, value.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputTextMultiline(label.c_str(), buffer, sizeof(buffer)))
|
||||
{
|
||||
value = std::string(buffer);
|
||||
}
|
||||
}
|
||||
void ImGuiTextMultiline(const std::string& label, std::string& value);
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
#include "src/Rendering/Vulkan/SceneRenderPipeline.h"
|
||||
#include <src/Rendering/Vulkan/DebugCmd.h>
|
||||
|
||||
#include "../Events/EditorRequests.h"
|
||||
|
||||
namespace Nuake {
|
||||
|
||||
ImFont* normalFont;
|
||||
@@ -126,6 +128,8 @@ namespace Nuake {
|
||||
Logger::Log("Creating editor windows", "window", VERBOSE);
|
||||
filesystem = new FileSystemUI(this);
|
||||
|
||||
//floatingFileBrowser = CreateScope<FileSystemUI>(this);
|
||||
|
||||
_WelcomeWindow = new WelcomeWindow(this);
|
||||
_NewProjectWindow = new NewProjectWindow(this);
|
||||
_audioWindow = new AudioWindow();
|
||||
@@ -147,6 +151,9 @@ namespace Nuake {
|
||||
hit = m_TitleBarHovered;
|
||||
});
|
||||
|
||||
EditorRequests& requests = EditorRequests::Get();
|
||||
requests.OnRequestLoadScene().AddRaw(this, &EditorInterface::OnRequestLoadScene);
|
||||
|
||||
Engine::OnSceneLoaded.AddRaw(this, &EditorInterface::OnSceneLoaded);
|
||||
}
|
||||
|
||||
@@ -946,6 +953,16 @@ namespace Nuake {
|
||||
if (ImGui::BeginViewportSideBar("##MainStatusBar", viewport, ImGuiDir_Down, height, window_flags)) {
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::Button("File Browser"))
|
||||
{
|
||||
this->showFloatingFileBrowser = !this->showFloatingFileBrowser;
|
||||
}
|
||||
|
||||
if (ImGui::Button("Logger"))
|
||||
{
|
||||
this->showFloatingLogger = !this->showFloatingLogger;
|
||||
}
|
||||
|
||||
ImGui::Text(m_StatusMessage.c_str());
|
||||
|
||||
ImGui::SameLine();
|
||||
@@ -2112,6 +2129,11 @@ namespace Nuake {
|
||||
}
|
||||
}
|
||||
|
||||
void EditorInterface::OnRequestLoadScene(Ref<File> file)
|
||||
{
|
||||
OpenSceneWindow(file->GetRelativePath());
|
||||
}
|
||||
|
||||
void EditorInterface::OpenPrefabWindow(const std::string& prefabPath)
|
||||
{
|
||||
if (!FileSystem::FileExists(prefabPath))
|
||||
@@ -2500,6 +2522,10 @@ namespace Nuake {
|
||||
if (isLoadingProjectQueue)
|
||||
{
|
||||
_WelcomeWindow->LoadQueuedProject();
|
||||
|
||||
auto project = Engine::GetProject();
|
||||
OpenSceneWindow(project->DefaultScene->Path);
|
||||
|
||||
isLoadingProjectQueue = false;
|
||||
|
||||
auto window = Window::Get();
|
||||
@@ -2741,31 +2767,30 @@ namespace Nuake {
|
||||
ImGuiWindowClass top_level_class;
|
||||
top_level_class.ClassId = ImHashStr("SceneEditor");
|
||||
top_level_class.DockingAllowUnclassed = false;
|
||||
ImGui::DockSpace(ImGui::GetID("SceneEditorDockSpace"), {0, 0}, 0, &top_level_class);
|
||||
|
||||
ImGuiDockNodeFlags flags = ImGuiDockNodeFlags_NoSplit;
|
||||
ImGui::DockSpace(ImGui::GetID("SceneEditorDockSpace"), {0, 0}, flags, &top_level_class);
|
||||
|
||||
ImGuiDockNode* node = (ImGuiDockNode*)GImGui->DockContext.Nodes.GetVoidPtr(ImGui::GetID("SceneEditorDockSpace"));
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 32);
|
||||
if(ImGui::DockNodeBeginAmendTabBar(node))
|
||||
if (node)
|
||||
{
|
||||
ImGui::SetNextItemWidth(48);
|
||||
if (ImGui::BeginTabItem("##logoPadding", 0, ImGuiTabItemFlags_Leading))
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() - 32);
|
||||
if (ImGui::DockNodeBeginAmendTabBar(node))
|
||||
{
|
||||
ImGui::SetNextItemWidth(48);
|
||||
if (ImGui::BeginTabItem("##logoPadding", 0, ImGuiTabItemFlags_Leading))
|
||||
{
|
||||
|
||||
ImGui::EndTabItem();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::DockNodeEndAmendTabBar();
|
||||
}
|
||||
ImGui::DockNodeEndAmendTabBar();
|
||||
}
|
||||
|
||||
ImGui::SetNextWindowClass(&top_level_class);
|
||||
ImGui::Begin("SceneEditor");
|
||||
{
|
||||
ImGuiWindowClass inside_document_class;
|
||||
inside_document_class.ClassId = ImHashStr("SceneEditor1");
|
||||
ImGui::DockSpace(ImGui::GetID("SceneEditorWindowDockspace"), ImGui::GetContentRegionAvail(), ImGuiDockNodeFlags_None, &inside_document_class);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
|
||||
//DrawMenuBar();
|
||||
//DrawMenuBars();
|
||||
|
||||
@@ -2788,12 +2813,16 @@ namespace Nuake {
|
||||
}
|
||||
|
||||
//pInterface.DrawEntitySettings();
|
||||
DrawViewport();
|
||||
DrawSceneTree();
|
||||
SelectionPanel->Draw(Selection);
|
||||
DrawLogger();
|
||||
filesystem->Draw();
|
||||
filesystem->DrawDirectoryExplorer();
|
||||
//DrawViewport();
|
||||
//DrawSceneTree();
|
||||
//SelectionPanel->Draw(Selection);
|
||||
//DrawLogger();
|
||||
//
|
||||
//if (this->showFloatingFileBrowser)
|
||||
//{
|
||||
// filesystem->Draw();
|
||||
// filesystem->DrawDirectoryExplorer();
|
||||
//}
|
||||
|
||||
//auto node = ImGui::DockBuilderGetNode(1);
|
||||
//node->SizeRef = { node->Size.x, 50.0f };
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "SceneEditor/SceneEditorWindow.h"
|
||||
|
||||
|
||||
using namespace NuakeEditor;
|
||||
|
||||
namespace Nuake
|
||||
@@ -71,6 +70,10 @@ namespace Nuake
|
||||
Ref<Material> m_SelectedMaterial;
|
||||
Ref<Directory> m_CurrentDirectory;
|
||||
|
||||
// Filebrowser
|
||||
bool showFloatingFileBrowser;
|
||||
bool showFloatingLogger;
|
||||
|
||||
bool m_IsMaterialSelected = false;
|
||||
|
||||
std::string m_StatusMessage = "";
|
||||
@@ -82,6 +85,8 @@ namespace Nuake
|
||||
|
||||
AudioWindow* _audioWindow;
|
||||
FileSystemUI* filesystem;
|
||||
|
||||
//Scope<FileSystemUI> floatingFileBrowser;
|
||||
bool isNewProject = false;
|
||||
static EditorSelection Selection;
|
||||
EditorSelectionPanel* SelectionPanel;
|
||||
@@ -120,6 +125,7 @@ namespace Nuake
|
||||
void DrawProjectSettings();
|
||||
void Overlay();
|
||||
|
||||
void OnRequestLoadScene(Ref<File> file);
|
||||
void OpenPrefabWindow(const std::string& prefabPath);
|
||||
void OpenSceneWindow(const std::string& scenePath);
|
||||
|
||||
|
||||
@@ -267,7 +267,8 @@ namespace Nuake
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::Scene:
|
||||
shouldOpenScene = true;
|
||||
//shouldOpenScene = true;
|
||||
this->Editor->OpenSceneWindow(file->GetRelativePath());
|
||||
break;
|
||||
case FileType::Solution:
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
@@ -633,18 +634,6 @@ namespace Nuake
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
bool Splitter(bool split_vertically, float thickness, float* size1, float* size2, float min_size1, float min_size2, float splitter_long_axis_size = -1.0f)
|
||||
{
|
||||
using namespace ImGui;
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiID id = window->GetID("##Splitter");
|
||||
ImRect bb;
|
||||
bb.Min = window->DC.CursorPos + (split_vertically ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
|
||||
bb.Max = bb.Min + CalcItemSize(split_vertically ? ImVec2(thickness, splitter_long_axis_size) : ImVec2(splitter_long_axis_size, thickness), 0.0f, 0.0f);
|
||||
return SplitterBehavior(bb, id, split_vertically ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, min_size1, min_size2, 0.0f);
|
||||
}
|
||||
|
||||
void FileSystemUI::DrawContextMenu()
|
||||
{
|
||||
if (!m_HasClickedOnFile && ImGui::IsMouseReleased(1) && ImGui::IsWindowHovered())
|
||||
@@ -833,7 +822,7 @@ namespace Nuake
|
||||
return;
|
||||
|
||||
ImVec2 avail = ImGui::GetContentRegionAvail();
|
||||
Splitter(true, 4.0f, &sz1, &sz2, 100, 8, avail.y);
|
||||
UI::Splitter(true, 4.0f, &sz1, &sz2, 100, 8, avail.y);
|
||||
|
||||
ImVec4* colors = ImGui::GetStyle().Colors;
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, colors[ImGuiCol_TitleBgCollapsed]);
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
const EditorSelection& GetSelection() const { return selection; }
|
||||
void SetSelection(EditorSelection inSelection)
|
||||
{
|
||||
selection = selection;
|
||||
selection = inSelection;
|
||||
OnSelectionChanged.Broadcast(selection);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,17 +2,25 @@
|
||||
|
||||
#include "Widgets/SceneHierarchyWidget.h"
|
||||
#include "Widgets/SelectionPropertyWidget.h"
|
||||
#include "Widgets/LoggerWidget.h"
|
||||
#include "Widgets/ViewportWidget.h"
|
||||
#include "Widgets/FileBrowserWidget.h"
|
||||
|
||||
#include <src/UI/ImUI.h>
|
||||
#include "src/Scene/Scene.h"
|
||||
|
||||
#include "src/UI/ImUI.h"
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
SceneEditorWindow::SceneEditorWindow(Ref<Scene> inScene)
|
||||
SceneEditorWindow::SceneEditorWindow(Ref<Scene> inScene) :
|
||||
editorContext(inScene, inScene->Path),
|
||||
layoutInitialized(false)
|
||||
{
|
||||
editorContext = EditorContext(inScene, inScene->GetName());
|
||||
|
||||
RegisterWidget<SceneHierarchyWidget>();
|
||||
RegisterWidget<SelectionPropertyWidget>();
|
||||
RegisterWidget<LoggerWidget>();
|
||||
RegisterWidget<ViewportWidget>();
|
||||
RegisterWidget<FileBrowserWidget>();
|
||||
}
|
||||
|
||||
void SceneEditorWindow::Update(float ts)
|
||||
@@ -26,27 +34,44 @@ void SceneEditorWindow::Update(float ts)
|
||||
void SceneEditorWindow::Draw()
|
||||
{
|
||||
Ref<Scene> scene = editorContext.GetScene();
|
||||
const std::string sceneName = scene->GetName();
|
||||
const std::string sceneName = scene->Path;
|
||||
|
||||
// This is to prevent other windows of other scene editors to dock
|
||||
ImGuiWindowClass windowClass;
|
||||
windowClass.ClassId = ImHashStr(editorContext.GetWindowClass().data());
|
||||
windowClass.ClassId = ImHashStr("SceneEditor");
|
||||
windowClass.DockingAllowUnclassed = false;
|
||||
ImGui::SetNextWindowClass(&windowClass);
|
||||
|
||||
if (ImGui::Begin(sceneName.c_str()))
|
||||
ImGui::SetNextWindowSizeConstraints({1280, 720}, { FLT_MAX, FLT_MAX });
|
||||
if (ImGui::Begin(std::string(ICON_FA_WINDOW_MAXIMIZE + std::string(" ") + sceneName).c_str()))
|
||||
{
|
||||
ImGuiWindowClass localSceneEditorClass;
|
||||
localSceneEditorClass.ClassId = ImHashStr(sceneName.c_str());
|
||||
std::string dockspaceId = std::string("Dockspace##" + sceneName);
|
||||
ImGui::DockSpace(ImGui::GetID(dockspaceId.c_str()), ImGui::GetContentRegionAvail(), ImGuiDockNodeFlags_None, &localSceneEditorClass);
|
||||
|
||||
std::string dockspaceName = std::string("Dockspace##" + sceneName);
|
||||
|
||||
ImGuiID dockspaceId = ImGui::GetID(dockspaceName.c_str());
|
||||
ImGui::DockSpace(dockspaceId, ImGui::GetContentRegionAvail(), ImGuiDockNodeFlags_None, &localSceneEditorClass);
|
||||
|
||||
for (auto& widget : widgets)
|
||||
{
|
||||
widget->Draw();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
// Build initial docking layout
|
||||
if (!layoutInitialized)
|
||||
{
|
||||
auto dockbottomId = ImGui::DockBuilderSplitNode(dockspaceId, ImGuiDir_Down, 0.3f, nullptr, &dockspaceId);
|
||||
auto dockLeftId = ImGui::DockBuilderSplitNode(dockspaceId, ImGuiDir_Left, 0.3f, nullptr, &dockspaceId);
|
||||
auto dockRightId = ImGui::DockBuilderSplitNode(dockspaceId, ImGuiDir_Right, 0.5f, nullptr, &dockspaceId);
|
||||
|
||||
widgets[0]->DockTo(dockLeftId);
|
||||
widgets[1]->DockTo(dockRightId);
|
||||
widgets[2]->DockTo(dockbottomId);
|
||||
widgets[3]->DockTo(dockspaceId);
|
||||
widgets[4]->DockTo(dockbottomId);
|
||||
layoutInitialized = true;
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ concept DerivedFromEditorWidget = std::derived_from<T, IEditorWidget>;
|
||||
class SceneEditorWindow
|
||||
{
|
||||
private:
|
||||
bool layoutInitialized;
|
||||
std::string windowID; // This is used for imgui docking
|
||||
|
||||
EditorContext editorContext;
|
||||
|
||||
920
Editor/src/Windows/SceneEditor/Widgets/FileBrowserWidget.cpp
Normal file
920
Editor/src/Windows/SceneEditor/Widgets/FileBrowserWidget.cpp
Normal file
@@ -0,0 +1,920 @@
|
||||
#include "FileBrowserWidget.h"
|
||||
|
||||
#include "../../../Misc/PopupHelper.h"
|
||||
#include "../../../Events/EditorRequests.h"
|
||||
|
||||
#include <src/FileSystem/Directory.h>
|
||||
#include <src/FileSystem/File.h>
|
||||
#include <src/Resource/Project.h>
|
||||
#include <src/Core/String.h>
|
||||
|
||||
#include <src/UI/ImUI.h>
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
FileBrowserWidget::FileBrowserWidget(EditorContext& inCtx) : IEditorWidget(inCtx)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FileBrowserWidget::Update(float ts)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FileBrowserWidget::Draw()
|
||||
{
|
||||
if (BeginWidgetWindow("File Browser"))
|
||||
{
|
||||
Ref<Nuake::Directory> rootDirectory = FileSystem::GetFileTree();
|
||||
|
||||
auto availableSpace = ImGui::GetContentRegionAvail();
|
||||
UI::Splitter(true, 4.0f, &splitterSizeLeft, &splitterSizeRight, 100, 8, availableSpace.y);
|
||||
|
||||
ImVec4* colors = ImGui::GetStyle().Colors;
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, colors[ImGuiCol_TitleBgCollapsed]);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 8);
|
||||
|
||||
if (ImGui::BeginChild("Tree", ImVec2(splitterSizeLeft, availableSpace.y), true))
|
||||
{
|
||||
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_SpanAvailWidth |
|
||||
ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_DefaultOpen |
|
||||
ImGuiTreeNodeFlags_FramePadding;
|
||||
|
||||
bool isSelected = this->currentDirectory == FileSystem::RootDirectory;
|
||||
if (isSelected)
|
||||
{
|
||||
base_flags |= ImGuiTreeNodeFlags_Selected;
|
||||
}
|
||||
|
||||
// Header
|
||||
{
|
||||
UIFont boldFont = UIFont(Fonts::Bold);
|
||||
bool open = ImGui::TreeNodeEx("PROJECT", base_flags);
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
this->currentDirectory = FileSystem::RootDirectory;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw tree
|
||||
for (auto& d : rootDirectory->Directories)
|
||||
{
|
||||
DrawFiletree(d);
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// Build file path buttons
|
||||
auto paths = std::vector<Ref<Nuake::Directory>>();
|
||||
{
|
||||
Ref<Nuake::Directory> currentParent = currentDirectory;
|
||||
paths.push_back(currentDirectory);
|
||||
|
||||
// Recursively build the path to the root
|
||||
while (currentParent != nullptr)
|
||||
{
|
||||
paths.push_back(currentParent);
|
||||
currentParent = currentParent->Parent;
|
||||
}
|
||||
}
|
||||
|
||||
availableSpace = ImGui::GetContentRegionAvail();
|
||||
if (ImGui::BeginChild("Wrapper", availableSpace))
|
||||
{
|
||||
availableSpace.y = 30;
|
||||
|
||||
if (ImGui::BeginChild("Path", availableSpace, true))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, { 2, 4 });
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
|
||||
const auto buttonSize = ImVec2(26, 26);
|
||||
|
||||
// Refresh button
|
||||
std::string refreshIcon = ICON_FA_SYNC_ALT;
|
||||
if (ImGui::Button((refreshIcon).c_str(), buttonSize))
|
||||
{
|
||||
// RefreshFileBrowser();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
const auto cursorStart = ImGui::GetCursorPosX();
|
||||
{ // Go back
|
||||
if (ImGui::Button((std::string(ICON_FA_ANGLE_LEFT)).c_str(), buttonSize))
|
||||
{
|
||||
if (currentDirectory != FileSystem::RootDirectory)
|
||||
{
|
||||
currentDirectory = currentDirectory->Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
const auto cursorEnd = ImGui::GetCursorPosX();
|
||||
const auto buttonWidth = cursorEnd - cursorStart;
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_ANGLE_RIGHT)).c_str(), buttonSize))
|
||||
{
|
||||
if (editorContext.GetSelection().Type == EditorSelectionType::Directory)
|
||||
{
|
||||
currentDirectory = editorContext.GetSelection().Directory;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t numButtonAfterPathBrowser = 2;
|
||||
const uint32_t searchBarSize = 6;
|
||||
ImGui::SameLine();
|
||||
|
||||
// Draw path buttons
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, colors[ImGuiCol_TitleBgCollapsed]);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
|
||||
ImGui::BeginChild("pathBrowser", ImVec2((ImGui::GetContentRegionAvail().x - (numButtonAfterPathBrowser * buttonWidth * searchBarSize)) - 4.0, 24));
|
||||
for (int i = paths.size() - 1; i > 0; i--)
|
||||
{
|
||||
if (i != paths.size())
|
||||
{
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
std::string pathLabel;
|
||||
if (i == paths.size() - 1)
|
||||
{
|
||||
pathLabel = "Project files";
|
||||
}
|
||||
else
|
||||
{
|
||||
pathLabel = paths[i]->Name;
|
||||
}
|
||||
|
||||
if (ImGui::Button(pathLabel.c_str()))
|
||||
{
|
||||
currentDirectory = paths[i];
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("/");
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// Search bar
|
||||
ImGui::BeginChild("searchBar", ImVec2(ImGui::GetContentRegionAvail().x - (numButtonAfterPathBrowser * buttonWidth), 24));
|
||||
char buffer[256];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
std::strncpy(buffer, searchQuery.c_str(), sizeof(buffer));
|
||||
if (ImGui::InputTextEx("##Search", "Asset search & filter ..", buffer, sizeof(buffer), ImVec2(ImGui::GetContentRegionAvail().x, 24), ImGuiInputTextFlags_EscapeClearsAll))
|
||||
{
|
||||
searchQuery = std::string(buffer);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_FOLDER_OPEN)).c_str(), buttonSize))
|
||||
{
|
||||
OS::OpenIn(currentDirectory->FullPath);
|
||||
}
|
||||
ImGui::PopStyleColor(); // Button color
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
ImGui::GetWindowDrawList()->AddLine(ImVec2(ImGui::GetCursorPosX(), ImGui::GetCursorPosY()), ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetCursorPosY()), IM_COL32(255, 0, 0, 255), 1.0f);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
|
||||
availableSpace = ImGui::GetContentRegionAvail();
|
||||
|
||||
bool child = ImGui::BeginChild("Content", availableSpace);
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::SameLine();
|
||||
if (child)
|
||||
{
|
||||
int width = availableSpace.x;
|
||||
ImVec2 buttonSize = ImVec2(80, 80);
|
||||
int amount = (int)(width / 110);
|
||||
if (amount <= 0) amount = 1;
|
||||
|
||||
int i = 1; // current amount of item per row.
|
||||
if (ImGui::BeginTable("ssss", amount))
|
||||
{
|
||||
// Button to go up a level.
|
||||
//if (m_CurrentDirectory && m_CurrentDirectory != FileSystem::RootDirectory && m_CurrentDirectory->Parent)
|
||||
//{
|
||||
// ImGui::TableNextColumn();
|
||||
// if (ImGui::Button("..", buttonSize))
|
||||
// m_CurrentDirectory = m_CurrentDirectory->Parent;
|
||||
// i++;
|
||||
//}
|
||||
|
||||
if (currentDirectory && currentDirectory->Directories.size() > 0)
|
||||
{
|
||||
for (Ref<Nuake::Directory>& d : currentDirectory->Directories)
|
||||
{
|
||||
if (d->GetName() == "bin" || d->GetName() == ".vs" || d->GetName() == "obj")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Nuake::String::Sanitize(d->Name).find(Nuake::String::Sanitize(searchQuery)) != std::string::npos)
|
||||
{
|
||||
if (i + 1 % amount != 0)
|
||||
ImGui::TableNextColumn();
|
||||
else
|
||||
ImGui::TableNextRow();
|
||||
|
||||
DrawDirectory(d, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentDirectory && currentDirectory->Files.size() > 0)
|
||||
{
|
||||
for (auto& f : currentDirectory->Files)
|
||||
{
|
||||
if (searchQuery.empty() || f->GetName().find(String::Sanitize(searchQuery)) != std::string::npos)
|
||||
{
|
||||
if (f->GetFileType() == FileType::Unknown || f->GetFileType() == FileType::Assembly)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i + 1 % amount != 0 || i == 1)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
}
|
||||
|
||||
DrawFile(f, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//DrawContextMenu();
|
||||
|
||||
//m_HasClickedOnFile = false;
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void FileBrowserWidget::DrawFiletree(Ref<Nuake::Directory> dir)
|
||||
{
|
||||
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick |
|
||||
ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_FramePadding;
|
||||
|
||||
if (currentDirectory == dir)
|
||||
{
|
||||
base_flags |= ImGuiTreeNodeFlags_Selected;
|
||||
}
|
||||
|
||||
if (dir->Directories.size() <= 0)
|
||||
{
|
||||
base_flags |= ImGuiTreeNodeFlags_Leaf;
|
||||
}
|
||||
|
||||
std::string icon = ICON_FA_FOLDER;
|
||||
bool open = ImGui::TreeNodeEx((icon + " " + dir->Name.c_str()).c_str(), base_flags);
|
||||
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
currentDirectory = dir;
|
||||
}
|
||||
|
||||
if (open)
|
||||
{
|
||||
for (auto& d : dir->Directories)
|
||||
{
|
||||
DrawFiletree(d);
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowserWidget::DrawDirectory(Ref<Nuake::Directory> directory, uint32_t drawId)
|
||||
{
|
||||
ImGui::PushFont(FontManager::GetFont(Icons));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
const char* icon = ICON_FA_FOLDER;
|
||||
const std::string id = std::string("##") + directory->Name;
|
||||
|
||||
ImVec2 prevCursor = ImGui::GetCursorPos();
|
||||
ImVec2 prevScreenPos = ImGui::GetCursorScreenPos();
|
||||
const bool selected = ImGui::Selectable(id.c_str(), editorContext.GetSelection().Directory == directory, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(100, 150));
|
||||
const std::string hoverMenuId = std::string("item_hover_menu") + std::to_string(drawId);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseReleased(1))
|
||||
{
|
||||
ImGui::OpenPopup(hoverMenuId.c_str());
|
||||
//m_HasClickedOnFile = true;
|
||||
}
|
||||
|
||||
const std::string renameId = "Rename" + std::string("##") + hoverMenuId;
|
||||
bool shouldRename = false;
|
||||
|
||||
const std::string deleteId = "Delete" + std::string("##") + hoverMenuId;
|
||||
bool shouldDelete = false;
|
||||
|
||||
if (selected)
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
currentDirectory = directory;
|
||||
}
|
||||
|
||||
//Editor->Selection = EditorSelection(directory);
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip(directory->Name.c_str());
|
||||
|
||||
|
||||
ImGui::SetCursorPos(prevCursor);
|
||||
ImGui::Image((ImTextureID)TextureManager::Get()->GetTexture2("Resources/Images/folder_icon.png")->GetImGuiDescriptorSet(), ImVec2(100, 100));
|
||||
|
||||
auto imguiStyle = ImGui::GetStyle();
|
||||
|
||||
ImVec2 startOffset = ImVec2(imguiStyle.CellPadding.x / 2.0f, 0);
|
||||
ImVec2 offsetEnd = ImVec2(startOffset.x, imguiStyle.CellPadding.y / 2.0f);
|
||||
ImU32 rectColor = IM_COL32(255, 255, 255, 16);
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 150) + offsetEnd, rectColor, 1.0f);
|
||||
std::string visibleName = directory->Name;
|
||||
const uint32_t MAX_CHAR_NAME = 34;
|
||||
if (directory->Name.size() > MAX_CHAR_NAME)
|
||||
{
|
||||
visibleName = std::string(directory->Name.begin(), directory->Name.begin() + MAX_CHAR_NAME - 3) + "...";
|
||||
}
|
||||
|
||||
ImGui::TextWrapped(visibleName.c_str());
|
||||
|
||||
ImGui::SetCursorPosY(prevCursor.y + 150 - ImGui::GetTextLineHeight());
|
||||
ImGui::TextColored({ 1, 1, 1, 0.5f }, "Folder");
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
|
||||
if (ImGui::BeginPopup(hoverMenuId.c_str()))
|
||||
{
|
||||
if (ImGui::MenuItem("Open"))
|
||||
{
|
||||
currentDirectory = directory;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("Copy"))
|
||||
{
|
||||
if (ImGui::MenuItem("Full Path"))
|
||||
{
|
||||
OS::CopyToClipboard(directory->FullPath);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Directory Name"))
|
||||
{
|
||||
OS::CopyToClipboard(String::Split(directory->Name, '/')[0]);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Delete"))
|
||||
{
|
||||
shouldDelete = true;
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Rename"))
|
||||
{
|
||||
shouldRename = true;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Show in File Explorer"))
|
||||
{
|
||||
OS::OpenIn(directory->FullPath);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Rename Popup
|
||||
|
||||
if (shouldRename)
|
||||
{
|
||||
//renameTempValue = directory->Name;
|
||||
//PopupHelper::OpenPopup(renameId);
|
||||
}
|
||||
|
||||
//if (PopupHelper::DefineTextDialog(renameId, renameTempValue))
|
||||
//{
|
||||
// if (OS::RenameDirectory(directory, renameTempValue) != 0)
|
||||
// {
|
||||
// Logger::Log("Cannot rename directory: " + renameTempValue, "editor", CRITICAL);
|
||||
// }
|
||||
// //RefreshFileBrowser();
|
||||
// renameTempValue = "";
|
||||
//}
|
||||
|
||||
// Delete Popup
|
||||
|
||||
if (shouldDelete)
|
||||
{
|
||||
PopupHelper::OpenPopup(deleteId);
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineConfirmationDialog(deleteId, " Are you sure you want to delete the folder and all its children?\n This action cannot be undone, and all data within the folder \n will be permanently lost."))
|
||||
{
|
||||
if (FileSystem::DeleteFolder(directory->FullPath) != 0)
|
||||
{
|
||||
Logger::Log("Failed to remove directory: " + directory->Name, "editor", CRITICAL);
|
||||
}
|
||||
//RefreshFileBrowser();
|
||||
}
|
||||
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
void FileBrowserWidget::DrawFile(Ref<Nuake::File> file, uint32_t drawId)
|
||||
{
|
||||
//ImGui::PushFont(EditorInterface::bigIconFont);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, { 0.f, 0.f });
|
||||
std::string fileExtension = file->GetExtension();
|
||||
|
||||
ImVec2 prevCursor = ImGui::GetCursorPos();
|
||||
ImVec2 prevScreenPos = ImGui::GetCursorScreenPos();
|
||||
std::string id = std::string("##") + file->GetAbsolutePath();
|
||||
const bool selected = ImGui::Selectable(id.c_str(), editorContext.GetSelection().File == file, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(100, 150));
|
||||
|
||||
const std::string hoverMenuId = std::string("item_hover_menu") + std::to_string(drawId);
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseReleased(1))
|
||||
{
|
||||
ImGui::OpenPopup(hoverMenuId.c_str());
|
||||
//m_HasClickedOnFile = true;
|
||||
}
|
||||
|
||||
bool shouldOpenScene = false;
|
||||
if (selected)
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
switch (file->GetFileType())
|
||||
{
|
||||
case FileType::Map:
|
||||
OS::OpenTrenchbroomMap(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::NetScript:
|
||||
case FileType::UI:
|
||||
case FileType::CSS:
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::Scene:
|
||||
//shouldOpenScene = true;
|
||||
EditorRequests::Get().RequestLoadScene(file);
|
||||
//this->Editor->OpenSceneWindow(file->GetRelativePath());
|
||||
break;
|
||||
case FileType::Solution:
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
break;
|
||||
case FileType::Prefab:
|
||||
//this->Editor->OpenPrefabWindow(file->GetRelativePath());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
editorContext.SetSelection(EditorSelection(file));
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip(file->GetName().c_str());
|
||||
|
||||
if (ImGui::BeginDragDropSource())
|
||||
{
|
||||
char pathBuffer[256];
|
||||
std::strncpy(pathBuffer, file->GetAbsolutePath().c_str(), sizeof(pathBuffer));
|
||||
std::string dragType;
|
||||
if (fileExtension == ".wren")
|
||||
{
|
||||
dragType = "_Script";
|
||||
}
|
||||
else if (fileExtension == ".cs")
|
||||
{
|
||||
dragType = "_NetScript";
|
||||
}
|
||||
else if (fileExtension == ".map")
|
||||
{
|
||||
dragType = "_Map";
|
||||
}
|
||||
else if (fileExtension == ".material")
|
||||
{
|
||||
dragType = "_Material";
|
||||
}
|
||||
else if (fileExtension == ".nkmesh" || fileExtension == ".obj" || fileExtension == ".mdl" || fileExtension == ".gltf" || fileExtension == ".md3" || fileExtension == ".fbx" || fileExtension == ".glb")
|
||||
{
|
||||
dragType = "_Model";
|
||||
}
|
||||
else if (fileExtension == ".interface")
|
||||
{
|
||||
dragType = "_Interface";
|
||||
}
|
||||
else if (fileExtension == ".prefab")
|
||||
{
|
||||
dragType = "_Prefab";
|
||||
}
|
||||
else if (fileExtension == ".png" || fileExtension == ".jpg")
|
||||
{
|
||||
dragType = "_Image";
|
||||
}
|
||||
else if (fileExtension == ".wav" || fileExtension == ".ogg")
|
||||
{
|
||||
dragType = "_AudioFile";
|
||||
}
|
||||
else if (fileExtension == ".html")
|
||||
{
|
||||
dragType = "_UIFile";
|
||||
}
|
||||
else if (fileExtension == ".sky")
|
||||
{
|
||||
dragType = "_SkyFile";
|
||||
}
|
||||
else if (fileExtension == ".env")
|
||||
{
|
||||
dragType = "_EnvFile";
|
||||
}
|
||||
|
||||
ImGui::SetDragDropPayload(dragType.c_str(), (void*)(pathBuffer), sizeof(pathBuffer));
|
||||
ImGui::Text(file->GetName().c_str());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
|
||||
Ref<VulkanImage> textureImage = TextureManager::Get()->GetTexture2("Resources/Images/file_icon.png");
|
||||
|
||||
const auto textureMgr = TextureManager::Get();
|
||||
const auto fileType = file->GetFileType();
|
||||
if (fileType == FileType::Material)
|
||||
{
|
||||
//auto image = ThumbnailManager::Get().GetThumbnail(file->GetRelativePath());
|
||||
//if (image)
|
||||
//{
|
||||
// textureImage = image;
|
||||
//}
|
||||
}
|
||||
else if (fileType == FileType::Image)
|
||||
{
|
||||
const std::string path = file->GetAbsolutePath();
|
||||
textureImage = textureMgr->GetTexture2(path);
|
||||
}
|
||||
else if (fileType == FileType::Project)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/project_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::NetScript)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/csharp_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Scene)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/scene_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Script)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/script_file_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Audio)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/audio_file_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Prefab)
|
||||
{
|
||||
//auto image = ThumbnailManager::Get().GetThumbnail(file->GetRelativePath());
|
||||
//if (image)
|
||||
//{
|
||||
// textureImage = image;
|
||||
//}
|
||||
}
|
||||
else if (fileType == FileType::Mesh)
|
||||
{
|
||||
//auto image = ThumbnailManager::Get().GetThumbnail(file->GetRelativePath());
|
||||
//if (image)
|
||||
//{
|
||||
// textureImage = image;
|
||||
//}
|
||||
}
|
||||
else if (fileType == FileType::Solution)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/sln_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Map)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/trenchbroom_icon.png");
|
||||
}
|
||||
else if (fileType == FileType::Env)
|
||||
{
|
||||
textureImage = textureMgr->GetTexture2("Resources/Images/env_file_icon.png");
|
||||
}
|
||||
|
||||
ImGui::SetCursorPos(prevCursor);
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(textureImage->GetImGuiDescriptorSet()), ImVec2(100, 100));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
auto& imguiStyle = ImGui::GetStyle();
|
||||
|
||||
ImVec2 startOffset = ImVec2(imguiStyle.CellPadding.x / 2.0f, 0);
|
||||
ImVec2 offsetEnd = ImVec2(startOffset.x, imguiStyle.CellPadding.y / 2.0f);
|
||||
ImU32 rectColor = IM_COL32(255, 255, 255, 16);
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 150) + offsetEnd, rectColor, 1.0f);
|
||||
|
||||
ImU32 rectColor2 = UI::PrimaryCol;
|
||||
Color fileTypeColor = GetColorByFileType(file->GetFileType());
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 101) + offsetEnd, IM_COL32(fileTypeColor.r * 255.f, fileTypeColor.g * 255.f, fileTypeColor.b * 255.f, fileTypeColor.a * 255.f), 0.0f);
|
||||
|
||||
std::string visibleName = file->GetName();
|
||||
const uint32_t MAX_CHAR_NAME = 32;
|
||||
if (file->GetName().size() >= MAX_CHAR_NAME)
|
||||
{
|
||||
visibleName = std::string(visibleName.begin(), visibleName.begin() + MAX_CHAR_NAME - 3) + "...";
|
||||
}
|
||||
|
||||
ImGui::TextWrapped(visibleName.c_str());
|
||||
|
||||
ImGui::SetCursorPosY(prevCursor.y + 150 - ImGui::GetTextLineHeight());
|
||||
ImGui::TextColored({ 1, 1, 1, 0.5f }, file->GetFileTypeAsString().c_str());
|
||||
|
||||
//if (fileExtension == ".png" || fileExtension == ".jpg")
|
||||
//{
|
||||
//
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// const char* icon = ICON_FA_FILE;
|
||||
// if (fileExtension == ".shader" || fileExtension == ".wren")
|
||||
// icon = ICON_FA_FILE_CODE;
|
||||
// if (fileExtension == ".map")
|
||||
// icon = ICON_FA_BROOM;
|
||||
// if (fileExtension == ".ogg" || fileExtension == ".mp3" || fileExtension == ".wav")
|
||||
// icon = ICON_FA_FILE_AUDIO;
|
||||
// if (fileExtension == ".gltf" || fileExtension == ".obj")
|
||||
// icon = ICON_FA_FILE_IMAGE;
|
||||
//
|
||||
// std::string fullName = icon + std::string("##") + file->GetAbsolutePath();
|
||||
//
|
||||
// bool pressed = false;
|
||||
// if (fileExtension == ".material")
|
||||
// {
|
||||
// ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
// pressed = ImGui::ImageButton(fullName.c_str(), (void*)ThumbnailManager::Get().GetThumbnail(file-//>GetRelativePath())->GetID(), ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0));
|
||||
// ImGui::PopStyleVar();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
// pressed = ImGui::Button(fullName.c_str(), ImVec2(100, 100));
|
||||
// ImGui::PopStyleVar();
|
||||
// }
|
||||
//
|
||||
if (editorContext.GetSelection().File == file && editorContext.GetSelection().File->GetFileType() != FileType::Prefab)
|
||||
{
|
||||
//ThumbnailManager::Get().MarkThumbnailAsDirty(file->GetRelativePath());
|
||||
}
|
||||
|
||||
// if(pressed)
|
||||
// {
|
||||
// Editor->Selection = EditorSelection(file);
|
||||
// }
|
||||
//
|
||||
// if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
|
||||
// {
|
||||
// OS::OpenTrenchbroomMap(file->GetAbsolutePath());
|
||||
// }
|
||||
//}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
const std::string openSceneId = "Open Scene" + std::string("##") + hoverMenuId;
|
||||
|
||||
|
||||
const std::string renameId = "Rename" + std::string("##") + hoverMenuId;
|
||||
bool shouldRename = false;
|
||||
|
||||
const std::string deleteId = "Delete" + std::string("##") + hoverMenuId;
|
||||
bool shouldDelete = false;
|
||||
|
||||
if (ImGui::BeginPopup(hoverMenuId.c_str()))
|
||||
{
|
||||
if (file->GetExtension() != ".scene")
|
||||
{
|
||||
if (ImGui::MenuItem("Open in Editor"))
|
||||
{
|
||||
OS::OpenIn(file->GetAbsolutePath());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::MenuItem("Load Scene"))
|
||||
{
|
||||
shouldOpenScene = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("Copy"))
|
||||
{
|
||||
if (ImGui::MenuItem("Full Path"))
|
||||
{
|
||||
OS::CopyToClipboard(file->GetAbsolutePath());
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("File Name"))
|
||||
{
|
||||
OS::CopyToClipboard(file->GetName());
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (file->GetExtension() != ".project")
|
||||
{
|
||||
if (ImGui::MenuItem("Delete"))
|
||||
{
|
||||
shouldDelete = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 1, 1, 0.2f));
|
||||
ImGui::MenuItem("Delete");
|
||||
ImGui::PopStyleColor();
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
ImGui::TextUnformatted("The file you're trying to delete is currently loaded by the game engine.");
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
if (file->GetExtension() == ".wad")
|
||||
{
|
||||
if (ImGui::MenuItem("Convert to Materials"))
|
||||
{
|
||||
//Nuake::ExtractWad(file->GetAbsolutePath(), FileSystem::Root);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Rename"))
|
||||
{
|
||||
shouldRename = true;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Show in File Explorer"))
|
||||
{
|
||||
OS::ShowInFileExplorer(file->GetAbsolutePath());
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Open Scene Popup
|
||||
|
||||
if (shouldOpenScene)
|
||||
{
|
||||
PopupHelper::OpenPopup(openSceneId);
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineConfirmationDialog(openSceneId, " Open the scene? \n Changes will not be saved."))
|
||||
{
|
||||
Ref<Scene> scene = Scene::New();
|
||||
const std::string projectPath = file->GetAbsolutePath();
|
||||
if (!scene->Deserialize(json::parse(FileSystem::ReadFile(projectPath, true))))
|
||||
{
|
||||
Logger::Log("Failed loading scene: " + projectPath, "editor", CRITICAL);
|
||||
ImGui::PopFont();
|
||||
return;
|
||||
}
|
||||
|
||||
scene->Path = FileSystem::AbsoluteToRelative(projectPath);
|
||||
Engine::SetCurrentScene(scene);
|
||||
}
|
||||
|
||||
// Rename Popup
|
||||
|
||||
if (shouldRename)
|
||||
{
|
||||
//renameTempValue = file->GetName();
|
||||
PopupHelper::OpenPopup(renameId);
|
||||
}
|
||||
|
||||
//if (PopupHelper::DefineTextDialog(renameId, renameTempValue))
|
||||
//{
|
||||
// if (OS::RenameFile(file, renameTempValue) != 0)
|
||||
// {
|
||||
// Logger::Log("Cannot rename file: " + renameTempValue, "editor", CRITICAL);
|
||||
// }
|
||||
// RefreshFileBrowser();
|
||||
// renameTempValue = "";
|
||||
//}
|
||||
|
||||
// Delete Popup
|
||||
|
||||
if (shouldDelete)
|
||||
{
|
||||
PopupHelper::OpenPopup(deleteId);
|
||||
}
|
||||
|
||||
if (PopupHelper::DefineConfirmationDialog(deleteId, " Are you sure you want to delete the file?\n This action cannot be undone, and all data \n will be permanently lost."))
|
||||
{
|
||||
if (FileSystem::DeleteFileFromPath(file->GetAbsolutePath()) != 0)
|
||||
{
|
||||
Logger::Log("Failed to remove file: " + file->GetRelativePath(), "editor", CRITICAL);
|
||||
}
|
||||
//RefreshFileBrowser();
|
||||
}
|
||||
|
||||
//ImGui::PopFont();
|
||||
}
|
||||
|
||||
Color FileBrowserWidget::GetColorByFileType(Nuake::FileType fileType)
|
||||
{
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case Nuake::FileType::Unknown:
|
||||
break;
|
||||
case Nuake::FileType::Image:
|
||||
break;
|
||||
case Nuake::FileType::Material:
|
||||
break;
|
||||
case Nuake::FileType::Mesh:
|
||||
break;
|
||||
case Nuake::FileType::Script:
|
||||
return { 1.0, 0.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::NetScript:
|
||||
return { 1.0, 0.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::Project:
|
||||
return Engine::GetProject()->Settings.PrimaryColor;
|
||||
break;
|
||||
case Nuake::FileType::Prefab:
|
||||
break;
|
||||
case Nuake::FileType::Scene:
|
||||
return { 0, 1.0f, 1.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::Wad:
|
||||
break;
|
||||
case Nuake::FileType::Map:
|
||||
return { 0.0, 1.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::Assembly:
|
||||
break;
|
||||
case Nuake::FileType::Solution:
|
||||
break;
|
||||
case Nuake::FileType::Audio:
|
||||
return { 0.0, 0.0, 1.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::UI:
|
||||
return { 1.0, 1.0, 0.0, 1.0 };
|
||||
break;
|
||||
case Nuake::FileType::CSS:
|
||||
return { 1.0, 0.0, 1.0, 1.0 };
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Color(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
39
Editor/src/Windows/SceneEditor/Widgets/FileBrowserWidget.h
Normal file
39
Editor/src/Windows/SceneEditor/Widgets/FileBrowserWidget.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Core/Core.h"
|
||||
#include "src/Core/Maths.h"
|
||||
#include "src/FileSystem/FileTypes.h"
|
||||
|
||||
#include "IEditorWidget.h"
|
||||
|
||||
namespace Nuake
|
||||
{
|
||||
class Directory;
|
||||
class File;
|
||||
}
|
||||
|
||||
class FileBrowserWidget : public IEditorWidget
|
||||
{
|
||||
private:
|
||||
float splitterSizeLeft = 300.0f;
|
||||
float splitterSizeRight = 300.0f;
|
||||
|
||||
Ref<Nuake::Directory> currentDirectory;
|
||||
|
||||
std::string searchQuery;
|
||||
|
||||
public:
|
||||
FileBrowserWidget(EditorContext& inCtx);
|
||||
~FileBrowserWidget() = default;
|
||||
|
||||
public:
|
||||
void Update(float ts) override;
|
||||
void Draw() override;
|
||||
|
||||
void DrawFiletree(Ref<Nuake::Directory> dir);
|
||||
void DrawDirectory(Ref<Nuake::Directory> dir, uint32_t drawId);
|
||||
void DrawFile(Ref<Nuake::File> file, uint32_t drawId);
|
||||
|
||||
Nuake::Color GetColorByFileType(Nuake::FileType fileType);
|
||||
|
||||
};
|
||||
@@ -9,6 +9,9 @@ class IEditorWidget
|
||||
protected:
|
||||
EditorContext& editorContext;
|
||||
|
||||
private:
|
||||
std::string widgetName;
|
||||
|
||||
public:
|
||||
IEditorWidget(EditorContext& inContext) : editorContext(inContext) {}
|
||||
virtual ~IEditorWidget() {};
|
||||
@@ -17,6 +20,11 @@ public:
|
||||
virtual void Update(float ts) = 0;
|
||||
virtual void Draw() = 0;
|
||||
|
||||
void DockTo(uint32_t dockId)
|
||||
{
|
||||
ImGui::DockBuilderDockWindow(widgetName.c_str(), dockId);
|
||||
}
|
||||
|
||||
bool BeginWidgetWindow(const std::string_view& name)
|
||||
{
|
||||
return BeginWidgetWindow(name.data());
|
||||
@@ -29,7 +37,7 @@ public:
|
||||
windowClass.DockingAllowUnclassed = false;
|
||||
ImGui::SetNextWindowClass(&windowClass);
|
||||
|
||||
std::string nameStr = std::string(name) + "##" + editorContext.GetScene()->GetName();
|
||||
return ImGui::Begin(nameStr.c_str());
|
||||
widgetName = std::string(name) + "##" + editorContext.GetScene()->Path;
|
||||
return ImGui::Begin(widgetName.c_str());
|
||||
}
|
||||
};
|
||||
210
Editor/src/Windows/SceneEditor/Widgets/LoggerWidget.cpp
Normal file
210
Editor/src/Windows/SceneEditor/Widgets/LoggerWidget.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
#include "LoggerWidget.h"
|
||||
|
||||
#include "src/Core/Logger.h"
|
||||
|
||||
#include "src/UI/ImUI.h"
|
||||
|
||||
#include "src/Resource/Project.h"
|
||||
#include "Engine.h"
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
void LoggerWidget::Update(float ts)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LoggerWidget::Draw()
|
||||
{
|
||||
if (BeginWidgetWindow("Logger"))
|
||||
{
|
||||
if (ImGui::Button("Clear", ImVec2(60, 28)))
|
||||
{
|
||||
Logger::ClearLogs();
|
||||
//SetStatusMessage("Logs cleared.");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(ICON_FA_FILTER, ImVec2(30, 28)))
|
||||
{
|
||||
ImGui::OpenPopup("filter_popup");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
bool isEnabled = LogErrors;
|
||||
if (ImGui::BeginPopup("filter_popup"))
|
||||
{
|
||||
ImGui::SeparatorText("Filters");
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
|
||||
|
||||
if (isEnabled)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_BAN) + " Error").c_str()))
|
||||
{
|
||||
LogErrors = !LogErrors;
|
||||
}
|
||||
|
||||
UI::Tooltip("Display Errors");
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
isEnabled = LogWarnings;
|
||||
if (isEnabled)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_EXCLAMATION_TRIANGLE) + " Warning").c_str()))
|
||||
{
|
||||
LogWarnings = !LogWarnings;
|
||||
}
|
||||
|
||||
UI::Tooltip("Display Warnings");
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
isEnabled = LogDebug;
|
||||
if (isEnabled)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_INFO) + " Info").c_str()))
|
||||
{
|
||||
LogDebug = !LogDebug;
|
||||
}
|
||||
|
||||
UI::Tooltip("Display Verbose");
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
isEnabled = AutoScroll;
|
||||
if (isEnabled)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button(ICON_FA_ARROW_DOWN, ImVec2(30, 28)))
|
||||
{
|
||||
AutoScroll = !AutoScroll;
|
||||
}
|
||||
|
||||
UI::Tooltip("Auto-Scroll");
|
||||
if (isEnabled)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
//ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
//if (ImGui::BeginChild("Log window", ImGui::GetContentRegionAvail(), false))
|
||||
//{
|
||||
//ImGui::PopStyleVar();
|
||||
ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Hideable;
|
||||
if (ImGui::BeginTable("LogTable", 3, flags))
|
||||
{
|
||||
ImGui::TableSetupColumn("Severity", ImGuiTableColumnFlags_WidthFixed, 64.0f);
|
||||
ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_WidthFixed, 64.0f);
|
||||
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch, 1.0f);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(4, 4));
|
||||
|
||||
for (auto& l : Logger::GetLogs())
|
||||
{
|
||||
if (l.type == LOG_TYPE::VERBOSE && !LogDebug)
|
||||
continue;
|
||||
if (l.type == LOG_TYPE::WARNING && !LogWarnings)
|
||||
continue;
|
||||
if (l.type == LOG_TYPE::CRITICAL && !LogErrors)
|
||||
continue;
|
||||
|
||||
std::string severityText = "";
|
||||
if (l.type == LOG_TYPE::VERBOSE)
|
||||
severityText = "verbose";
|
||||
else if (l.type == LOG_TYPE::WARNING)
|
||||
severityText = "warning";
|
||||
else
|
||||
severityText = "critical";
|
||||
|
||||
ImVec4 redColor = ImVec4(0.6, 0.1f, 0.1f, 0.2f);
|
||||
ImVec4 yellowColor = ImVec4(0.6, 0.6f, 0.1f, 0.2f);
|
||||
ImVec4 colorGreen = ImVec4(0.59, 0.76, 0.47, 1.0);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, colorGreen);
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(0.59, 0.76, 0.47, 0.2)), -1);
|
||||
const std::string timeString = " [" + l.time + "]";
|
||||
ImGui::Text(timeString.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImVec4 colorBlue = ImVec4(98 / 255.0, 174 / 255.0, 239 / 255.0, 1.);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, colorBlue);
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(98 / 255.0, 174 / 255.0, 239 / 255.0, 0.2)), -1);
|
||||
ImGui::Text(l.logger.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImVec4 color = ImVec4(1, 1, 1, 1.0);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
|
||||
if (l.type == CRITICAL)
|
||||
{
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(redColor), -1);
|
||||
}
|
||||
else if (l.type == WARNING)
|
||||
{
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(yellowColor), -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImVec4(1, 1, 1, 0.0)), -1);
|
||||
}
|
||||
|
||||
std::string displayMessage = l.message;
|
||||
if (l.count > 0)
|
||||
{
|
||||
displayMessage += "(" + std::to_string(l.count) + ")";
|
||||
}
|
||||
|
||||
ImGui::TextWrapped(displayMessage.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
|
||||
{
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
20
Editor/src/Windows/SceneEditor/Widgets/LoggerWidget.h
Normal file
20
Editor/src/Windows/SceneEditor/Widgets/LoggerWidget.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "IEditorWidget.h"
|
||||
|
||||
class LoggerWidget : public IEditorWidget
|
||||
{
|
||||
private:
|
||||
bool LogErrors = true;
|
||||
bool LogWarnings = true;
|
||||
bool LogDebug = true;
|
||||
bool AutoScroll = true;
|
||||
|
||||
public:
|
||||
LoggerWidget(EditorContext& inCtx) : IEditorWidget(inCtx) {}
|
||||
~LoggerWidget() = default;
|
||||
|
||||
public:
|
||||
void Update(float ts) override;
|
||||
void Draw() override;
|
||||
};
|
||||
@@ -38,9 +38,8 @@ void SceneHierarchyWidget::Draw()
|
||||
DrawCreateEntityButton();
|
||||
|
||||
DrawEntityTree();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SceneHierarchyWidget::DrawSearchBar()
|
||||
@@ -202,7 +201,6 @@ void SceneHierarchyWidget::DrawEntityTree()
|
||||
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Script", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("Visibility ", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,20 @@
|
||||
#pragma once
|
||||
#include "IEditorWidget.h"
|
||||
#include "../../EditorSelectionPanel.h"
|
||||
|
||||
class EditorContext;
|
||||
|
||||
using DrawComponentTypeFn = std::function<void(Nuake::Entity& entity, entt::meta_any& componentInstance)>;
|
||||
using DrawFieldTypeFn = std::function<void(entt::meta_data& fieldMeta, entt::meta_any& componentInstance)>;
|
||||
|
||||
class SelectionPropertyWidget : public IEditorWidget
|
||||
{
|
||||
private:
|
||||
TransformPanel transformPanel;
|
||||
MeshPanel meshPanel;
|
||||
SkinnedMeshPanel skinnedMeshPanel;
|
||||
Ref<Nuake::File> currentFile;
|
||||
Ref<Nuake::Resource> selectedResource;
|
||||
public:
|
||||
SelectionPropertyWidget(EditorContext& inCtx);
|
||||
~SelectionPropertyWidget() = default;
|
||||
@@ -14,5 +24,51 @@ public:
|
||||
void Draw() override;
|
||||
|
||||
private:
|
||||
|
||||
void DrawNone();
|
||||
void DrawEntity(Nuake::Entity entity);
|
||||
void DrawAddComponentMenu(Nuake::Entity entity);
|
||||
void DrawFile(Ref<Nuake::File> file);
|
||||
void DrawResource(Nuake::Resource resource);
|
||||
|
||||
template<class T, auto Func>
|
||||
void RegisterComponentDrawer()
|
||||
{
|
||||
const auto t = entt::type_id<T>();
|
||||
ComponentTypeDrawers[t.hash()] = std::bind(Func, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
template<class T, auto Func, class O>
|
||||
void RegisterComponentDrawer(O* o)
|
||||
{
|
||||
ComponentTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
template<class T, auto Func, class O>
|
||||
void RegisterTypeDrawer(O* o)
|
||||
{
|
||||
FieldTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Drawing functions for each component (for writing very specific inspectors for specific components)
|
||||
std::unordered_map<entt::id_type, DrawComponentTypeFn> ComponentTypeDrawers;
|
||||
|
||||
// List of functions to call for each component field type that needs to be drawn
|
||||
std::unordered_map<entt::id_type, DrawFieldTypeFn> FieldTypeDrawers;
|
||||
|
||||
void ResolveFile(Ref<Nuake::File> file);
|
||||
void DrawMaterialPanel(Ref<Nuake::Material> material);
|
||||
void DrawProjectPanel(Ref<Nuake::Project> project);
|
||||
void DrawNetScriptPanel(Ref<Nuake::File> file);
|
||||
|
||||
void DrawComponent(Nuake::Entity& entity, entt::meta_any& component);
|
||||
void DrawComponentContent(entt::meta_any& component);
|
||||
|
||||
void DrawFieldTypeFloat(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeBool(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeVector2(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeVector3(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeString(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeResourceFile(entt::meta_data& field, entt::meta_any& component);
|
||||
void DrawFieldTypeDynamicItemList(entt::meta_data& field, entt::meta_any& component);
|
||||
};
|
||||
151
Editor/src/Windows/SceneEditor/Widgets/ViewportWidget.cpp
Normal file
151
Editor/src/Windows/SceneEditor/Widgets/ViewportWidget.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "ViewportWidget.h"
|
||||
|
||||
#include <src/UI/ImUI.h>
|
||||
#include "src/Core/Input.h"
|
||||
|
||||
#include "../../EditorInterface.h"
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
void ViewportWidget::Update(float ts)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ViewportWidget::Draw()
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
if (BeginWidgetWindow(ICON_FA_GAMEPAD + std::string("Viewport")))
|
||||
{
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGuizmo::BeginFrame();
|
||||
ImGuizmo::SetOrthographic(false);
|
||||
|
||||
ImVec2 regionAvail = ImGui::GetContentRegionAvail();
|
||||
Vector2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y);
|
||||
|
||||
// This is important for make UI mouse coord relative to viewport
|
||||
// Input::SetViewportDimensions(m_ViewportPos, viewportPanelSize);
|
||||
|
||||
VkDescriptorSet textureDesc = VkRenderer::Get().DrawImage->GetImGuiDescriptorSet();
|
||||
|
||||
ImVec2 imagePos = ImGui::GetWindowPos() + ImGui::GetCursorPos();
|
||||
// Input::SetEditorViewportSize(m_ViewportPos, viewportPanelSize);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
//m_ViewportPos = { imagePos.x, imagePos.y };
|
||||
ImGui::Image(textureDesc, regionAvail, { 0, 1 }, { 1, 0 });
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
const Vector2& mousePos = Input::GetMousePosition();
|
||||
|
||||
const ImVec2& windowPos = ImGui::GetWindowPos();
|
||||
const auto windowPosNuake = Vector2(windowPos.x, windowPos.y);
|
||||
const ImVec2& windowSize = ImGui::GetWindowSize();
|
||||
const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x;
|
||||
const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y;
|
||||
// m_IsHoveringViewport = isInsideWidth && isInsideHeight;
|
||||
|
||||
// TODO(antopilo) drag n drop
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::AllowAxisFlip(true);
|
||||
ImGuizmo::SetRect(imagePos.x, imagePos.y, viewportPanelSize.x, viewportPanelSize.y);
|
||||
|
||||
// TODO(grid)
|
||||
auto selection = editorContext.GetSelection();
|
||||
if (selection.Type == EditorSelectionType::Entity && !Engine::IsPlayMode())
|
||||
{
|
||||
if (!selection.Entity.IsValid())
|
||||
{
|
||||
editorContext.SetSelection(EditorSelection());
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformComponent& tc = selection.Entity.GetComponent<TransformComponent>();
|
||||
Matrix4 transform = tc.GetGlobalTransform();
|
||||
const auto& editorCam = Engine::GetCurrentScene()->GetCurrentCamera();
|
||||
Matrix4 cameraView = editorCam->GetTransform();
|
||||
|
||||
// Since imguizmo doesnt support reverse-Z, we need to create a new projection matrix
|
||||
// With a normal near and far plane.
|
||||
Matrix4 normalZProjection = glm::perspectiveFov(glm::radians(editorCam->Fov), 9.0f * editorCam->AspectRatio, 9.0f, editorCam->Far, editorCam->Near);
|
||||
|
||||
static Vector3 camPreviousPos = Engine::GetCurrentScene()->m_EditorCamera->Translation;
|
||||
static Vector3 camNewPos = Vector3(0, 0, 0);
|
||||
Vector3 camDelta = camNewPos - camPreviousPos;
|
||||
Vector3 previousGlobalPos = transform[3];
|
||||
// Imguizmo calculates the delta from the gizmo,
|
||||
ImGuizmo::Manipulate(
|
||||
glm::value_ptr(Engine::GetCurrentScene()->GetCurrentCamera()->GetTransform()),
|
||||
glm::value_ptr(normalZProjection),
|
||||
CurrentOperation, CurrentMode,
|
||||
glm::value_ptr(transform), NULL,
|
||||
UseSnapping ? &CurrentSnapping.x : NULL
|
||||
);
|
||||
|
||||
if (ImGuizmo::IsUsing())
|
||||
{
|
||||
// Since imguizmo returns a transform in global space and we want the local transform,
|
||||
// we need to multiply by the inverse of the parent's global transform in order to revert
|
||||
// the changes from the parent transform.
|
||||
Matrix4 localTransform = Matrix4(transform);
|
||||
|
||||
Vector3 newGlobalPos = transform[3];
|
||||
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
|
||||
{
|
||||
Vector3 positionDelta = newGlobalPos - previousGlobalPos;
|
||||
Engine::GetCurrentScene()->m_EditorCamera->Translation += positionDelta;
|
||||
camNewPos = Engine::GetCurrentScene()->m_EditorCamera->Translation;
|
||||
}
|
||||
|
||||
ParentComponent& parent = selection.Entity.GetComponent<ParentComponent>();
|
||||
if (parent.HasParent)
|
||||
{
|
||||
const auto& parentTransformComponent = parent.Parent.GetComponent<TransformComponent>();
|
||||
const Matrix4& parentTransform = parentTransformComponent.GetGlobalTransform();
|
||||
localTransform = glm::inverse(parentTransform) * localTransform;
|
||||
}
|
||||
|
||||
// Decompose local transform
|
||||
float decomposedPosition[3];
|
||||
float decomposedEuler[3];
|
||||
float decomposedScale[3];
|
||||
ImGuizmo::DecomposeMatrixToComponents(glm::value_ptr(localTransform), decomposedPosition, decomposedEuler, decomposedScale);
|
||||
|
||||
const auto& localPosition = Vector3(decomposedPosition[0], decomposedPosition[1], decomposedPosition[2]);
|
||||
const auto& localScale = Vector3(decomposedScale[0], decomposedScale[1], decomposedScale[2]);
|
||||
|
||||
localTransform[0] /= localScale.x;
|
||||
localTransform[1] /= localScale.y;
|
||||
localTransform[2] /= localScale.z;
|
||||
const auto& rotationMatrix = Matrix3(localTransform);
|
||||
const Quat& localRotation = glm::normalize(Quat(rotationMatrix));
|
||||
|
||||
const Matrix4& rotationMatrix4 = glm::mat4_cast(localRotation);
|
||||
const Matrix4& scaleMatrix = glm::scale(Matrix4(1.0f), localScale);
|
||||
const Matrix4& translationMatrix = glm::translate(Matrix4(1.0f), localPosition);
|
||||
const Matrix4& newLocalTransform = translationMatrix * rotationMatrix4 * scaleMatrix;
|
||||
|
||||
tc.Translation = localPosition;
|
||||
|
||||
if (CurrentOperation != ImGuizmo::SCALE)
|
||||
{
|
||||
tc.Rotation = localRotation;
|
||||
}
|
||||
|
||||
tc.Scale = localScale;
|
||||
tc.LocalTransform = newLocalTransform;
|
||||
tc.Dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
24
Editor/src/Windows/SceneEditor/Widgets/ViewportWidget.h
Normal file
24
Editor/src/Windows/SceneEditor/Widgets/ViewportWidget.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "IEditorWidget.h"
|
||||
|
||||
#include <imgui/ImGuizmo.h>
|
||||
|
||||
class EditorContext;
|
||||
|
||||
class ViewportWidget : public IEditorWidget
|
||||
{
|
||||
private:
|
||||
ImGuizmo::OPERATION CurrentOperation = ImGuizmo::TRANSLATE;
|
||||
ImGuizmo::MODE CurrentMode = ImGuizmo::WORLD;
|
||||
bool UseSnapping = true;
|
||||
Nuake::Vector3 CurrentSnapping = { 0.05f, 0.05f, 0.05f };
|
||||
|
||||
public:
|
||||
ViewportWidget(EditorContext& context) : IEditorWidget(context) {}
|
||||
~ViewportWidget() = default;
|
||||
|
||||
public:
|
||||
void Update(float ts) override;
|
||||
void Draw() override;
|
||||
};
|
||||
@@ -423,7 +423,7 @@ void VkRenderer::InitImgui()
|
||||
io.Fonts->AddFontFromMemoryTTF(StaticResources::Resources_Fonts_Poppins_Regular_ttf, StaticResources::Resources_Fonts_Poppins_Regular_ttf_len, 16.0);
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGuiStyle& s = ImGui::GetStyle();
|
||||
@@ -654,6 +654,15 @@ void VkRenderer::EndDraw()
|
||||
|
||||
VK_CALL(vkQueuePresentKHR(GPUQueue, &presentInfo));
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
//Update and Render additional Platform Windows
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
{
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
}
|
||||
|
||||
// Increase the number of frames drawn
|
||||
FrameNumber++;
|
||||
}
|
||||
|
||||
@@ -263,5 +263,17 @@ namespace Nuake
|
||||
{
|
||||
DrawButtonImage(image, image, image, tintNormal, tintHovered, tintPressed, ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||
};
|
||||
|
||||
bool Splitter(bool split_vertically, float thickness, float* size1, float* size2, float min_size1, float min_size2, float splitter_long_axis_size)
|
||||
{
|
||||
using namespace ImGui;
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiID id = window->GetID("##Splitter");
|
||||
ImRect bb;
|
||||
bb.Min = window->DC.CursorPos + (split_vertically ? ImVec2(*size1, 0.0f) : ImVec2(0.0f, *size1));
|
||||
bb.Max = bb.Min + CalcItemSize(split_vertically ? ImVec2(thickness, splitter_long_axis_size) : ImVec2(splitter_long_axis_size, thickness), 0.0f, 0.0f);
|
||||
return SplitterBehavior(bb, id, split_vertically ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, min_size1, min_size2, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,5 +79,6 @@ namespace Nuake
|
||||
|
||||
ImRect RectOffset(const ImRect& rect, ImVec2 xy);
|
||||
|
||||
bool Splitter(bool split_vertically, float thickness, float* size1, float* size2, float min_size1, float min_size2, float splitter_long_axis_size = -1.0f);
|
||||
}
|
||||
}
|
||||
@@ -258,8 +258,8 @@ void Window::EndDraw()
|
||||
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
{
|
||||
GLFWwindow* backup_current_context = glfwGetCurrentContext();
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
//ImGui::UpdatePlatformWindows();
|
||||
//ImGui::RenderPlatformWindowsDefault();
|
||||
glfwMakeContextCurrent(backup_current_context);
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ void Window::InitImgui()
|
||||
io.Fonts->AddFontFromMemoryTTF(StaticResources::Resources_Fonts_Poppins_Regular_ttf, StaticResources::Resources_Fonts_Poppins_Regular_ttf_len, 16.0);
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGuiStyle& s = ImGui::GetStyle();
|
||||
|
||||
Reference in New Issue
Block a user