mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 20:17:06 +03:00
511 lines
14 KiB
C++
511 lines
14 KiB
C++
#include "dockspace.h"
|
|
#include "console.h"
|
|
#include "content.h"
|
|
#include <asset/asset_manager.h>
|
|
#include <nfd.h>
|
|
#include <scene/scene_manager.h>
|
|
using namespace engine;
|
|
using namespace engine::ui;
|
|
|
|
const static std::string MAINMENU_GCloseIcon = ICON_FA_POWER_OFF;
|
|
|
|
MainViewportDockspaceAndMenu::MainViewportDockspaceAndMenu()
|
|
: WidgetBase("MainViewportDockspaceAndMenu", "MainViewportDockspaceAndMenu")
|
|
, sceneAssetSave(combineIcon("Save edited scenes...", ICON_FA_MESSAGE))
|
|
, contentAssetImport(combineIcon("Imported assets config...", ICON_FA_MESSAGE))
|
|
{
|
|
m_bShow = false;
|
|
}
|
|
|
|
|
|
|
|
void MainViewportDockspaceAndMenu::dockspace(
|
|
bool bNewWindow,
|
|
const std::string& name,
|
|
const RuntimeModuleTickData& tickData,
|
|
VulkanContext* context,
|
|
ImGuiViewport* viewport,
|
|
std::function<void()>&& menu)
|
|
{
|
|
ZoneScoped;
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
if (!(io.ConfigFlags & ImGuiConfigFlags_DockingEnable))
|
|
{
|
|
return;
|
|
}
|
|
static bool bShow = true;
|
|
|
|
static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_None;
|
|
|
|
ImGuiWindowFlags windowFlags
|
|
= ImGuiWindowFlags_MenuBar
|
|
| ImGuiWindowFlags_NoDocking
|
|
| ImGuiWindowFlags_NoTitleBar
|
|
| ImGuiWindowFlags_NoCollapse
|
|
| ImGuiWindowFlags_NoResize
|
|
| ImGuiWindowFlags_NoMove
|
|
| ImGuiWindowFlags_NoBringToFrontOnFocus
|
|
| ImGuiWindowFlags_NoNavFocus;
|
|
if (dockspaceFlags & ImGuiDockNodeFlags_PassthruCentralNode)
|
|
{
|
|
windowFlags |= ImGuiWindowFlags_NoBackground;
|
|
}
|
|
|
|
{
|
|
ImGui::SetNextWindowPos(viewport->WorkPos);
|
|
ImGui::SetNextWindowSize(viewport->WorkSize);
|
|
ImGui::SetNextWindowViewport(viewport->ID);
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 6.0f));
|
|
{
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
|
if(bNewWindow)
|
|
{
|
|
ImGui::Begin(name.c_str(), &bShow, windowFlags);
|
|
}
|
|
ImGui::PopStyleVar();
|
|
|
|
ImGuiID dockspaceId = ImGui::GetID(name.c_str());
|
|
ImGui::DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
|
|
|
|
if (ImGui::BeginMenuBar())
|
|
{
|
|
menu();
|
|
|
|
ImGui::EndMenuBar();
|
|
}
|
|
}
|
|
ImGui::PopStyleVar(3);
|
|
|
|
if (bNewWindow)
|
|
{
|
|
ImGui::End();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainViewportDockspaceAndMenu::onTick(const RuntimeModuleTickData& tickData, VulkanContext* context)
|
|
{
|
|
static std::string dockspaceName = "Engine MainViewport Dockspace";
|
|
dockspace(true, dockspaceName, tickData, context, ImGui::GetMainViewport(), [this]() { drawDockspaceMenu(); });
|
|
|
|
sceneAssetSave.draw();
|
|
contentAssetImport.draw();
|
|
}
|
|
|
|
|
|
void MainViewportDockspaceAndMenu::drawDockspaceMenu()
|
|
{
|
|
if (ImGui::BeginMenu(" FILE "))
|
|
{
|
|
const bool bSceneDirty = !getAssetManager()->getDirtyAsset<Scene>().empty();
|
|
if (ImGui::MenuItem(combineIcon("New Scene", ICON_NONE).c_str()))
|
|
{
|
|
if (bSceneDirty)
|
|
{
|
|
if (sceneAssetSave.open())
|
|
{
|
|
CHECK(!sceneAssetSave.afterEventAccept);
|
|
sceneAssetSave.afterEventAccept = []()
|
|
{
|
|
getSceneManager()->releaseScene();
|
|
};
|
|
}
|
|
}
|
|
else
|
|
{
|
|
getSceneManager()->releaseScene();
|
|
}
|
|
}
|
|
|
|
if (!bSceneDirty) { ImGui::BeginDisabled(); }
|
|
if (ImGui::MenuItem(combineIcon("Save Scene", ICON_NONE).c_str()))
|
|
{
|
|
if (bSceneDirty)
|
|
{
|
|
sceneAssetSave.open();
|
|
}
|
|
}
|
|
if (!bSceneDirty) { ImGui::EndDisabled(); }
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::MenuItem(combineIcon(" Exit", MAINMENU_GCloseIcon).c_str()))
|
|
{
|
|
m_engine->getGLFWWindows()->close();
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::BeginMenu(" EDIT "))
|
|
{
|
|
if (ImGui::MenuItem(combineIcon("Undo", ICON_FA_ARROW_ROTATE_LEFT).c_str()))
|
|
{
|
|
|
|
}
|
|
|
|
if (ImGui::MenuItem(combineIcon("Redo", ICON_FA_ARROW_ROTATE_RIGHT).c_str()))
|
|
{
|
|
|
|
}
|
|
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::BeginMenu(" VIEW "))
|
|
{
|
|
widgetInView.loop([](WidgetInView& widgetInView)
|
|
{
|
|
if(!widgetInView.bMultiWindow)
|
|
{
|
|
auto* widget = widgetInView.widgets[0];
|
|
if (ImGui::MenuItem(widget->getName().c_str(), NULL, widget->getVisible()))
|
|
{
|
|
widget->setVisible(!widget->getVisible());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const char* name = widgetInView.widgets[0]->getWidgetName().c_str();
|
|
if (ImGui::BeginMenu(name))
|
|
{
|
|
for (size_t i = 0; i < widgetInView.widgets.size(); i++)
|
|
{
|
|
auto* widget = widgetInView.widgets[i];
|
|
std::string secondName = widgetInView.widgets[i]->getName();
|
|
if (ImGui::MenuItem(secondName.c_str(), NULL, widget->getVisible()))
|
|
{
|
|
widget->setVisible(!widget->getVisible());
|
|
}
|
|
}
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
}
|
|
});
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::BeginMenu(" HELP "))
|
|
{
|
|
if (ImGui::MenuItem(combineIcon(" About", ICON_FA_CIRCLE_QUESTION).c_str()))
|
|
{
|
|
|
|
}
|
|
|
|
ImGui::Separator();
|
|
|
|
if (ImGui::MenuItem(combineIcon("Developer", ICON_NONE).c_str()))
|
|
{
|
|
|
|
}
|
|
|
|
if (ImGui::MenuItem(combineIcon("SDKs", ICON_NONE).c_str()))
|
|
{
|
|
|
|
}
|
|
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::Separator();
|
|
}
|
|
|
|
|
|
SceneAssetSaveWidget::SceneAssetSaveWidget(const std::string& titleName)
|
|
: ImGuiPopupSelfManagedOpenState(titleName, ImGuiWindowFlags_AlwaysAutoResize)
|
|
{
|
|
|
|
}
|
|
|
|
void SceneAssetSaveWidget::onDraw()
|
|
{
|
|
auto scenes = getAssetManager()->getDirtyAsset<Scene>();
|
|
|
|
// Current only support one scene edit.
|
|
CHECK(scenes.size() == 1);
|
|
|
|
auto scene = scenes[0].lock();
|
|
const bool bTemp = scene->getSaveInfo().isTemp();
|
|
|
|
if (m_processingAsset != scene->getSaveInfo())
|
|
{
|
|
m_processingAsset = scene->getSaveInfo();
|
|
m_bSelected = true;
|
|
}
|
|
|
|
ImGui::TextDisabled("Scene still un-save after edited, please decide discard or save.");
|
|
ImGui::NewLine();
|
|
ImGui::Indent();
|
|
{
|
|
std::string showName = Scene::uiGetAssetReflectionInfo().decoratedName + ": " + scene->getName() +
|
|
(bTemp ? "* (Created)" : "* (Edited)");
|
|
|
|
if (bTemp) ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor::HSV(0.15f, 0.6f, 1.0f));
|
|
{
|
|
ImGui::Checkbox("##HideCheckBox", &m_bSelected); ImGui::SameLine();
|
|
ImGui::Selectable(showName.c_str(), &m_bSelected, ImGuiSelectableFlags_DontClosePopups);
|
|
}
|
|
if (bTemp) ImGui::PopStyleColor();
|
|
}
|
|
ImGui::Unindent();
|
|
ImGui::NewLine();
|
|
ImGui::NewLine();
|
|
ImGui::NewLine();
|
|
|
|
bool bAccept = false;
|
|
|
|
if (ImGui::Button("Save", ImVec2(120, 0)))
|
|
{
|
|
bAccept = true;
|
|
if (m_bSelected)
|
|
{
|
|
if (bTemp)
|
|
{
|
|
std::string path;
|
|
|
|
const auto assetStartFolder = utf8::utf16to8(getAssetManager()->getProjectConfig().assetPath);
|
|
nfdchar_t* outPathChars;
|
|
|
|
std::string suffix = std::string(scene->getSuffix()).erase(0, 1) + "\0";
|
|
nfdchar_t* filterList = suffix.data();
|
|
nfdresult_t result = NFD_SaveDialog(filterList, assetStartFolder.c_str(), &outPathChars);
|
|
if (result == NFD_OKAY)
|
|
{
|
|
path = outPathChars;
|
|
free(outPathChars);
|
|
}
|
|
|
|
auto u16PathString = utf8::utf8to16(path);
|
|
std::filesystem::path fp(u16PathString);
|
|
if (!path.empty())
|
|
{
|
|
std::filesystem::path assetName = fp.filename();
|
|
std::string assetNameUtf8 = utf8::utf16to8(assetName.u16string()) + Scene::getCDO()->getSuffix();
|
|
|
|
const auto relativePath = buildRelativePathUtf8(getAssetManager()->getProjectConfig().assetPath, fp.remove_filename());
|
|
|
|
const AssetSaveInfo newInfo(assetNameUtf8, relativePath);
|
|
scene->changeSaveInfo(newInfo);
|
|
|
|
if (!scene->save())
|
|
{
|
|
LOG_ERROR("Fail to save new created scene {0} in path {1}.", scene->getName(), utf8::utf16to8(scene->getSavePath().u16string()));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!scene->save())
|
|
{
|
|
LOG_ERROR("Fail to save edited scene {0} in path {1}.", scene->getName(), utf8::utf16to8(scene->getSavePath().u16string()));
|
|
}
|
|
}
|
|
}
|
|
|
|
m_bSelected = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Discard", ImVec2(120, 0)))
|
|
{
|
|
bAccept = true;
|
|
if (m_bSelected)
|
|
{
|
|
const auto saveInfo = scene->getSaveInfo();
|
|
scene->discardChanged();
|
|
|
|
if (!saveInfo.isTemp())
|
|
{
|
|
// Reload src scene in disk.
|
|
getSceneManager()->loadScene(saveInfo.toPath());
|
|
}
|
|
}
|
|
m_bSelected = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (bAccept)
|
|
{
|
|
if (afterEventAccept)
|
|
{
|
|
afterEventAccept();
|
|
}
|
|
onClosed();
|
|
}
|
|
}
|
|
|
|
ContentAssetImportWidget::ContentAssetImportWidget(const std::string& titleName)
|
|
: ImGuiPopupSelfManagedOpenState(titleName, ImGuiWindowFlags_AlwaysAutoResize)
|
|
{
|
|
|
|
}
|
|
|
|
void ContentAssetImportWidget::onDraw()
|
|
{
|
|
if (m_bImporting)
|
|
{
|
|
onDrawImporting();
|
|
}
|
|
else
|
|
{
|
|
onDrawState();
|
|
}
|
|
}
|
|
|
|
void ContentAssetImportWidget::onDrawState()
|
|
{
|
|
CHECK(!importConfigs.empty());
|
|
CHECK(!typeName.empty());
|
|
|
|
auto type = rttr::type::get_by_name(typeName);
|
|
|
|
const auto& method = type.get_method("uiGetAssetReflectionInfo");
|
|
rttr::variant returnValue = method.invoke({});
|
|
const auto& meta = returnValue.get_value<AssetReflectionInfo>();
|
|
|
|
CHECK(meta.importConfig.drawAssetImportConfig);
|
|
for (auto& ptr : importConfigs)
|
|
{
|
|
meta.importConfig.drawAssetImportConfig(ptr);
|
|
}
|
|
|
|
bool bAccept = false;
|
|
|
|
if (ImGui::Button("OK", ImVec2(120, 0)))
|
|
{
|
|
m_bImporting = true;
|
|
{
|
|
CHECK(!m_importProgress.logHandle.isValid());
|
|
{
|
|
m_importProgress.logHandle = LoggerSystem::get()->pushCallback([&](const std::string& info, ELogType type)
|
|
{
|
|
m_importProgress.logItems.push_back({ type, info });
|
|
if (static_cast<uint32_t>(m_importProgress.logItems.size()) >= 60)
|
|
{
|
|
m_importProgress.logItems.pop_front();
|
|
}
|
|
});
|
|
}
|
|
|
|
CHECK(m_executeFutures.futures.empty());
|
|
{
|
|
auto type = rttr::type::get_by_name(typeName);
|
|
|
|
const auto& method = type.get_method("uiGetAssetReflectionInfo");
|
|
rttr::variant returnValue = method.invoke({});
|
|
const auto& meta = returnValue.get_value<AssetReflectionInfo>();
|
|
|
|
CHECK(meta.importConfig.importAssetFromConfigThreadSafe);
|
|
|
|
const auto loop = [this, meta](const size_t loopStart, const size_t loopEnd)
|
|
{
|
|
for (size_t i = loopStart; i < loopEnd; ++i)
|
|
{
|
|
meta.importConfig.importAssetFromConfigThreadSafe(importConfigs[i]);
|
|
}
|
|
};
|
|
m_executeFutures = Engine::get()->getThreadPool()->parallelizeLoop(0, importConfigs.size(), loop);
|
|
}
|
|
}
|
|
}
|
|
|
|
ImGui::SetItemDefaultFocus();
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Cancel", ImVec2(120, 0)))
|
|
{
|
|
bAccept = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (bAccept)
|
|
{
|
|
if (afterEventAccept)
|
|
{
|
|
afterEventAccept();
|
|
}
|
|
onClosed();
|
|
}
|
|
}
|
|
|
|
void ContentAssetImportWidget::onDrawImporting()
|
|
{
|
|
CHECK(!m_executeFutures.futures.empty());
|
|
CHECK(m_bImporting);
|
|
|
|
ImGui::Indent();
|
|
ImGui::Text("Asset Importing ... ");
|
|
ImGui::SameLine();
|
|
|
|
float progress = m_executeFutures.getProgress();
|
|
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
|
|
|
|
ImGui::Unindent();
|
|
ImGui::Separator();
|
|
|
|
ImGui::BeginDisabled();
|
|
for (int i = 0; i < m_importProgress.logItems.size(); i++)
|
|
{
|
|
ImVec4 color;
|
|
if (m_importProgress.logItems[i].first == ELogType::Error ||
|
|
m_importProgress.logItems[i].first == ELogType::Fatal)
|
|
{
|
|
color = ImVec4(1.0f, 0.08f, 0.08f, 1.0f);
|
|
}
|
|
else if (m_importProgress.logItems[i].first == ELogType::Warn)
|
|
{
|
|
color = ImVec4(1.0f, 1.0f, 0.1f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
|
|
|
|
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
|
ImGui::Selectable(m_importProgress.logItems[i].second.c_str());
|
|
ImGui::PopStyleColor();
|
|
}
|
|
ImGui::EndDisabled();
|
|
|
|
bool bAccept = false;
|
|
if (progress > 0.99f)
|
|
{
|
|
m_executeFutures.wait();
|
|
|
|
// Clean state.
|
|
m_bImporting = false;
|
|
m_executeFutures = {};
|
|
if (m_importProgress.logHandle.isValid())
|
|
{
|
|
LoggerSystem::get()->popCallback(m_importProgress.logHandle);
|
|
m_importProgress.logHandle.reset();
|
|
m_importProgress.logItems.clear();
|
|
}
|
|
|
|
bAccept = true;
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
|
|
if (bAccept)
|
|
{
|
|
if (afterEventAccept)
|
|
{
|
|
afterEventAccept();
|
|
}
|
|
onClosed();
|
|
}
|
|
}
|