mirror of https://github.com/AxioDL/metaforce.git
Add initial imgui implementation
This commit is contained in:
parent
94f10bb002
commit
1a5ec8b569
|
@ -58,3 +58,6 @@
|
||||||
path = extern/zeus
|
path = extern/zeus
|
||||||
url = ../zeus.git
|
url = ../zeus.git
|
||||||
branch = master
|
branch = master
|
||||||
|
[submodule "extern/imgui"]
|
||||||
|
path = extern/imgui
|
||||||
|
url = https://github.com/ocornut/imgui.git
|
||||||
|
|
|
@ -396,6 +396,7 @@ add_subdirectory(extern/boo)
|
||||||
add_subdirectory(hecl/shaderc)
|
add_subdirectory(hecl/shaderc)
|
||||||
include(hecl/ApplicationTools.cmake)
|
include(hecl/ApplicationTools.cmake)
|
||||||
add_subdirectory(Shaders)
|
add_subdirectory(Shaders)
|
||||||
|
add_subdirectory(imgui)
|
||||||
add_subdirectory(extern/libSquish)
|
add_subdirectory(extern/libSquish)
|
||||||
add_subdirectory(extern/libpng)
|
add_subdirectory(extern/libpng)
|
||||||
add_subdirectory(extern/libjpeg-turbo)
|
add_subdirectory(extern/libjpeg-turbo)
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <iostream>
|
|
||||||
#include <hecl/Pipeline.hpp>
|
#include <hecl/Pipeline.hpp>
|
||||||
|
|
||||||
#include "boo/boo.hpp"
|
#include "boo/boo.hpp"
|
||||||
#include "logvisor/logvisor.hpp"
|
#include "logvisor/logvisor.hpp"
|
||||||
|
|
||||||
|
#include "ImGuiEngine.hpp"
|
||||||
#include "Runtime/Graphics/CGraphics.hpp"
|
#include "Runtime/Graphics/CGraphics.hpp"
|
||||||
#include "Runtime/MP1/MP1.hpp"
|
#include "Runtime/MP1/MP1.hpp"
|
||||||
#include "cmake-build-debug-llvm/hecl/DataSpecRegistry.hpp"
|
|
||||||
#include "amuse/BooBackend.hpp"
|
#include "amuse/BooBackend.hpp"
|
||||||
|
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
|
/* Static reference to dataspec additions
|
||||||
|
* (used by MSVC to definitively link DataSpecs) */
|
||||||
|
#include "DataSpecRegistry.hpp"
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
static logvisor::Module AthenaLog("Athena");
|
static logvisor::Module AthenaLog("Athena");
|
||||||
|
@ -104,10 +108,14 @@ static hecl::SystemString CPUFeatureString(const zeus::CPUInfo& cpuInf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WindowCallback : boo::IWindowCallback {
|
struct WindowCallback : boo::IWindowCallback {
|
||||||
|
friend struct Application;
|
||||||
|
|
||||||
|
private:
|
||||||
bool m_fullscreenToggleRequested = false;
|
bool m_fullscreenToggleRequested = false;
|
||||||
boo::SWindowRect m_lastRect;
|
boo::SWindowRect m_lastRect;
|
||||||
bool m_rectDirty = false;
|
bool m_rectDirty = false;
|
||||||
bool m_windowInvalid = false;
|
bool m_windowInvalid = false;
|
||||||
|
ImGuiWindowCallback m_imguiCallback;
|
||||||
|
|
||||||
void resized(const boo::SWindowRect& rect, bool sync) override {
|
void resized(const boo::SWindowRect& rect, bool sync) override {
|
||||||
m_lastRect = rect;
|
m_lastRect = rect;
|
||||||
|
@ -115,11 +123,12 @@ struct WindowCallback : boo::IWindowCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) override {
|
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) override {
|
||||||
if (g_mainMP1) {
|
if (!ImGuiWindowCallback::m_mouseCaptured && g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
||||||
as->mouseDown(coord, button, mods);
|
as->mouseDown(coord, button, mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.mouseDown(coord, button, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) override {
|
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) override {
|
||||||
|
@ -128,30 +137,38 @@ struct WindowCallback : boo::IWindowCallback {
|
||||||
as->mouseUp(coord, button, mods);
|
as->mouseUp(coord, button, mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.mouseUp(coord, button, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseMove(const boo::SWindowCoord& coord) override {
|
void mouseMove(const boo::SWindowCoord& coord) override {
|
||||||
if (g_mainMP1) {
|
if (!ImGuiWindowCallback::m_mouseCaptured && g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
||||||
as->mouseMove(coord);
|
as->mouseMove(coord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.mouseMove(coord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mouseEnter(const boo::SWindowCoord& coord) override { m_imguiCallback.mouseEnter(coord); }
|
||||||
|
|
||||||
|
void mouseLeave(const boo::SWindowCoord& coord) override { m_imguiCallback.mouseLeave(coord); }
|
||||||
|
|
||||||
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) override {
|
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) override {
|
||||||
if (g_mainMP1) {
|
if (!ImGuiWindowCallback::m_mouseCaptured && g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
||||||
as->scroll(coord, scroll);
|
as->scroll(coord, scroll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.scroll(coord, scroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) override {
|
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) override {
|
||||||
if (g_mainMP1) {
|
if (!ImGuiWindowCallback::m_keyboardCaptured && g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
||||||
as->charKeyDown(charCode, mods, isRepeat);
|
as->charKeyDown(charCode, mods, isRepeat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.charKeyDown(charCode, mods, isRepeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void charKeyUp(unsigned long charCode, boo::EModifierKey mods) override {
|
void charKeyUp(unsigned long charCode, boo::EModifierKey mods) override {
|
||||||
|
@ -160,16 +177,19 @@ struct WindowCallback : boo::IWindowCallback {
|
||||||
as->charKeyUp(charCode, mods);
|
as->charKeyUp(charCode, mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.charKeyUp(charCode, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) override {
|
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) override {
|
||||||
if (g_mainMP1) {
|
if (!ImGuiWindowCallback::m_keyboardCaptured && g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
||||||
as->specialKeyDown(key, mods, isRepeat);
|
as->specialKeyDown(key, mods, isRepeat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key == boo::ESpecialKey::Enter && True(mods & boo::EModifierKey::Alt))
|
if (key == boo::ESpecialKey::Enter && True(mods & boo::EModifierKey::Alt)) {
|
||||||
m_fullscreenToggleRequested = true;
|
m_fullscreenToggleRequested = true;
|
||||||
|
}
|
||||||
|
m_imguiCallback.specialKeyDown(key, mods, isRepeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) override {
|
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) override {
|
||||||
|
@ -178,12 +198,14 @@ struct WindowCallback : boo::IWindowCallback {
|
||||||
as->specialKeyUp(key, mods);
|
as->specialKeyUp(key, mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
m_imguiCallback.specialKeyUp(key, mods);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyed() override { m_windowInvalid = true; }
|
void destroyed() override { m_windowInvalid = true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Application : boo::IApplicationCallback {
|
struct Application : boo::IApplicationCallback {
|
||||||
|
private:
|
||||||
std::shared_ptr<boo::IWindow> m_window;
|
std::shared_ptr<boo::IWindow> m_window;
|
||||||
WindowCallback m_windowCallback;
|
WindowCallback m_windowCallback;
|
||||||
hecl::Runtime::FileStoreManager& m_fileMgr;
|
hecl::Runtime::FileStoreManager& m_fileMgr;
|
||||||
|
@ -201,6 +223,10 @@ struct Application : boo::IApplicationCallback {
|
||||||
std::atomic_bool m_running = {true};
|
std::atomic_bool m_running = {true};
|
||||||
bool m_noShaderWarmup = false;
|
bool m_noShaderWarmup = false;
|
||||||
|
|
||||||
|
bool m_firstFrame = true;
|
||||||
|
using delta_clock = std::chrono::high_resolution_clock;
|
||||||
|
std::chrono::time_point<delta_clock> m_prevFrameTime;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Application(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCmns)
|
Application(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCmns)
|
||||||
: m_fileMgr(fileMgr), m_cvarManager(cvarMgr), m_cvarCommons(cvarCmns) {}
|
: m_fileMgr(fileMgr), m_cvarManager(cvarMgr), m_cvarCommons(cvarCmns) {}
|
||||||
|
@ -216,12 +242,13 @@ public:
|
||||||
m_window->showWindow();
|
m_window->showWindow();
|
||||||
|
|
||||||
boo::SWindowRect rect = m_window->getWindowFrame();
|
boo::SWindowRect rect = m_window->getWindowFrame();
|
||||||
m_window->getMainContextDataFactory()->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
|
boo::IGraphicsDataFactory* gfxF = m_window->getMainContextDataFactory();
|
||||||
|
gfxF->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||||
m_renderTex = ctx.newRenderTexture(rect.size[0], rect.size[1], boo::TextureClampMode::ClampToEdge, 3, 3);
|
m_renderTex = ctx.newRenderTexture(rect.size[0], rect.size[1], boo::TextureClampMode::ClampToEdge, 3, 3);
|
||||||
return true;
|
return true;
|
||||||
} BooTrace);
|
} BooTrace);
|
||||||
|
|
||||||
m_pipelineConv = hecl::NewPipelineConverter(m_window->getMainContextDataFactory());
|
m_pipelineConv = hecl::NewPipelineConverter(gfxF);
|
||||||
hecl::conv = m_pipelineConv.get();
|
hecl::conv = m_pipelineConv.get();
|
||||||
|
|
||||||
m_voiceEngine = boo::NewAudioVoiceEngine();
|
m_voiceEngine = boo::NewAudioVoiceEngine();
|
||||||
|
@ -258,6 +285,7 @@ public:
|
||||||
onAppIdle();
|
onAppIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGuiEngine::Shutdown();
|
||||||
if (m_window) {
|
if (m_window) {
|
||||||
m_window->getCommandQueue()->stopRenderer();
|
m_window->getCommandQueue()->stopRenderer();
|
||||||
}
|
}
|
||||||
|
@ -329,29 +357,60 @@ public:
|
||||||
m_windowCallback.m_fullscreenToggleRequested = false;
|
m_windowCallback.m_fullscreenToggleRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boo::IGraphicsDataFactory* gfxF = m_window->getMainContextDataFactory();
|
||||||
if (!g_mainMP1) {
|
if (!g_mainMP1) {
|
||||||
g_mainMP1.emplace(nullptr, nullptr, m_window->getMainContextDataFactory(), gfxQ, m_renderTex.get());
|
g_mainMP1.emplace(nullptr, nullptr, gfxF, gfxQ, m_renderTex.get());
|
||||||
g_mainMP1->Init(m_fileMgr, &m_cvarManager, m_window.get(), m_voiceEngine.get(), *m_amuseAllocWrapper);
|
g_mainMP1->Init(m_fileMgr, &m_cvarManager, m_window.get(), m_voiceEngine.get(), *m_amuseAllocWrapper);
|
||||||
if (!m_noShaderWarmup) {
|
if (!m_noShaderWarmup) {
|
||||||
g_mainMP1->WarmupShaders();
|
g_mainMP1->WarmupShaders();
|
||||||
}
|
}
|
||||||
|
ImGuiEngine::Initialize(gfxF, m_window->getWindowFrame());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_mainMP1->Proc()) {
|
float dt = 1 / 60.f;
|
||||||
|
float realDt = dt;
|
||||||
|
auto now = delta_clock::now();
|
||||||
|
if (m_firstFrame) {
|
||||||
|
m_firstFrame = false;
|
||||||
|
} else {
|
||||||
|
using delta_duration = std::chrono::duration<float, std::ratio<1>>;
|
||||||
|
realDt = std::chrono::duration_cast<delta_duration>(now - m_prevFrameTime).count();
|
||||||
|
if (m_cvarCommons.m_variableDt->toBoolean()) {
|
||||||
|
dt = std::min(realDt, 1 / 30.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_prevFrameTime = now;
|
||||||
|
|
||||||
|
ImGuiEngine::Begin(realDt);
|
||||||
|
|
||||||
|
if (g_mainMP1->Proc(dt)) {
|
||||||
m_running.store(false);
|
m_running.store(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxQ->setRenderTarget(m_renderTex);
|
|
||||||
{
|
{
|
||||||
OPTICK_EVENT("Draw");
|
OPTICK_EVENT("Draw");
|
||||||
if (g_Renderer)
|
gfxQ->setRenderTarget(m_renderTex);
|
||||||
|
if (g_Renderer != nullptr) {
|
||||||
g_Renderer->BeginScene();
|
g_Renderer->BeginScene();
|
||||||
|
}
|
||||||
g_mainMP1->Draw();
|
g_mainMP1->Draw();
|
||||||
if (g_Renderer)
|
if (g_Renderer != nullptr) {
|
||||||
g_Renderer->EndScene();
|
g_Renderer->EndScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
OPTICK_EVENT("ImGui Draw");
|
||||||
|
ImGuiEngine::End();
|
||||||
|
ImGuiEngine::Draw(gfxQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
OPTICK_EVENT("Execute");
|
||||||
gfxQ->execute();
|
gfxQ->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxQ->resolveDisplay(m_renderTex);
|
gfxQ->resolveDisplay(m_renderTex);
|
||||||
|
|
||||||
if (g_ResFactory != nullptr) {
|
if (g_ResFactory != nullptr) {
|
||||||
|
@ -380,7 +439,9 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }
|
[[nodiscard]] bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }
|
||||||
|
|
||||||
[[nodiscard]] int64_t getTargetFrameTime() const { return m_cvarCommons.getVariableFrameTime() ? 0 : 1000000000L / 60; }
|
[[nodiscard]] int64_t getTargetFrameTime() const {
|
||||||
|
return m_cvarCommons.getVariableFrameTime() ? 0 : 1000000000L / 60;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -201,7 +201,7 @@ elseif(UNIX)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(metaforce CMain.cpp ${PLAT_SRCS})
|
add_executable(metaforce CMain.cpp ${PLAT_SRCS})
|
||||||
target_link_libraries(metaforce PUBLIC RuntimeCommon ${PLAT_LIBS})
|
target_link_libraries(metaforce PUBLIC RuntimeCommon ${PLAT_LIBS} imgui)
|
||||||
|
|
||||||
if(COMMAND add_sanitizers)
|
if(COMMAND add_sanitizers)
|
||||||
add_sanitizers(metaforce)
|
add_sanitizers(metaforce)
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
virtual void Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarMgr, boo::IWindow* window,
|
virtual void Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarMgr, boo::IWindow* window,
|
||||||
boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) = 0;
|
boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) = 0;
|
||||||
virtual void Draw() = 0;
|
virtual void Draw() = 0;
|
||||||
virtual bool Proc() = 0;
|
virtual bool Proc(float dt) = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
virtual boo::IWindow* GetMainWindow() const = 0;
|
virtual boo::IWindow* GetMainWindow() const = 0;
|
||||||
virtual EFlowState GetFlowState() const = 0;
|
virtual EFlowState GetFlowState() const = 0;
|
||||||
|
|
|
@ -897,7 +897,7 @@ void CMain::WarmupShaders() {
|
||||||
WarmupLog.report(logvisor::Info, FMT_STRING("Began warmup of {} objects"), m_warmupTags.size());
|
WarmupLog.report(logvisor::Info, FMT_STRING("Began warmup of {} objects"), m_warmupTags.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CMain::Proc() {
|
bool CMain::Proc(float dt) {
|
||||||
CRandom16::ResetNumNextCalls();
|
CRandom16::ResetNumNextCalls();
|
||||||
// Warmup cycle overrides update
|
// Warmup cycle overrides update
|
||||||
if (m_warmupTags.size())
|
if (m_warmupTags.size())
|
||||||
|
@ -907,18 +907,6 @@ bool CMain::Proc() {
|
||||||
m_loadedPersistentResources = true;
|
m_loadedPersistentResources = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
float dt = 1 / 60.f;
|
|
||||||
if (m_cvarCommons->m_variableDt->toBoolean()) {
|
|
||||||
auto now = delta_clock::now();
|
|
||||||
if (m_firstFrame) {
|
|
||||||
m_firstFrame = false;
|
|
||||||
} else {
|
|
||||||
using delta_duration = std::chrono::duration<float, std::ratio<1>>;
|
|
||||||
dt = std::min(std::chrono::duration_cast<delta_duration>(now - m_prevFrameTime).count(), 1 / 30.f);
|
|
||||||
}
|
|
||||||
m_prevFrameTime = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_console->proc();
|
m_console->proc();
|
||||||
if (!m_console->isOpen()) {
|
if (!m_console->isOpen()) {
|
||||||
CGBASupport::GlobalPoll();
|
CGBASupport::GlobalPoll();
|
||||||
|
|
|
@ -253,10 +253,6 @@ private:
|
||||||
bool m_needsWarmupClear = false;
|
bool m_needsWarmupClear = false;
|
||||||
bool m_loadedPersistentResources = false;
|
bool m_loadedPersistentResources = false;
|
||||||
bool m_doQuit = false;
|
bool m_doQuit = false;
|
||||||
|
|
||||||
bool m_firstFrame = true;
|
|
||||||
using delta_clock = std::chrono::high_resolution_clock;
|
|
||||||
std::chrono::time_point<delta_clock> m_prevFrameTime;
|
|
||||||
DataSpec::MetaforceVersionInfo m_version;
|
DataSpec::MetaforceVersionInfo m_version;
|
||||||
|
|
||||||
void InitializeSubsystems();
|
void InitializeSubsystems();
|
||||||
|
@ -286,7 +282,7 @@ public:
|
||||||
void Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarManager, boo::IWindow* window,
|
void Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarManager, boo::IWindow* window,
|
||||||
boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) override;
|
boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) override;
|
||||||
void WarmupShaders() override;
|
void WarmupShaders() override;
|
||||||
bool Proc() override;
|
bool Proc(float dt) override;
|
||||||
void Draw() override;
|
void Draw() override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
boo::IWindow* GetMainWindow() const override;
|
boo::IWindow* GetMainWindow() const override;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 55deba091336b787d405a8747bff9757713e7960
|
Subproject commit d13fbda0c0ef0a832ed31ab4a7e91a23c6167f52
|
|
@ -40,6 +40,7 @@ set(HECL_HEADERS
|
||||||
../include/hecl/MathExtras.hpp
|
../include/hecl/MathExtras.hpp
|
||||||
../include/hecl/UniformBufferPool.hpp
|
../include/hecl/UniformBufferPool.hpp
|
||||||
../include/hecl/VertexBufferPool.hpp
|
../include/hecl/VertexBufferPool.hpp
|
||||||
|
../include/hecl/IndexBufferPool.hpp
|
||||||
../include/hecl/PipelineBase.hpp
|
../include/hecl/PipelineBase.hpp
|
||||||
../include/hecl/Pipeline.hpp
|
../include/hecl/Pipeline.hpp
|
||||||
../include/hecl/Compilers.hpp)
|
../include/hecl/Compilers.hpp)
|
||||||
|
|
|
@ -537,6 +537,9 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName,
|
||||||
fmt::print(out.second, FMT_STRING("static const boo::VertexElementDescriptor {}_vtxfmtelems[] = {{\n"), shaderName);
|
fmt::print(out.second, FMT_STRING("static const boo::VertexElementDescriptor {}_vtxfmtelems[] = {{\n"), shaderName);
|
||||||
for (const auto& attr : shaderAttributes) {
|
for (const auto& attr : shaderAttributes) {
|
||||||
switch (attr.first & boo::VertexSemantic::SemanticMask) {
|
switch (attr.first & boo::VertexSemantic::SemanticMask) {
|
||||||
|
case boo::VertexSemantic::Position2:
|
||||||
|
SemanticOut(out.second, attr, FMT_STRING("{{boo::VertexSemantic::Position2{}, {}}},\n"));
|
||||||
|
break;
|
||||||
case boo::VertexSemantic::Position3:
|
case boo::VertexSemantic::Position3:
|
||||||
SemanticOut(out.second, attr, FMT_STRING("{{boo::VertexSemantic::Position3{}, {}}},\n"));
|
SemanticOut(out.second, attr, FMT_STRING("{{boo::VertexSemantic::Position3{}, {}}},\n"));
|
||||||
break;
|
break;
|
||||||
|
@ -611,7 +614,9 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName,
|
||||||
boo::VertexSemantic orsem = inst ? boo::VertexSemantic::Instanced : boo::VertexSemantic::None;
|
boo::VertexSemantic orsem = inst ? boo::VertexSemantic::Instanced : boo::VertexSemantic::None;
|
||||||
int idxNum = int(strtoul(idx.c_str(), nullptr, 10));
|
int idxNum = int(strtoul(idx.c_str(), nullptr, 10));
|
||||||
std::transform(semantic.begin(), semantic.end(), semantic.begin(), ::tolower);
|
std::transform(semantic.begin(), semantic.end(), semantic.begin(), ::tolower);
|
||||||
if (semantic == "position3")
|
if (semantic == "position2")
|
||||||
|
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::Position2 | orsem, idxNum));
|
||||||
|
else if (semantic == "position3")
|
||||||
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::Position3 | orsem, idxNum));
|
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::Position3 | orsem, idxNum));
|
||||||
else if (semantic == "position4")
|
else if (semantic == "position4")
|
||||||
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::Position4 | orsem, idxNum));
|
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::Position4 | orsem, idxNum));
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
add_library(imgui
|
||||||
|
../extern/imgui/imgui.cpp
|
||||||
|
../extern/imgui/imgui_demo.cpp
|
||||||
|
../extern/imgui/imgui_draw.cpp
|
||||||
|
../extern/imgui/imgui_tables.cpp
|
||||||
|
../extern/imgui/imgui_widgets.cpp
|
||||||
|
../extern/imgui/backends/imgui_impl_vulkan.cpp
|
||||||
|
ImGuiEngine.cpp
|
||||||
|
ImGuiEngine.hpp
|
||||||
|
)
|
||||||
|
target_include_directories(imgui PUBLIC ../extern/imgui ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
target_compile_definitions(imgui PUBLIC IMGUI_USER_CONFIG="imconfig_user.h")
|
||||||
|
target_link_libraries(imgui PRIVATE boo hecl-light RetroDataSpec)
|
||||||
|
|
||||||
|
add_shader(ImguiShader)
|
||||||
|
target_link_libraries(shader_ImguiShader PRIVATE hecl-light)
|
|
@ -0,0 +1,286 @@
|
||||||
|
#include "ImGuiEngine.hpp"
|
||||||
|
|
||||||
|
#include "hecl/Pipeline.hpp"
|
||||||
|
#include "hecl/VertexBufferPool.hpp"
|
||||||
|
|
||||||
|
#include <zeus/CMatrix4f.hpp>
|
||||||
|
|
||||||
|
namespace metaforce {
|
||||||
|
static logvisor::Module Log{"ImGuiEngine"};
|
||||||
|
|
||||||
|
struct ImGuiEngine::Input ImGuiEngine::Input;
|
||||||
|
|
||||||
|
static boo::IGraphicsDataFactory* m_factory;
|
||||||
|
static boo::ObjToken<boo::IShaderPipeline> ShaderPipeline;
|
||||||
|
static boo::ObjToken<boo::IGraphicsBufferD> VertexBuffer;
|
||||||
|
static boo::ObjToken<boo::IGraphicsBufferD> IndexBuffer;
|
||||||
|
static boo::ObjToken<boo::IGraphicsBufferD> UniformBuffer;
|
||||||
|
static boo::ObjToken<boo::IShaderDataBinding> ShaderDataBinding;
|
||||||
|
static boo::ObjToken<boo::ITextureS> ImGuiAtlas;
|
||||||
|
static boo::SWindowRect WindowRect;
|
||||||
|
|
||||||
|
struct Uniform {
|
||||||
|
zeus::CMatrix4f xf;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t VertexBufferSize = 5000;
|
||||||
|
static size_t IndexBufferSize = 5000;
|
||||||
|
|
||||||
|
void ImGuiEngine::Initialize(boo::IGraphicsDataFactory* factory, const boo::SWindowRect& rect) {
|
||||||
|
m_factory = factory;
|
||||||
|
WindowRect = rect;
|
||||||
|
|
||||||
|
ImGui::CreateContext();
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;
|
||||||
|
io.KeyMap[ImGuiKey_Tab] = 256 + static_cast<int>(boo::ESpecialKey::Tab);
|
||||||
|
io.KeyMap[ImGuiKey_LeftArrow] = 256 + static_cast<int>(boo::ESpecialKey::Left);
|
||||||
|
io.KeyMap[ImGuiKey_RightArrow] = 256 + static_cast<int>(boo::ESpecialKey::Right);
|
||||||
|
io.KeyMap[ImGuiKey_UpArrow] = 256 + static_cast<int>(boo::ESpecialKey::Up);
|
||||||
|
io.KeyMap[ImGuiKey_DownArrow] = 256 + static_cast<int>(boo::ESpecialKey::Down);
|
||||||
|
io.KeyMap[ImGuiKey_PageUp] = 256 + static_cast<int>(boo::ESpecialKey::PgUp);
|
||||||
|
io.KeyMap[ImGuiKey_PageDown] = 256 + static_cast<int>(boo::ESpecialKey::PgDown);
|
||||||
|
io.KeyMap[ImGuiKey_Home] = 256 + static_cast<int>(boo::ESpecialKey::Home);
|
||||||
|
io.KeyMap[ImGuiKey_End] = 256 + static_cast<int>(boo::ESpecialKey::End);
|
||||||
|
io.KeyMap[ImGuiKey_Insert] = 256 + static_cast<int>(boo::ESpecialKey::Insert);
|
||||||
|
io.KeyMap[ImGuiKey_Delete] = 256 + static_cast<int>(boo::ESpecialKey::Delete);
|
||||||
|
io.KeyMap[ImGuiKey_Backspace] = 256 + static_cast<int>(boo::ESpecialKey::Backspace);
|
||||||
|
io.KeyMap[ImGuiKey_Space] = ' ';
|
||||||
|
io.KeyMap[ImGuiKey_Enter] = 256 + static_cast<int>(boo::ESpecialKey::Enter);
|
||||||
|
io.KeyMap[ImGuiKey_Escape] = 256 + static_cast<int>(boo::ESpecialKey::Esc);
|
||||||
|
io.KeyMap[ImGuiKey_A] = 'A'; // for text edit CTRL+A: select all
|
||||||
|
io.KeyMap[ImGuiKey_C] = 'C'; // for text edit CTRL+C: copy
|
||||||
|
io.KeyMap[ImGuiKey_V] = 'V'; // for text edit CTRL+V: paste
|
||||||
|
io.KeyMap[ImGuiKey_X] = 'X'; // for text edit CTRL+X: cut
|
||||||
|
io.KeyMap[ImGuiKey_Y] = 'Y'; // for text edit CTRL+Y: redo
|
||||||
|
io.KeyMap[ImGuiKey_Z] = 'Z'; // for text edit CTRL+Z: undo
|
||||||
|
|
||||||
|
int width = 0;
|
||||||
|
int height = 0;
|
||||||
|
unsigned char* pixels = nullptr;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||||
|
factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||||
|
ShaderPipeline = hecl::conv->convert(Shader_ImguiShader{});
|
||||||
|
ImGuiAtlas = ctx.newStaticTexture(width, height, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::ClampToEdge,
|
||||||
|
pixels, width * height * 4);
|
||||||
|
VertexBuffer = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(ImDrawVert), VertexBufferSize);
|
||||||
|
IndexBuffer = ctx.newDynamicBuffer(boo::BufferUse::Index, sizeof(ImDrawIdx), IndexBufferSize);
|
||||||
|
UniformBuffer = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
|
||||||
|
BuildShaderDataBinding(ctx);
|
||||||
|
return true;
|
||||||
|
} BooTrace);
|
||||||
|
io.Fonts->SetTexID(ImGuiAtlas.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiEngine::Shutdown() {
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
ShaderPipeline.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiEngine::Begin(float dt) {
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
io.DeltaTime = dt;
|
||||||
|
io.DisplaySize.x = WindowRect.size[0];
|
||||||
|
io.DisplaySize.y = WindowRect.size[1];
|
||||||
|
// TODO
|
||||||
|
// io.DisplayFramebufferScale = ImVec2{1.f, 1.f};
|
||||||
|
if (Input.m_mouseIn) {
|
||||||
|
io.MousePos = ImVec2{static_cast<float>(Input.m_mousePos.pixel[0]),
|
||||||
|
static_cast<float>(WindowRect.size[1] - Input.m_mousePos.pixel[1])};
|
||||||
|
} else {
|
||||||
|
io.MousePos = ImVec2{-FLT_MAX, -FLT_MAX};
|
||||||
|
}
|
||||||
|
memcpy(io.MouseDown, Input.m_mouseButtons.data(), sizeof(io.MouseDown));
|
||||||
|
io.MouseWheel = static_cast<float>(Input.m_scrollDelta.delta[1]);
|
||||||
|
io.MouseWheelH = static_cast<float>(Input.m_scrollDelta.delta[0]);
|
||||||
|
Input.m_scrollDelta.zeroOut();
|
||||||
|
io.KeyCtrl = True(Input.m_modifiers & boo::EModifierKey::Ctrl);
|
||||||
|
io.KeyShift = True(Input.m_modifiers & boo::EModifierKey::Shift);
|
||||||
|
io.KeyAlt = True(Input.m_modifiers & boo::EModifierKey::Alt);
|
||||||
|
io.KeySuper = True(Input.m_modifiers & boo::EModifierKey::Command);
|
||||||
|
memcpy(io.KeysDown, Input.m_keys.data(), sizeof(io.KeysDown));
|
||||||
|
|
||||||
|
for (const auto c : ImGuiEngine::Input.m_charCodes) {
|
||||||
|
io.AddInputCharacter(c);
|
||||||
|
}
|
||||||
|
ImGuiEngine::Input.m_charCodes.clear();
|
||||||
|
|
||||||
|
ImGuiWindowCallback::m_mouseCaptured = io.WantCaptureMouse;
|
||||||
|
ImGuiWindowCallback::m_keyboardCaptured = io.WantCaptureKeyboard;
|
||||||
|
|
||||||
|
ImGui::NewFrame();
|
||||||
|
ImGui::ShowDemoWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiEngine::End() {
|
||||||
|
ImGui::EndFrame();
|
||||||
|
ImGui::Render();
|
||||||
|
ImDrawData* drawData = ImGui::GetDrawData();
|
||||||
|
|
||||||
|
float L = drawData->DisplayPos.x;
|
||||||
|
float R = drawData->DisplayPos.x + drawData->DisplaySize.x;
|
||||||
|
float T = drawData->DisplayPos.y;
|
||||||
|
float B = drawData->DisplayPos.y + drawData->DisplaySize.y;
|
||||||
|
float N = 0.f;
|
||||||
|
float F = 1.f;
|
||||||
|
zeus::CMatrix4f projXf = zeus::CMatrix4f{
|
||||||
|
zeus::CVector4f{2.0f / (R - L), 0.0f, 0.0f, 0.0f},
|
||||||
|
zeus::CVector4f{0.0f, 2.0f / (T - B), 0.0f, 0.0f},
|
||||||
|
zeus::CVector4f{0.0f, 0.0f, 1 / (F - N), 0.0f},
|
||||||
|
zeus::CVector4f{(R + L) / (L - R), (T + B) / (B - T), N / (F - N), 1.0f},
|
||||||
|
};
|
||||||
|
|
||||||
|
m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
|
||||||
|
bool rebind = false;
|
||||||
|
if (drawData->TotalIdxCount > IndexBufferSize) {
|
||||||
|
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Resizing index buffer from {} to {}")), IndexBufferSize,
|
||||||
|
drawData->TotalIdxCount);
|
||||||
|
IndexBuffer = ctx.newDynamicBuffer(boo::BufferUse::Index, sizeof(ImDrawIdx), drawData->TotalIdxCount);
|
||||||
|
IndexBufferSize = drawData->TotalIdxCount;
|
||||||
|
rebind = true;
|
||||||
|
}
|
||||||
|
if (drawData->TotalVtxCount > VertexBufferSize) {
|
||||||
|
Log.report(logvisor::Info, FMT_STRING(_SYS_STR("Resizing vertex buffer from {} to {}")), VertexBufferSize,
|
||||||
|
drawData->TotalVtxCount);
|
||||||
|
VertexBuffer = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(ImDrawVert), drawData->TotalVtxCount);
|
||||||
|
VertexBufferSize = drawData->TotalVtxCount;
|
||||||
|
rebind = true;
|
||||||
|
}
|
||||||
|
if (rebind) {
|
||||||
|
BuildShaderDataBinding(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
UniformBuffer->load(&projXf, sizeof(Uniform));
|
||||||
|
auto* vtxBuf = static_cast<ImDrawVert*>(VertexBuffer->map(drawData->TotalVtxCount * sizeof(ImDrawVert)));
|
||||||
|
auto* idxBuf = static_cast<ImDrawIdx*>(IndexBuffer->map(drawData->TotalIdxCount * sizeof(ImDrawIdx)));
|
||||||
|
|
||||||
|
for (int i = 0; i < drawData->CmdListsCount; ++i) {
|
||||||
|
const auto* cmdList = drawData->CmdLists[i];
|
||||||
|
int vtxBufferSz = cmdList->VtxBuffer.size();
|
||||||
|
int idxBufferSz = cmdList->IdxBuffer.size();
|
||||||
|
memcpy(vtxBuf, cmdList->VtxBuffer.begin(), vtxBufferSz * sizeof(ImDrawVert));
|
||||||
|
memcpy(idxBuf, cmdList->IdxBuffer.begin(), idxBufferSz * sizeof(ImDrawIdx));
|
||||||
|
vtxBuf += vtxBufferSz;
|
||||||
|
idxBuf += idxBufferSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexBuffer->unmap();
|
||||||
|
IndexBuffer->unmap();
|
||||||
|
return true;
|
||||||
|
} BooTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiEngine::Draw(boo::IGraphicsCommandQueue* gfxQ) {
|
||||||
|
ImDrawData* drawData = ImGui::GetDrawData();
|
||||||
|
|
||||||
|
gfxQ->setShaderDataBinding(ShaderDataBinding);
|
||||||
|
|
||||||
|
boo::SWindowRect viewportRect = WindowRect;
|
||||||
|
int viewportHeight = viewportRect.size[1];
|
||||||
|
viewportRect.location = {0, 0};
|
||||||
|
if (m_factory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan) {
|
||||||
|
viewportRect.location[1] = viewportHeight;
|
||||||
|
viewportRect.size[1] = -viewportHeight;
|
||||||
|
}
|
||||||
|
gfxQ->setViewport(viewportRect);
|
||||||
|
|
||||||
|
size_t idxOffset = 0;
|
||||||
|
size_t vtxOffset = 0;
|
||||||
|
for (int i = 0; i < drawData->CmdListsCount; ++i) {
|
||||||
|
const auto* cmdList = drawData->CmdLists[i];
|
||||||
|
for (const auto& drawCmd : cmdList->CmdBuffer) {
|
||||||
|
if (drawCmd.UserCallback != nullptr) {
|
||||||
|
drawCmd.UserCallback(cmdList, &drawCmd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ImVec2 pos = drawData->DisplayPos;
|
||||||
|
int clipX = static_cast<int>(drawCmd.ClipRect.x - pos.x);
|
||||||
|
int clipY = static_cast<int>(drawCmd.ClipRect.y - pos.y);
|
||||||
|
int clipW = static_cast<int>(drawCmd.ClipRect.z - pos.x) - clipX;
|
||||||
|
int clipH = static_cast<int>(drawCmd.ClipRect.w - pos.y) - clipY;
|
||||||
|
boo::SWindowRect clipRect{clipX, clipY, clipW, clipH};
|
||||||
|
if (m_factory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan) {
|
||||||
|
clipRect.location[1] = viewportHeight - clipRect.location[1] - clipRect.size[1];
|
||||||
|
}
|
||||||
|
gfxQ->setScissor(clipRect);
|
||||||
|
gfxQ->drawIndexed(idxOffset + drawCmd.IdxOffset, drawCmd.ElemCount, vtxOffset + drawCmd.VtxOffset);
|
||||||
|
}
|
||||||
|
idxOffset += cmdList->IdxBuffer.size();
|
||||||
|
vtxOffset += cmdList->VtxBuffer.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiEngine::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx) {
|
||||||
|
boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {UniformBuffer.get()};
|
||||||
|
boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex};
|
||||||
|
size_t unioffs[] = {0};
|
||||||
|
size_t unisizes[] = {sizeof(Uniform)};
|
||||||
|
boo::ObjToken<boo::ITexture> texs[] = {ImGuiAtlas.get()};
|
||||||
|
ShaderDataBinding = ctx.newShaderDataBinding(ShaderPipeline, VertexBuffer.get(), nullptr, IndexBuffer.get(), 1,
|
||||||
|
uniforms, unistages, unioffs, unisizes, 1, texs, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGuiWindowCallback::m_mouseCaptured = false;
|
||||||
|
bool ImGuiWindowCallback::m_keyboardCaptured = false;
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
|
||||||
|
ImGuiEngine::Input.m_mousePos = coord;
|
||||||
|
if (button != boo::EMouseButton::None) {
|
||||||
|
ImGuiEngine::Input.m_mouseButtons[static_cast<size_t>(button) - 1] = true;
|
||||||
|
}
|
||||||
|
ImGuiEngine::Input.m_modifiers = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) {
|
||||||
|
ImGuiEngine::Input.m_mousePos = coord;
|
||||||
|
if (button != boo::EMouseButton::None) {
|
||||||
|
ImGuiEngine::Input.m_mouseButtons[static_cast<size_t>(button) - 1] = false;
|
||||||
|
}
|
||||||
|
ImGuiEngine::Input.m_modifiers = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::mouseMove(const boo::SWindowCoord& coord) { ImGuiEngine::Input.m_mousePos = coord; }
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::mouseEnter(const boo::SWindowCoord& coord) {
|
||||||
|
ImGuiEngine::Input.m_mouseIn = true;
|
||||||
|
ImGuiEngine::Input.m_mousePos = coord;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::mouseLeave(const boo::SWindowCoord& coord) {
|
||||||
|
ImGuiEngine::Input.m_mouseIn = false;
|
||||||
|
ImGuiEngine::Input.m_mousePos = coord;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
|
||||||
|
ImGuiEngine::Input.m_mousePos = coord;
|
||||||
|
ImGuiEngine::Input.m_scrollDelta += scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) {
|
||||||
|
if (charCode < 256) {
|
||||||
|
ImGuiEngine::Input.m_keys[charCode] = true;
|
||||||
|
}
|
||||||
|
ImGuiEngine::Input.m_charCodes.push_back(charCode);
|
||||||
|
ImGuiEngine::Input.m_modifiers = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::charKeyUp(unsigned long charCode, boo::EModifierKey mods) {
|
||||||
|
if (charCode < 256) {
|
||||||
|
ImGuiEngine::Input.m_keys[charCode] = false;
|
||||||
|
}
|
||||||
|
ImGuiEngine::Input.m_modifiers = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
|
||||||
|
ImGuiEngine::Input.m_keys[256 + static_cast<int>(key)] = true;
|
||||||
|
ImGuiEngine::Input.m_modifiers = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) {
|
||||||
|
ImGuiEngine::Input.m_keys[256 + static_cast<int>(key)] = false;
|
||||||
|
ImGuiEngine::Input.m_modifiers = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiWindowCallback::resized(const boo::SWindowRect& rect, bool sync) { WindowRect = rect; }
|
||||||
|
|
||||||
|
} // namespace metaforce
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "imgui.h"
|
||||||
|
|
||||||
|
#include <boo/IWindow.hpp>
|
||||||
|
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
|
||||||
|
|
||||||
|
namespace metaforce {
|
||||||
|
class ImGuiEngine {
|
||||||
|
public:
|
||||||
|
static struct Input {
|
||||||
|
boo::SWindowCoord m_mousePos{};
|
||||||
|
std::array<bool, 5> m_mouseButtons{};
|
||||||
|
boo::SScrollDelta m_scrollDelta{};
|
||||||
|
boo::EModifierKey m_modifiers{};
|
||||||
|
std::array<bool, 512> m_keys{};
|
||||||
|
std::vector<unsigned long> m_charCodes{};
|
||||||
|
bool m_mouseIn = true;
|
||||||
|
} Input;
|
||||||
|
|
||||||
|
static void Initialize(boo::IGraphicsDataFactory* factory, const boo::SWindowRect &rect);
|
||||||
|
static void Shutdown();
|
||||||
|
|
||||||
|
static void Begin(float dt);
|
||||||
|
static void End();
|
||||||
|
static void Draw(boo::IGraphicsCommandQueue* gfxQ);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImGuiWindowCallback : boo::IWindowCallback {
|
||||||
|
static bool m_mouseCaptured;
|
||||||
|
static bool m_keyboardCaptured;
|
||||||
|
|
||||||
|
void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) override;
|
||||||
|
void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) override;
|
||||||
|
void mouseMove(const boo::SWindowCoord& coord) override;
|
||||||
|
void mouseEnter(const boo::SWindowCoord& coord) override;
|
||||||
|
void mouseLeave(const boo::SWindowCoord& coord) override;
|
||||||
|
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) override;
|
||||||
|
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) override;
|
||||||
|
void charKeyUp(unsigned long charCode, boo::EModifierKey mods) override;
|
||||||
|
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) override;
|
||||||
|
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) override;
|
||||||
|
void resized(const boo::SWindowRect &rect, bool sync) override;
|
||||||
|
};
|
||||||
|
} // namespace metaforce
|
|
@ -0,0 +1,134 @@
|
||||||
|
#shader ImguiShader
|
||||||
|
#attribute position2
|
||||||
|
#attribute uv2
|
||||||
|
#attribute colorunorm
|
||||||
|
#srcfac srcalpha
|
||||||
|
#dstfac invsrcalpha
|
||||||
|
#primitive triangles
|
||||||
|
#depthtest none
|
||||||
|
#depthwrite false
|
||||||
|
#culling none
|
||||||
|
|
||||||
|
|
||||||
|
#vertex glsl
|
||||||
|
layout (location = 0) in vec2 pos;
|
||||||
|
layout (location = 1) in vec2 uv;
|
||||||
|
layout (location = 2) in vec4 color;
|
||||||
|
UBINDING0 uniform ImguiShaderUniform
|
||||||
|
{
|
||||||
|
mat4 xf;
|
||||||
|
};
|
||||||
|
struct VertToFrag
|
||||||
|
{
|
||||||
|
vec2 uv;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
SBINDING(0) out VertToFrag vtf;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vtf.uv = uv;
|
||||||
|
vtf.color = color;
|
||||||
|
gl_Position = xf * vec4(pos.xy,0,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#fragment glsl
|
||||||
|
struct VertToFrag
|
||||||
|
{
|
||||||
|
vec2 uv;
|
||||||
|
vec4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
SBINDING(0) in VertToFrag vtf;
|
||||||
|
layout (location = 0) out vec4 colorOut;
|
||||||
|
TBINDING0 uniform sampler2D tex;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
colorOut = vtf.color * texture(tex, vtf.uv.st);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#vertex hlsl
|
||||||
|
cbuffer ImguiShaderUniform : register(b0)
|
||||||
|
{
|
||||||
|
float4x4 xf;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertData
|
||||||
|
{
|
||||||
|
float2 pos : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
float4 col : COLOR0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertToFrag
|
||||||
|
{
|
||||||
|
float4 pos : SV_POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
float4 col : COLOR0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VertToFrag main(in VS_INPUT v)
|
||||||
|
{
|
||||||
|
VertToFrag vtf;
|
||||||
|
vtf.pos = mul(xf, float4(v.pos.xy, 0.f, 1.f));
|
||||||
|
vtf.col = v.col;
|
||||||
|
vtf.uv = v.uv;
|
||||||
|
return vtf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fragment hlsl
|
||||||
|
struct VertToFrag
|
||||||
|
{
|
||||||
|
float4 pos : SV_POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
float4 col : COLOR0;
|
||||||
|
};
|
||||||
|
SamplerState samp : register(s0);
|
||||||
|
Texture2D tex0 : register(t0);
|
||||||
|
|
||||||
|
float4 main(in VertToFrag vtf) : SV_Target0
|
||||||
|
{
|
||||||
|
return vtf.col * tex0.Sample(samp, vtf.uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#vertex metal
|
||||||
|
struct ImguiShaderUniform {
|
||||||
|
float4x4 xf;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexIn {
|
||||||
|
float2 position [[attribute(0)]];
|
||||||
|
float2 texCoords [[attribute(1)]];
|
||||||
|
uchar4 color [[attribute(2)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertToFrag {
|
||||||
|
float4 position [[position]];
|
||||||
|
float2 texCoords;
|
||||||
|
float4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex VertToFrag vmain(VertexIn v [[stage_in]],
|
||||||
|
constant ImguiShaderUniform& u [[buffer(2)]]) {
|
||||||
|
VertToFrag vtf;
|
||||||
|
vtf.position = u.xf * float4(v.position, 0, 1);
|
||||||
|
vtf.texCoords = v.texCoords;
|
||||||
|
vtf.color = float4(v.color) / float4(255.0);
|
||||||
|
return vtf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fragment metal
|
||||||
|
struct VertToFrag {
|
||||||
|
float4 position [[position]];
|
||||||
|
float2 texCoords;
|
||||||
|
float4 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment half4 fmain(VertToFrag vtf [[stage_in]],
|
||||||
|
texture2d<half, access::sample> tex [[texture(0)]]) {
|
||||||
|
constexpr sampler linearSampler(coord::normalized, min_filter::linear, mag_filter::linear, mip_filter::linear);
|
||||||
|
half4 texColor = tex.sample(linearSampler, vtf.texCoords);
|
||||||
|
return half4(vtf.color) * texColor;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
|
|
||||||
|
// Use 32-bit index type for boo
|
||||||
|
#define ImDrawIdx uint32_t
|
Loading…
Reference in New Issue