Editor Tweaks #192
|
@ -10,63 +10,102 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHCommandManager::CommandStack SHCommandManager::undoStack{};
|
|
||||||
SHCommandManager::CommandStack SHCommandManager::redoStack{};
|
SHCommandManager::CommandStack SHCommandManager::undoStack(defaultStackSize);
|
||||||
|
SHCommandManager::CommandStack SHCommandManager::redoStack(defaultStackSize);
|
||||||
|
SHCommandManager::CommandStack SHCommandManager::secondaryUndoStack(defaultStackSize);
|
||||||
|
SHCommandManager::CommandStack SHCommandManager::secondaryRedoStack(defaultStackSize);
|
||||||
|
|
||||||
|
SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack);
|
||||||
|
SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack);
|
||||||
|
|
||||||
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
||||||
{
|
{
|
||||||
redoStack = CommandStack();
|
*pCurrRedoStack = CommandStack(defaultStackSize);
|
||||||
commandPtr->Execute();
|
commandPtr->Execute();
|
||||||
if (overrideValue && !undoStack.empty())
|
if (overrideValue && !pCurrUndoStack->Empty())
|
||||||
{
|
{
|
||||||
undoStack.top()->Merge(commandPtr);
|
pCurrUndoStack->Top()->Merge(commandPtr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
undoStack.push(commandPtr);
|
pCurrUndoStack->Push(commandPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
|
void SHCommandManager::RegisterCommand(BaseCommandPtr commandPtr)
|
||||||
{
|
{
|
||||||
undoStack.push(commandPtr);
|
pCurrUndoStack->Push(commandPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::UndoCommand()
|
void SHCommandManager::UndoCommand()
|
||||||
{
|
{
|
||||||
if (undoStack.empty())
|
if (pCurrUndoStack->Empty())
|
||||||
return;
|
return;
|
||||||
undoStack.top()->Undo();
|
pCurrUndoStack->Top()->Undo();
|
||||||
redoStack.push(undoStack.top());
|
pCurrRedoStack->Push(pCurrUndoStack->Top());
|
||||||
undoStack.pop();
|
pCurrUndoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::RedoCommand()
|
void SHCommandManager::RedoCommand()
|
||||||
{
|
{
|
||||||
if (redoStack.empty())
|
if (pCurrRedoStack->Empty())
|
||||||
return;
|
return;
|
||||||
redoStack.top()->Execute();
|
pCurrRedoStack->Top()->Execute();
|
||||||
undoStack.push(redoStack.top());
|
pCurrUndoStack->Push(pCurrRedoStack->Top());
|
||||||
redoStack.pop();
|
pCurrRedoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SHCommandManager::GetUndoStackSize()
|
std::size_t SHCommandManager::GetUndoStackSize()
|
||||||
{
|
{
|
||||||
return undoStack.size();
|
return pCurrUndoStack->Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SHCommandManager::GetRedoStackSize()
|
std::size_t SHCommandManager::GetRedoStackSize()
|
||||||
{
|
{
|
||||||
return redoStack.size();
|
return pCurrRedoStack->Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::PopLatestCommandFromRedoStack()
|
void SHCommandManager::PopLatestCommandFromRedoStack()
|
||||||
{
|
{
|
||||||
redoStack.pop();
|
pCurrRedoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::PopLatestCommandFromUndoStack()
|
void SHCommandManager::PopLatestCommandFromUndoStack()
|
||||||
{
|
{
|
||||||
undoStack.pop();
|
pCurrUndoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHCommandManager::SwapStacks()
|
||||||
|
{
|
||||||
|
if (pCurrUndoStack == &undoStack)
|
||||||
|
{
|
||||||
|
pCurrUndoStack = &secondaryUndoStack;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
secondaryUndoStack.Clear();
|
||||||
|
pCurrUndoStack = &undoStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pCurrRedoStack == &redoStack)
|
||||||
|
{
|
||||||
|
pCurrRedoStack = &secondaryRedoStack;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
secondaryRedoStack.Clear();
|
||||||
|
pCurrRedoStack = &redoStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHCommandManager::ClearAll()
|
||||||
|
{
|
||||||
|
undoStack.Clear();
|
||||||
|
redoStack.Clear();
|
||||||
|
|
||||||
|
secondaryUndoStack.Clear();
|
||||||
|
secondaryRedoStack.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
#include "SHCommand.hpp"
|
#include "SHCommand.hpp"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
#include "Tools/SHDeque.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -22,7 +23,8 @@ namespace SHADE
|
||||||
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
|
using BaseCommandPtr = std::shared_ptr<SHBaseCommand>;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
|
using SHCommandPtr = std::shared_ptr<SHCommand<T>>;
|
||||||
using CommandStack = std::stack<BaseCommandPtr>;
|
using CommandStack = SHDeque<BaseCommandPtr>;
|
||||||
|
using CommandStackPtr = CommandStack*;
|
||||||
|
|
||||||
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
|
static void PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue = false);
|
||||||
static void RegisterCommand(BaseCommandPtr commandPtr);
|
static void RegisterCommand(BaseCommandPtr commandPtr);
|
||||||
|
@ -34,8 +36,17 @@ namespace SHADE
|
||||||
static void PopLatestCommandFromRedoStack();
|
static void PopLatestCommandFromRedoStack();
|
||||||
static void PopLatestCommandFromUndoStack();
|
static void PopLatestCommandFromUndoStack();
|
||||||
|
|
||||||
|
static void SwapStacks();
|
||||||
|
static void ClearAll();
|
||||||
|
|
||||||
|
static constexpr CommandStack::SizeType defaultStackSize = 100;
|
||||||
private:
|
private:
|
||||||
|
static CommandStackPtr pCurrUndoStack;
|
||||||
|
static CommandStackPtr pCurrRedoStack;
|
||||||
|
|
||||||
static CommandStack undoStack;
|
static CommandStack undoStack;
|
||||||
|
static CommandStack secondaryUndoStack;
|
||||||
static CommandStack redoStack;
|
static CommandStack redoStack;
|
||||||
|
static CommandStack secondaryRedoStack;
|
||||||
};
|
};
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHAssetBrowser::SHAssetBrowser()
|
SHAssetBrowser::SHAssetBrowser()
|
||||||
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder), assetBeingCreated(std::nullopt)
|
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,23 +34,48 @@ namespace SHADE
|
||||||
RecursivelyDrawTree(rootFolder);
|
RecursivelyDrawTree(rootFolder);
|
||||||
DrawMenuBar();
|
DrawMenuBar();
|
||||||
DrawCurrentFolder();
|
DrawCurrentFolder();
|
||||||
|
DrawAssetBeingCreated();
|
||||||
|
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
if(refreshQueued)
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::QueueRefresh() noexcept
|
||||||
|
{
|
||||||
|
refreshQueued = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHAssetBrowser::Refresh() noexcept
|
||||||
|
{
|
||||||
|
SHAssetManager::RefreshDirectory();
|
||||||
|
rootFolder = SHAssetManager::GetRootFolder();
|
||||||
|
refreshQueued = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAssetBrowser::DrawMenuBar()
|
void SHAssetBrowser::DrawMenuBar()
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenuBar())
|
if (ImGui::BeginMenuBar())
|
||||||
{
|
{
|
||||||
|
if(ImGui::SmallButton(ICON_MD_SYNC))
|
||||||
|
{
|
||||||
|
QueueRefresh();
|
||||||
|
}
|
||||||
|
if(ImGui::SmallButton(ICON_FA_CIRCLE_PLUS))
|
||||||
|
{
|
||||||
|
isAssetBeingCreated = true;
|
||||||
|
}
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if !compiled, set genMeta to true
|
||||||
|
|
||||||
ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder)
|
ImRect SHAssetBrowser::RecursivelyDrawTree(FolderPointer folder)
|
||||||
{
|
{
|
||||||
auto const& subFolders = folder->subFolders;
|
auto const& subFolders = folder->subFolders;
|
||||||
auto const& files = folder->files;
|
auto files = folder->files;
|
||||||
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
const bool isSelected = std::ranges::find(selectedFolders, folder) != selectedFolders.end();
|
||||||
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
ImGuiTreeNodeFlags flags = (subFolders.empty() && files.empty()) ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_OpenOnArrow;
|
||||||
if (isSelected)
|
if (isSelected)
|
||||||
|
@ -62,21 +87,10 @@ namespace SHADE
|
||||||
ImGuiID folderID = ImGui::GetItemID();
|
ImGuiID folderID = ImGui::GetItemID();
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
|
||||||
if (ImGui::BeginPopupContextItem())
|
//if (ImGui::BeginPopupContextItem())
|
||||||
{
|
//{
|
||||||
if (ImGui::BeginMenu("Create Asset"))
|
// ImGui::EndPopup();
|
||||||
{
|
//}
|
||||||
//TODO: Change to rttr type enum align
|
|
||||||
if (ImGui::Selectable("Material"))
|
|
||||||
{
|
|
||||||
assetBeingCreated = { folder, AssetType::MATERIAL, "New Material" };
|
|
||||||
ImGui::TreeNodeSetOpen(folderID, true);
|
|
||||||
isOpen = true;
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::IsItemClicked())
|
if (ImGui::IsItemClicked())
|
||||||
{
|
{
|
||||||
|
@ -100,19 +114,15 @@ namespace SHADE
|
||||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
vertLineEnd.y = midPoint;
|
vertLineEnd.y = midPoint;
|
||||||
}
|
}
|
||||||
for (auto const& file : files)
|
for (auto& file : files)
|
||||||
{
|
{
|
||||||
if(file.assetMeta == nullptr)
|
|
||||||
continue;
|
|
||||||
const float horizontalLineSize = 25.0f;
|
const float horizontalLineSize = 25.0f;
|
||||||
const ImRect childRect = DrawFile(file.assetMeta);
|
const ImRect childRect = DrawFile(file);
|
||||||
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
vertLineEnd.y = midPoint;
|
vertLineEnd.y = midPoint;
|
||||||
}
|
}
|
||||||
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
||||||
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
|
|
||||||
DrawAssetBeingCreated();
|
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
@ -148,7 +158,33 @@ namespace SHADE
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImRect SHAssetBrowser::DrawFile(SHAsset const* const asset) noexcept
|
ImRect SHAssetBrowser::DrawFile(SHFile& file) noexcept
|
||||||
|
{
|
||||||
|
if(file.compilable)
|
||||||
|
{
|
||||||
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
|
||||||
|
static constexpr std::string_view icon = ICON_MD_FILE_PRESENT;
|
||||||
|
ImGui::PushID(file.name.data());
|
||||||
|
bool const isOpen = ImGui::TreeNodeEx(file.name.data(), flags, "%s %s%s", icon.data(), file.name.data(), file.ext.data());
|
||||||
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
if(ImGui::BeginPopupContextItem())
|
||||||
|
{
|
||||||
|
if(ImGui::Selectable("Compile"))
|
||||||
|
{
|
||||||
|
SHAssetManager::CompileAsset(file.path, !file.compiled);
|
||||||
|
QueueRefresh();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
ImGui::TreePop();
|
||||||
|
ImGui::PopID();
|
||||||
|
return nodeRect;
|
||||||
|
}
|
||||||
|
if(file.assetMeta)
|
||||||
|
DrawAsset(file.assetMeta, file.ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImRect SHAssetBrowser::DrawAsset(SHAsset const* const asset, FileExt const& ext /*= ""*/) noexcept
|
||||||
{
|
{
|
||||||
if (asset == nullptr)
|
if (asset == nullptr)
|
||||||
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
|
@ -173,7 +209,7 @@ namespace SHADE
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s", icon.data(), asset->name.data());
|
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s%s", icon.data(), asset->name.data(), ext.data());
|
||||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||||
if (SHDragDrop::BeginSource())
|
if (SHDragDrop::BeginSource())
|
||||||
{
|
{
|
||||||
|
@ -212,7 +248,6 @@ namespace SHADE
|
||||||
case AssetType::MAX_COUNT: break;
|
case AssetType::MAX_COUNT: break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
||||||
|
@ -227,7 +262,7 @@ namespace SHADE
|
||||||
for(auto const& subAsset : asset->subAssets)
|
for(auto const& subAsset : asset->subAssets)
|
||||||
{
|
{
|
||||||
const float horizontalLineSize = 25.0f;
|
const float horizontalLineSize = 25.0f;
|
||||||
const ImRect childRect = DrawFile(subAsset);
|
const ImRect childRect = DrawAsset(subAsset);
|
||||||
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||||
vertLineEnd.y = midPoint;
|
vertLineEnd.y = midPoint;
|
||||||
|
@ -240,19 +275,52 @@ namespace SHADE
|
||||||
|
|
||||||
void SHAssetBrowser::DrawAssetBeingCreated() noexcept
|
void SHAssetBrowser::DrawAssetBeingCreated() noexcept
|
||||||
{
|
{
|
||||||
if (!assetBeingCreated.has_value())
|
if(isAssetBeingCreated)
|
||||||
return;
|
ImGui::OpenPopup(newAssetPopup.data());
|
||||||
auto& path = std::get<0>(assetBeingCreated.value());
|
|
||||||
auto& type = std::get<1>(assetBeingCreated.value());
|
if(ImGui::BeginPopupModal(newAssetPopup.data(), &isAssetBeingCreated))
|
||||||
auto& assetName = std::get<2>(assetBeingCreated.value());
|
|
||||||
if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue))
|
|
||||||
{
|
{
|
||||||
AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
|
ImGui::RadioButton("Material", true);
|
||||||
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
ImGui::SameLine();
|
||||||
|
if (ImGui::InputText("##newAssetName", &nameOfAssetBeingCreated, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll))
|
||||||
{
|
{
|
||||||
matInspector->OpenMaterial(assetId, true);
|
AssetID assetId = SHAssetManager::CreateNewAsset(AssetType::MATERIAL, nameOfAssetBeingCreated);
|
||||||
|
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||||
|
{
|
||||||
|
matInspector->OpenMaterial(assetId, true);
|
||||||
|
}
|
||||||
|
nameOfAssetBeingCreated.clear();
|
||||||
|
QueueRefresh();
|
||||||
|
isAssetBeingCreated = false;
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
}
|
}
|
||||||
assetBeingCreated.reset();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
//if (ImGui::BeginMenu("Create Asset"))
|
||||||
|
//{
|
||||||
|
// //TODO: Change to rttr type enum align
|
||||||
|
// if (ImGui::Selectable("Material"))
|
||||||
|
// {
|
||||||
|
// assetBeingCreated = { folder, AssetType::MATERIAL, "NewMaterial" };
|
||||||
|
// ImGui::TreeNodeSetOpen(folderID, true);
|
||||||
|
// isOpen = true;
|
||||||
|
// }
|
||||||
|
// ImGui::EndMenu();
|
||||||
|
//}
|
||||||
|
//if (!assetBeingCreated.has_value())
|
||||||
|
// return;
|
||||||
|
//auto& path = std::get<0>(assetBeingCreated.value());
|
||||||
|
//auto& type = std::get<1>(assetBeingCreated.value());
|
||||||
|
//auto& assetName = std::get<2>(assetBeingCreated.value());
|
||||||
|
//if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll))
|
||||||
|
//{
|
||||||
|
// AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
|
||||||
|
// if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||||
|
// {
|
||||||
|
// matInspector->OpenMaterial(assetId, true);
|
||||||
|
// }
|
||||||
|
// assetBeingCreated.reset();
|
||||||
|
// QueueRefresh();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,29 @@ namespace SHADE
|
||||||
class SHAssetBrowser final : public SHEditorWindow
|
class SHAssetBrowser final : public SHEditorWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
|
|
||||||
SHAssetBrowser();
|
SHAssetBrowser();
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
void Refresh();
|
void QueueRefresh() noexcept;
|
||||||
private:
|
private:
|
||||||
void DrawMenuBar();
|
void DrawMenuBar();
|
||||||
ImRect RecursivelyDrawTree(FolderPointer folder);
|
ImRect RecursivelyDrawTree(FolderPointer folder);
|
||||||
void DrawCurrentFolder();
|
void DrawCurrentFolder();
|
||||||
ImRect DrawFile(SHAsset const* const asset) noexcept;
|
ImRect DrawFile(SHFile& file) noexcept;
|
||||||
|
ImRect DrawAsset(SHAsset const* const asset, FileExt const& ext = "") noexcept;
|
||||||
void DrawAssetBeingCreated() noexcept;
|
void DrawAssetBeingCreated() noexcept;
|
||||||
|
|
||||||
|
void Refresh() noexcept;
|
||||||
|
|
||||||
FolderPointer rootFolder, prevFolder, currentFolder;
|
FolderPointer rootFolder, prevFolder, currentFolder;
|
||||||
std::optional<AssetEntry> assetBeingCreated;
|
|
||||||
std::vector<FolderPointer> selectedFolders;
|
std::vector<FolderPointer> selectedFolders;
|
||||||
std::vector<AssetID> selectedAssets;
|
std::vector<AssetID> selectedAssets;
|
||||||
static constexpr float tileWidth = 50.0f;
|
static constexpr float tileWidth = 50.0f;
|
||||||
|
bool refreshQueued = false;
|
||||||
|
bool isAssetBeingCreated = false;
|
||||||
|
static constexpr std::string_view newAssetPopup = "Create New Asset";
|
||||||
|
std::string nameOfAssetBeingCreated;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,13 +93,14 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
EntityID const& eid = editor->selectedEntities[0];
|
EntityID const& eid = editor->selectedEntities[0];
|
||||||
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
SHEntity* entity = SHEntityManager::GetEntityByID(eid);
|
||||||
if(!entity)
|
SHSceneNode* entityNode = SHSceneManager::GetCurrentSceneGraph().GetNode(eid);
|
||||||
|
if(!entity || !entityNode)
|
||||||
{
|
{
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
ImGui::TextColored(ImGuiColors::green, "EID: %zu", eid);
|
||||||
SHEditorWidgets::CheckBox("##IsActive", [entity]()->bool {return entity->GetActive(); }, [entity](bool const& active) {entity->SetActive(active); });
|
SHEditorWidgets::CheckBox("##IsActive", [entityNode]()->bool {return entityNode->IsActive(); }, [entityNode](bool const& active) {entityNode->SetActive(active); });
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::InputText("##EntityName", &entity->name);
|
ImGui::InputText("##EntityName", &entity->name);
|
||||||
|
|
|
@ -223,39 +223,20 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if(editor->SaveScene())
|
if(editor->SaveScene())
|
||||||
{
|
{
|
||||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
editor->Play();
|
||||||
{
|
|
||||||
.previousState = editor->editorState
|
|
||||||
};
|
|
||||||
editor->editorState = SHEditor::State::PLAY;
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
|
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
|
||||||
if(ImGui::SmallButton(ICON_MD_PAUSE))
|
if(ImGui::SmallButton(ICON_MD_PAUSE))
|
||||||
{
|
{
|
||||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
editor->Pause();
|
||||||
{
|
|
||||||
.previousState = editor->editorState
|
|
||||||
};
|
|
||||||
editor->editorState = SHEditor::State::PAUSE;
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
|
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
|
ImGui::BeginDisabled(editor->editorState == SHEditor::State::STOP);
|
||||||
if(ImGui::SmallButton(ICON_MD_STOP))
|
if(ImGui::SmallButton(ICON_MD_STOP))
|
||||||
{
|
{
|
||||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
editor->Stop();
|
||||||
{
|
|
||||||
.previousState = editor->editorState
|
|
||||||
};
|
|
||||||
editor->editorState = SHEditor::State::STOP;
|
|
||||||
|
|
||||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
|
||||||
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace SHADE
|
||||||
shouldUpdateCamera = false;
|
shouldUpdateCamera = false;
|
||||||
}
|
}
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||||
|
SHEditor* editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
|
||||||
if (Begin())
|
if (Begin())
|
||||||
{
|
{
|
||||||
|
@ -51,7 +52,6 @@ namespace SHADE
|
||||||
beginCursorPos = ImGui::GetCursorScreenPos();
|
beginCursorPos = ImGui::GetCursorScreenPos();
|
||||||
viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y };
|
viewportMousePos = { mousePos.x - beginCursorPos.x, mousePos.y - beginCursorPos.y };
|
||||||
gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos);
|
gfxSystem->GetMousePickSystem()->SetViewportMousePos(viewportMousePos);
|
||||||
|
|
||||||
ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y });
|
ImGui::Image((ImTextureID)descriptorSet, { beginContentRegionAvailable.x, beginContentRegionAvailable.y });
|
||||||
|
|
||||||
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
if (ImGui::IsWindowHovered() && ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||||
|
@ -64,24 +64,25 @@ namespace SHADE
|
||||||
|
|
||||||
shouldUpdateCamera = true;
|
shouldUpdateCamera = true;
|
||||||
}
|
}
|
||||||
if (ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
if (editor->editorState != SHEditor::State::PLAY && ImGui::IsWindowFocused() && !ImGui::IsMouseDown(ImGuiMouseButton_Right))
|
||||||
{
|
{
|
||||||
if (ImGui::IsKeyReleased(ImGuiKey_Q))
|
if (ImGui::IsKeyReleased(ImGuiKey_W))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
transformGizmo.operation = SHTransformGizmo::Operation::TRANSLATE;
|
||||||
}
|
}
|
||||||
if (ImGui::IsKeyReleased(ImGuiKey_W))
|
if (ImGui::IsKeyReleased(ImGuiKey_E))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
transformGizmo.operation = SHTransformGizmo::Operation::ROTATE;
|
||||||
}
|
}
|
||||||
if (ImGui::IsKeyReleased(ImGuiKey_E))
|
if (ImGui::IsKeyReleased(ImGuiKey_R))
|
||||||
{
|
{
|
||||||
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
transformGizmo.operation = SHTransformGizmo::Operation::SCALE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
ImGuizmo::SetRect(beginCursorPos.x, beginCursorPos.y, beginContentRegionAvailable.x, beginContentRegionAvailable.y);
|
||||||
transformGizmo.Draw();
|
if(editor->editorState != SHEditor::State::PLAY)
|
||||||
|
transformGizmo.Draw();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,19 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
SHCommandManager::UndoCommand();
|
SHCommandManager::UndoCommand();
|
||||||
}
|
}
|
||||||
|
if(ImGui::IsKeyReleased(ImGuiKey_F5))
|
||||||
|
{
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
|
||||||
|
{
|
||||||
|
Pause();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,6 +609,48 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHEditor::Play()
|
||||||
|
{
|
||||||
|
if(editorState == State::PLAY)
|
||||||
|
return;
|
||||||
|
if (SaveScene())
|
||||||
|
{
|
||||||
|
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||||
|
{
|
||||||
|
.previousState = editorState
|
||||||
|
};
|
||||||
|
editorState = State::PLAY;
|
||||||
|
SHCommandManager::SwapStacks();
|
||||||
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEditor::Pause()
|
||||||
|
{
|
||||||
|
if (editorState == State::PAUSE)
|
||||||
|
return;
|
||||||
|
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||||
|
{
|
||||||
|
.previousState = editorState
|
||||||
|
};
|
||||||
|
editorState = State::PAUSE;
|
||||||
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PAUSE_EVENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHEditor::Stop()
|
||||||
|
{
|
||||||
|
if (editorState == State::STOP)
|
||||||
|
return;
|
||||||
|
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||||
|
{
|
||||||
|
.previousState = editorState
|
||||||
|
};
|
||||||
|
editorState = SHEditor::State::STOP;
|
||||||
|
SHCommandManager::SwapStacks();
|
||||||
|
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
||||||
|
LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
|
}
|
||||||
|
|
||||||
void SHEditor::NewFrame()
|
void SHEditor::NewFrame()
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
|
@ -184,6 +184,10 @@ namespace SHADE
|
||||||
|
|
||||||
void LoadScene(AssetID const& assetID) noexcept;
|
void LoadScene(AssetID const& assetID) noexcept;
|
||||||
|
|
||||||
|
void Play();
|
||||||
|
void Pause();
|
||||||
|
void Stop();
|
||||||
|
|
||||||
// List of selected entities
|
// List of selected entities
|
||||||
std::vector<EntityID> selectedEntities;
|
std::vector<EntityID> selectedEntities;
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace SHADE
|
||||||
|
|
||||||
for (auto* child : children)
|
for (auto* child : children)
|
||||||
{
|
{
|
||||||
SetActive(newActiveState);
|
child->SetActive(newActiveState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SH_API.h"
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
class SH_API SHDeque
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ValueType = T;
|
||||||
|
using Pointer = T*;
|
||||||
|
using ValueRef = T&;
|
||||||
|
using ValueConstRef = T const&;
|
||||||
|
using SizeType = uint32_t;
|
||||||
|
using ContainerType = std::deque<ValueType>;
|
||||||
|
using ContainerTypeConstRef = std::deque<ValueType>;
|
||||||
|
|
||||||
|
SHDeque(SizeType n) : max_size(n) {}
|
||||||
|
|
||||||
|
ContainerTypeConstRef const& GetDeque() const
|
||||||
|
{
|
||||||
|
return deque;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Push(ValueConstRef obj)
|
||||||
|
{
|
||||||
|
if (deque.size() < max_size)
|
||||||
|
deque.push_front(std::move(obj));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
deque.pop_back();
|
||||||
|
deque.push_front(std::move(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Empty()
|
||||||
|
{
|
||||||
|
return deque.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop()
|
||||||
|
{
|
||||||
|
deque.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueConstRef Top()
|
||||||
|
{
|
||||||
|
return deque.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeType Size() const noexcept
|
||||||
|
{
|
||||||
|
return deque.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
deque.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int max_size;
|
||||||
|
ContainerType deque{};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue