diff --git a/Source/Render/inc/IRenderDevice.h b/Source/Render/inc/IRenderDevice.h index 12cafe61..a2b51a75 100644 --- a/Source/Render/inc/IRenderDevice.h +++ b/Source/Render/inc/IRenderDevice.h @@ -151,6 +151,7 @@ class cInterfaceRenderDevice : public cUnknownClass std::unordered_map drawBuffers; Mat4f orthoVP; eCullMode CameraCullMode = CULL_NONE; + bool debugUIEnabled = false; virtual void DrawFieldDispatcher(class FieldDispatcher* ffd, uint8_t transparent); @@ -268,6 +269,16 @@ class cInterfaceRenderDevice : public cUnknownClass virtual void DrawPoint(const Vect3f &v1, const sColor4c& color); virtual void FlushPrimitive3D(); + virtual void DebugUISetEnable(bool enabled); + virtual bool DebugUIIsEnabled(); + virtual bool DebugUIMouseMove(const Vect2f& pos); + virtual bool DebugUIMousePress(const Vect2f& pos, uint8_t button, bool pressed); + virtual bool DebugUIKeyPress(struct sKey* key, bool pressed); + +#ifdef PERIMETER_DEBUG + virtual void StartCaptureFrame(); +#endif + // Decl only methods virtual eRenderDeviceSelection GetRenderSelection() const = 0; @@ -333,9 +344,7 @@ class cInterfaceRenderDevice : public cUnknownClass virtual cTexture* GetShadowMap() = 0; virtual cTexture* GetLightMap() = 0; -#ifdef PERIMETER_DEBUG - virtual void StartCaptureFrame(); -#endif + // Decl only methods end }; cInterfaceRenderDevice* CreateIRenderDevice(eRenderDeviceSelection selection); diff --git a/Source/Render/sokol/CMakeLists.txt b/Source/Render/sokol/CMakeLists.txt index 37e2782d..7d6f1141 100644 --- a/Source/Render/sokol/CMakeLists.txt +++ b/Source/Render/sokol/CMakeLists.txt @@ -4,18 +4,26 @@ OPTION(OPTION_PROCESS_SHADERS "Re-Process game shaders" OFF) #Include Sokol FetchContent_Declare(sokol GIT_REPOSITORY https://github.com/floooh/sokol - GIT_TAG "67339198b75a7d04da3676db2b56514bf363d4b1" + GIT_TAG "4bda1469d3b311af03a34dd956460776c920dc2e" GIT_SHALLOW OFF - ) +) FetchContent_MakeAvailable(sokol) +#Include ImGui +FetchContent_Declare(imgui + GIT_REPOSITORY https://github.com/ocornut/imgui + GIT_TAG "cb16568fca5297512ff6a8f3b877f461c4323fbe" + GIT_SHALLOW OFF +) +FetchContent_MakeAvailable(imgui) + IF (OPTION_PROCESS_SHADERS) #Download precompiled sokol-shdc FetchContent_Declare(sokol-tools-bin GIT_REPOSITORY https://github.com/floooh/sokol-tools-bin - GIT_TAG "9a54e8ea68807733d82f4b169a8752a8fcad2040" + GIT_TAG "f1af4529746b804d6c79d5a36c333aec489fab27" GIT_SHALLOW OFF - ) + ) FetchContent_MakeAvailable(sokol-tools-bin) if(NOT DEFINED ENV{PERIMETER_SHADER_LANG}) @@ -74,64 +82,58 @@ if (MACOS) #Required for compiling some glue as Obj-C set(RenderSokol_SokolImpl sokol/SokolImpl.mm) if(OPTION_SOKOL_API MATCHES "GLCORE") - message("Sokol API: OpenGL Core") - add_definitions(-DSOKOL_GLCORE) - set(SOKOL_GL ON) set(RenderSokol_LINK_LIBS "-framework OpenGL") elseif(OPTION_SOKOL_API MATCHES "METAL") - message("Sokol API: Metal") - add_definitions(-DSOKOL_METAL) set(RenderSokol_LINK_LIBS "-framework Foundation -framework QuartzCore -framework Metal -framework MetalKit") #set(RenderSokol_LINK_LIBS "${RenderSokol_LINK_LIBS} -fobjc-arc -framework AudioToolbox") #You may wanna use UIKit here instead when porting to iOS in far far future set(RenderSokol_LINK_LIBS "${RenderSokol_LINK_LIBS} -framework Cocoa") - else() - message(SEND_ERROR "Unknown Sokol API selected: ${OPTION_SOKOL_API}") endif() elseif(PERIMETER_WINDOWS) if(NOT OPTION_SOKOL_API) set(OPTION_SOKOL_API "D3D11") endif () if(OPTION_SOKOL_API MATCHES "D3D11") - message("Sokol API: DirectX 11") - add_definitions(-DSOKOL_D3D11) set(RenderSokol_LINK_LIBS d3d11) elseif(OPTION_SOKOL_API MATCHES "GLCORE") - message("Sokol API: OpenGL Core") - add_definitions(-DSOKOL_GLCORE) - set(SOKOL_GL ON) set(RenderSokol_LINK_LIBS opengl32) - else() - message(SEND_ERROR "Unknown Sokol API selected: ${OPTION_SOKOL_API}") endif() else() if(NOT OPTION_SOKOL_API) set(OPTION_SOKOL_API "GLCORE") endif () if(OPTION_SOKOL_API MATCHES "GLES3") - message("Sokol API: OpenGLES 3.0") - add_definitions(-DSOKOL_GLES3) - set(SOKOL_GL ON) + set(RenderSokol_LINK_LIBS GL) elseif(OPTION_SOKOL_API MATCHES "GLCORE") - message("Sokol API: OpenGL Core") - add_definitions(-DSOKOL_GLCORE) - set(SOKOL_GL ON) - elseif(OPTION_SOKOL_API MATCHES "D3D11") - message("Sokol API: D3D11") - add_definitions(-DSOKOL_D3D11) - #The rest done after add_library() - else() - message(SEND_ERROR "Unknown Sokol API selected: ${OPTION_SOKOL_API}") - endif() - if (SOKOL_GL) set(RenderSokol_LINK_LIBS GL) - endif () + endif() +endif() +message(${OPTION_SOKOL_API}) +if(OPTION_SOKOL_API MATCHES "GLES3") + message("Sokol API: OpenGLES 3.0") + add_definitions(-DSOKOL_GLES3) + set(SOKOL_GL ON) + set(RenderSokol_ImguiBackend ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp) +elseif(OPTION_SOKOL_API MATCHES "GLCORE") + message("Sokol API: OpenGL Core") + add_definitions(-DSOKOL_GLCORE) + set(RenderSokol_ImguiBackend ${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp) +elseif(OPTION_SOKOL_API MATCHES "D3D11") + message("Sokol API: D3D11") + add_definitions(-DSOKOL_D3D11) + set(RenderSokol_ImguiBackend ${imgui_SOURCE_DIR}/backends/imgui_impl_dx11.cpp) +elseif(OPTION_SOKOL_API MATCHES "METAL") + message("Sokol API: Metal") + add_definitions(-DSOKOL_METAL) + set(RenderSokol_ImguiBackend ${imgui_SOURCE_DIR}/backends/imgui_impl_metal.mm) +else() + message(SEND_ERROR "Unknown Sokol API selected: ${OPTION_SOKOL_API}") endif() #Required for SDL_GL_* and SDL_SetHint/SDL_GetHint funcs called during render init set(RenderSokol_LINK_LIBS ${RenderSokol_LINK_LIBS} ${SDL2_LIBRARY}) -add_library(RenderSokol STATIC +set(RenderSokol_SRCS ${RenderSokol_SokolImpl} sokol/SokolResources.cpp sokol/SokolRender.cpp @@ -140,8 +142,15 @@ add_library(RenderSokol STATIC sokol/SokolRenderDraw.cpp sokol/SokolRenderPipeline.cpp sokol/SokolShaders.cpp + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${RenderSokol_ImguiBackend} ) +add_library(RenderSokol STATIC ${RenderSokol_SRCS}) + if(NOT PERIMETER_WINDOWS AND OPTION_SOKOL_API MATCHES "D3D11") #This way dxvk will be fetched and compiled before RenderSokol add_dependencies(RenderSokol dxvk) @@ -170,6 +179,7 @@ target_include_directories(RenderSokol PRIVATE "${PROJECT_SOURCE_DIR}/Source/Render/tracker" "${PROJECT_SOURCE_DIR}/Source/Render/tilemap" "${sokol_SOURCE_DIR}/" + "${imgui_SOURCE_DIR}/" ) #Render also needs headers diff --git a/Source/Render/sokol/SokolImpl.cpp b/Source/Render/sokol/SokolImpl.cpp index 7aee7bad..eb6a5014 100644 --- a/Source/Render/sokol/SokolImpl.cpp +++ b/Source/Render/sokol/SokolImpl.cpp @@ -6,14 +6,18 @@ #define LoadLibraryA(a) (nullptr) #define GetProcAddress(a,b) (nullptr) #endif + +#include + #define SOKOL_IMPL +#define SOKOL_TRACE_HOOKS #define SOKOL_ASSERT xassert + #ifdef __GNUG__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wextra" #endif -#include -#include +#include "SokolIncludes.h" #ifdef __GNUG__ #pragma GCC diagnostic pop #endif diff --git a/Source/Render/sokol/SokolIncludes.h b/Source/Render/sokol/SokolIncludes.h new file mode 100644 index 00000000..0d634881 --- /dev/null +++ b/Source/Render/sokol/SokolIncludes.h @@ -0,0 +1,10 @@ +#ifndef PERIMETER_SOKOLINCLUDES_H +#define PERIMETER_SOKOLINCLUDES_H + +#include +#include +#define SOKOL_IMGUI_NO_SOKOL_APP +#include +#include + +#endif //PERIMETER_SOKOLINCLUDES_H diff --git a/Source/Render/sokol/SokolRender.cpp b/Source/Render/sokol/SokolRender.cpp index d2b805f5..72c3d71f 100644 --- a/Source/Render/sokol/SokolRender.cpp +++ b/Source/Render/sokol/SokolRender.cpp @@ -3,8 +3,7 @@ #include "StdAfxRD.h" #include "xmath.h" #include "Umath.h" -#include -#include +#include "SokolIncludes.h" #include "SokolResources.h" #include "IRenderDevice.h" #include "SokolRender.h" @@ -260,9 +259,13 @@ int cSokolRender::Init(int xScr, int yScr, int mode, SDL_Window* wnd, int Refres //Call sokol gfx setup sg_setup(&desc); -#ifdef PERIMETER_DEBUG printf("cSokolRender::Init sg_setup done\n"); -#endif + + debugUIEnabled = false; + + if (check_command_line("render_debug") != nullptr) { + DebugUISetEnable(true); + } //Create sampler sg_sampler_desc sampler_desc = {}; @@ -397,6 +400,11 @@ int cSokolRender::Done() { sdl_gl_context = nullptr; } #endif + if (imgui_state) { + sgimgui_discard(imgui_state); + delete imgui_state; + imgui_state = nullptr; + } RenderSubmitEvent(RenderEvent::DONE, "Sokol done"); return ret; } diff --git a/Source/Render/sokol/SokolRender.h b/Source/Render/sokol/SokolRender.h index 9da7d483..83aa4aea 100644 --- a/Source/Render/sokol/SokolRender.h +++ b/Source/Render/sokol/SokolRender.h @@ -5,7 +5,6 @@ #define PERIMETER_SOKOL_GL (1) #endif -#include #include #include "SokolTypes.h" @@ -92,6 +91,8 @@ class cSokolRender: public cInterfaceRenderDevice { friend const void* sokol_d3d_render_target_view_cb(); friend const void* sokol_d3d_depth_stencil_view_cb(); #endif + + struct sgimgui_t* imgui_state = nullptr; //Stores resources for reusing void ClearPooledResources(uint32_t max_life); @@ -240,6 +241,10 @@ class cSokolRender: public cInterfaceRenderDevice { void StartCaptureFrame() override; #endif + void DebugUISetEnable(bool state) override; + bool DebugUIMouseMove(const Vect2f& pos) override; + bool DebugUIMousePress(const Vect2f& pos, uint8_t button, bool pressed) override; + int SetGamma(float fGamma,float fStart=0.f,float fFinish=1.f) override; void DeleteVertexBuffer(class VertexBuffer &vb) override; diff --git a/Source/Render/sokol/SokolRenderDraw.cpp b/Source/Render/sokol/SokolRenderDraw.cpp index 5db65764..9b4f8762 100644 --- a/Source/Render/sokol/SokolRenderDraw.cpp +++ b/Source/Render/sokol/SokolRenderDraw.cpp @@ -2,6 +2,7 @@ #include "xmath.h" #include "VertexFormat.h" #include "IRenderDevice.h" +#include "SokolIncludes.h" #include "SokolRender.h" #include "SokolResources.h" #include "DrawBuffer.h" diff --git a/Source/Render/sokol/SokolRenderPipeline.cpp b/Source/Render/sokol/SokolRenderPipeline.cpp index 1bf850bb..513a3669 100644 --- a/Source/Render/sokol/SokolRenderPipeline.cpp +++ b/Source/Render/sokol/SokolRenderPipeline.cpp @@ -4,7 +4,7 @@ #include "Umath.h" #include "StdAfxRD.h" #include "VertexFormat.h" -#include +#include "SokolIncludes.h" #include "SokolRender.h" #include "SokolRenderPipeline.h" #include "SokolShaders.h" diff --git a/Source/Render/sokol/SokolRenderState.cpp b/Source/Render/sokol/SokolRenderState.cpp index bdbe5219..3f56b29a 100644 --- a/Source/Render/sokol/SokolRenderState.cpp +++ b/Source/Render/sokol/SokolRenderState.cpp @@ -2,11 +2,12 @@ #include #include #include +#include #include "xmath.h" #include "Umath.h" #include "StdAfxRD.h" #include "VertexFormat.h" -#include +#include "SokolIncludes.h" #include "SokolResources.h" #include "IRenderDevice.h" #include "SokolRender.h" @@ -39,7 +40,6 @@ void sokol_metal_render_callback() { #ifdef PERIMETER_DEBUG void sokol_metal_capture_frame(); #endif - #endif //How many frames to store the resources until freed @@ -97,6 +97,18 @@ void cSokolRender::DoSokolRendering() { } #endif + if (debugUIEnabled) { + static int last_clock = clocki(); + const simgui_frame_desc_t frame_desc = { + .width = ScreenSize.x, + .height = ScreenSize.y, + .delta_time = clocki() - last_clock, + .dpi_scale = 1.0 + }; + last_clock = clocki(); + simgui_new_frame(&frame_desc); + } + for (auto& target : { shadowMapRenderTarget, lightMapRenderTarget }) { if (target != nullptr) { ProcessRenderPass(target->render_pass, target->commands); @@ -281,6 +293,13 @@ void cSokolRender::ProcessRenderPass(sg_pass& render_pass, const std::vector(command->base_elements), static_cast(command->indices), 1); } + //Special pass for imgui during swapchain pass + if (debugUIEnabled && render_pass.attachments.id == 0) { + sgimgui_draw(imgui_state); + sgimgui_draw_menu(imgui_state, "sokol-gfx"); + simgui_render(); + } + //End pass sg_end_pass(); } @@ -330,6 +349,32 @@ void cSokolRender::StartCaptureFrame() { } #endif +void cSokolRender::DebugUISetEnable(bool state) { + cInterfaceRenderDevice::DebugUISetEnable(state); + + //If enabled and imgui_state isn't initialized, do it + if (debugUIEnabled && imgui_state == nullptr) { + const simgui_desc_t simgui_desc = {}; + simgui_setup(&simgui_desc); + const sgimgui_desc_t sgimgui_desc = {}; + imgui_state = new sgimgui_t {}; + sgimgui_init(imgui_state, &sgimgui_desc); + } +} + +bool cSokolRender::DebugUIMouseMove(const Vect2f& pos) { + simgui_add_mouse_pos_event( + (pos.x + 0.5f) * ScreenSize.x, + (pos.y + 0.5f) * ScreenSize.y + ); + return false; +} + +bool cSokolRender::DebugUIMousePress(const Vect2f& pos, uint8_t button, bool pressed) { + simgui_add_mouse_button_event(button - SDL_BUTTON_LEFT, pressed); + return true; +} + void cSokolRender::ClearActiveBufferAndPassAction() { if (activeDrawBuffer) { //Send out any active DB before we set a pass action diff --git a/Source/Render/sokol/SokolRenderTexture.cpp b/Source/Render/sokol/SokolRenderTexture.cpp index f04b7e38..c327af6f 100644 --- a/Source/Render/sokol/SokolRenderTexture.cpp +++ b/Source/Render/sokol/SokolRenderTexture.cpp @@ -4,7 +4,7 @@ #include "Umath.h" #include "StdAfxRD.h" #include "VertexFormat.h" -#include +#include "SokolIncludes.h" #include "IRenderDevice.h" #include "SokolRender.h" #include "FileImage.h" diff --git a/Source/Render/sokol/SokolResources.cpp b/Source/Render/sokol/SokolResources.cpp index 3b56ac13..1f83293e 100644 --- a/Source/Render/sokol/SokolResources.cpp +++ b/Source/Render/sokol/SokolResources.cpp @@ -1,6 +1,6 @@ #include "xerrhand.h" #include "xmath.h" -#include +#include "SokolIncludes.h" #include "SokolResources.h" #include "SokolTypes.h" diff --git a/Source/Render/sokol/SokolShaders.cpp b/Source/Render/sokol/SokolShaders.cpp index ae3669c6..b19fb981 100644 --- a/Source/Render/sokol/SokolShaders.cpp +++ b/Source/Render/sokol/SokolShaders.cpp @@ -1,6 +1,6 @@ // This file implements shaders structs #include -#include +#include "SokolIncludes.h" #include "xmath.h" #include "SokolShaders.h" SOKOL_SHADER_IMPL(color_tex1); diff --git a/Source/Render/src/RenderDevice.cpp b/Source/Render/src/RenderDevice.cpp index cb966422..4ea3ffe3 100644 --- a/Source/Render/src/RenderDevice.cpp +++ b/Source/Render/src/RenderDevice.cpp @@ -14,6 +14,7 @@ #include "D3DRender.h" #endif #ifdef PERIMETER_SOKOL +#include "sokol/SokolIncludes.h" #include "sokol/SokolRender.h" #endif @@ -611,6 +612,26 @@ void BuildMipMap(int x,int y,int bpp,int bplSrc,const void *pSrc,int bplDst,void } } +void cInterfaceRenderDevice::DebugUISetEnable(bool state) { + debugUIEnabled = state; +} + +bool cInterfaceRenderDevice::DebugUIIsEnabled() { + return debugUIEnabled; +} + +bool cInterfaceRenderDevice::DebugUIMouseMove(const Vect2f& pos) { + return false; +} + +bool cInterfaceRenderDevice::DebugUIMousePress(const Vect2f& pos, uint8_t button, bool pressed) { + return false; +} + +bool cInterfaceRenderDevice::DebugUIKeyPress(struct sKey* key, bool pressed) { + return false; +} + // Render device selection cInterfaceRenderDevice *gb_RenderDevice = nullptr; diff --git a/Source/Render/src/TexLibrary.cpp b/Source/Render/src/TexLibrary.cpp index ef0f497c..0f8625ab 100644 --- a/Source/Render/src/TexLibrary.cpp +++ b/Source/Render/src/TexLibrary.cpp @@ -10,7 +10,7 @@ #endif //PERIMETER_D3D9 #ifdef PERIMETER_SOKOL -#include +#include "sokol/SokolIncludes.h" #include "sokol/SokolResources.h" #endif //PERIMETER_SOKOL diff --git a/Source/UserInterface/GameShell.cpp b/Source/UserInterface/GameShell.cpp index fffe07ff..7589fcb4 100644 --- a/Source/UserInterface/GameShell.cpp +++ b/Source/UserInterface/GameShell.cpp @@ -1086,6 +1086,10 @@ void GameShell::EventHandler(SDL_Event& event) { } Vect2f where = convert(event.button.x, event.button.y); //printf("M %fx%f B %dn", where.x, where.y, event.button.button, pressed); + if (terRenderDevice->DebugUIIsEnabled() + && terRenderDevice->DebugUIMousePress(where, event.button.button, pressed)) { + break; + } switch (event.button.button) { case SDL_BUTTON_LEFT: if (doubleClick) { @@ -1372,6 +1376,10 @@ bool GameShell::DebugKeyPressed(sKey& Key) debug_variation = 1 - debug_variation; break; + case 'R' | KBD_CTRL: + terRenderDevice->DebugUISetEnable(!terRenderDevice->DebugUIIsEnabled()); + break; + case 'M': terCamera->setRestriction(!terCamera->restricted()); break; @@ -1577,9 +1585,15 @@ void GameShell::KeyPressed(sKey& Key) terminate(); return; } - - if(missionEditor_ && missionEditor_->keyPressed(Key)) - return; + + if (terRenderDevice->DebugUIIsEnabled() + && terRenderDevice->DebugUIKeyPress(&Key, true)) { + return; + } + + if (missionEditor_ && missionEditor_->keyPressed(Key)) { + return; + } if (Key.fullkey == (VK_F1|KBD_SHIFT|KBD_CTRL)) { #ifndef PERIMETER_DEBUG @@ -1813,8 +1827,14 @@ void GameShell::ControlPressed(int key) void GameShell::KeyUnpressed(sKey& Key) { - if(missionEditor_ && missionEditor_->keyUnpressed(Key)) - return; + if (terRenderDevice->DebugUIIsEnabled() + && terRenderDevice->DebugUIKeyPress(&Key, false)) { + return; + } + + if (missionEditor_ && missionEditor_->keyUnpressed(Key)) { + return; + } if(_bMenuMode){ _shellIconManager.OnKeyUp(Key.fullkey); @@ -1876,8 +1896,14 @@ void GameShell::updatePosition() void GameShell::MouseMove(const Vect2f& pos, const Vect2f& rel) { - if(missionEditor_ && missionEditor_->mouseMove(pos)) - return; + if (terRenderDevice->DebugUIIsEnabled() + && terRenderDevice->DebugUIMouseMove(pos)) { + return; + } + + if (missionEditor_ && missionEditor_->mouseMove(pos)) { + return; + } cameraCursorInWindow = true;