Start ImGui-based settings menu

the integration of that at least, the menu is still a stub
This commit is contained in:
Daniel Gibson 2024-04-05 06:33:33 +02:00
parent 8fce796680
commit ffaf135758
5 changed files with 147 additions and 40 deletions

View file

@ -564,6 +564,7 @@ set(src_framework
framework/DeclPDA.cpp
framework/DeclSkin.cpp
framework/DeclTable.cpp
framework/Dhewm3SettingsMenu.cpp
framework/EditField.cpp
framework/EventLoop.cpp
framework/File.cpp

View file

@ -60,6 +60,9 @@ If you have questions concerning this license or the applicable additional terms
#define MAX_PRINT_MSG_SIZE 4096
#define MAX_WARNING_LIST 256
// DG: implemented in Dhewm3SettingsMenu.cpp (the only Com_*_f() function not implemented in this file)
extern void Com_Dhewm3Settings_f( const idCmdArgs &args );
typedef enum {
ERP_NONE,
ERP_FATAL, // exit the entire game with a popup window
@ -2302,6 +2305,8 @@ void idCommonLocal::InitCommands( void ) {
cmdSystem->AddCommand( "setMachineSpec", Com_SetMachineSpec_f, CMD_FL_SYSTEM, "detects system capabilities and sets com_machineSpec to appropriate value" );
cmdSystem->AddCommand( "execMachineSpec", Com_ExecMachineSpec_f, CMD_FL_SYSTEM, "execs the appropriate config files and sets cvars based on com_machineSpec" );
cmdSystem->AddCommand( "dhewm3Settings", Com_Dhewm3Settings_f, CMD_FL_SYSTEM, "Toggles (opens/closes) the (advanced) dhewm3 settings menu" );
#if !defined( ID_DEDICATED )
// compilers
cmdSystem->AddCommand( "dmap", Dmap_f, CMD_FL_TOOL, "compiles a map", idCmdSystem::ArgCompletion_MapName );

View file

@ -0,0 +1,72 @@
#include "Common.h"
#include "sys/sys_imgui.h"
#ifndef IMGUI_DISABLE
static bool dhewm3MenuOpen = false;
// called from D3::ImGuiHooks::NewFrame() (if this window is enabled)
void Com_DrawDhewm3SettingsMenu()
{
bool showSettingsWindow = true;
ImGui::Begin("dhewm3 Settings", &showSettingsWindow);
if (ImGui::Button("Show ImGui Demo")) {
D3::ImGuiHooks::OpenWindow( D3::ImGuiHooks::D3_ImGuiWin_Demo );
}
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
if (ImGui::BeginTabBar("SettingsTabBar", tab_bar_flags))
{
if (ImGui::BeginTabItem("Avocado"))
{
ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Broccoli"))
{
ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem("Cucumber"))
{
ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
ImGui::End();
if(!showSettingsWindow) {
D3::ImGuiHooks::CloseWindow( D3::ImGuiHooks::D3_ImGuiWin_Settings );
dhewm3MenuOpen = false;
}
}
void Com_Dhewm3Settings_f( const idCmdArgs &args )
{
if ( !dhewm3MenuOpen ) {
// TODO: if in SP game, pause
D3::ImGuiHooks::OpenWindow( D3::ImGuiHooks::D3_ImGuiWin_Settings );
dhewm3MenuOpen = true;
} else {
D3::ImGuiHooks::CloseWindow( D3::ImGuiHooks::D3_ImGuiWin_Settings );
// TODO: if in SP game, unpause
dhewm3MenuOpen = false;
}
}
#else // IMGUI_DISABLE - just a stub function
void Com_Dhewm3Settings_f( const idCmdArgs &args ) {}
#endif

View file

@ -12,6 +12,7 @@
#include "renderer/qgl.h"
#include "renderer/tr_local.h" // glconfig
extern void Com_DrawDhewm3SettingsMenu(); // in framework/dhewm3SettingsMenu.cpp
namespace D3 {
namespace ImGuiHooks {
@ -19,6 +20,8 @@ namespace ImGuiHooks {
ImGuiContext* imguiCtx = NULL;
static bool haveNewFrame = false;
static int openImguiWindows = 0; // or-ed enum D3ImGuiWindow values
// using void* instead of SDL_Window and SDL_GLContext to avoid dragging SDL headers into sys_imgui.h
bool Init(void* sdlWindow, void* sdlGlContext)
{
@ -51,6 +54,17 @@ bool Init(void* sdlWindow, void* sdlGlContext)
ImVec4* colors = style.Colors;
colors[ImGuiCol_TitleBg] = ImVec4(0.28f, 0.36f, 0.48f, 0.88f);
colors[ImGuiCol_TabHovered] = ImVec4(0.42f, 0.69f, 1.00f, 0.80f);
colors[ImGuiCol_TabActive] = ImVec4(0.24f, 0.51f, 0.83f, 1.00f);
int winIdx = SDL_GetWindowDisplayIndex( (SDL_Window*)sdlWindow );
if (winIdx >= 0) {
float ddpi = 0, hdpi = 0, vdpi = 0;
SDL_GetDisplayDPI(winIdx, &ddpi, &hdpi, &vdpi);
printf("XXX ddpi = %f, hdpi = %f, vdpi = %f\n", ddpi, hdpi, vdpi);
// TODO: does this work good enough for high DPI support?
io.FontGlobalScale = vdpi / 96.0f;
}
// Setup Platform/Renderer backends
if ( ! ImGui_ImplSDL2_InitForOpenGL( (SDL_Window*)sdlWindow, sdlGlContext ) ) {
@ -96,58 +110,38 @@ void Shutdown()
ImGui::DestroyContext( imguiCtx );
}
// NewFrame() is called once per D3 frame, after all events have been gotten
// => ProcessEvent() has already been called (probably multiple times)
void NewFrame()
{
if (openImguiWindows == 0)
return;
// Start the Dear ImGui frame
ImGui_ImplOpenGL2_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
haveNewFrame = true;
// XXX hack for testing:
static bool show_another_window = false;
static bool show_demo_window = true;
if(show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
{
static float f = 0.0f;
static int counter = 0;
ImGuiIO& io = ImGui::GetIO();
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
//ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
ImGui::End();
if (openImguiWindows & D3_ImGuiWin_Settings) {
Com_DrawDhewm3SettingsMenu();
}
if ( show_another_window ) {
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
ImGui::End();
if (openImguiWindows & D3_ImGuiWin_Demo) {
bool show_demo_window = true;
ImGui::ShowDemoWindow(&show_demo_window);
if(!show_demo_window)
CloseWindow(D3_ImGuiWin_Demo);
}
}
// returns true if ImGui has handled the event and it shouldn't be passed to the game
// called with every SDL event by Sys_GetEvent()
// returns true if ImGui has handled the event (so it shouldn't be handled by D3)
bool ProcessEvent(const void* sdlEvent)
{
if (openImguiWindows == 0)
return false;
const SDL_Event* ev = (const SDL_Event*)sdlEvent;
// ImGui_ImplSDL2_ProcessEvent() doc says:
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
@ -180,6 +174,9 @@ bool ProcessEvent(const void* sdlEvent)
void EndFrame()
{
if (openImguiWindows == 0 && !haveNewFrame)
return;
// I think this can happen if we're not coming from idCommon::Frame() but screenshot or sth
if ( !haveNewFrame ) {
NewFrame();
@ -222,6 +219,17 @@ void EndFrame()
}
}
void OpenWindow( D3ImGuiWindow win )
{
openImguiWindows |= win;
}
void CloseWindow( D3ImGuiWindow win )
{
openImguiWindows &= ~win;
}
}} //namespace D3::ImGuiHooks
#endif // D3_ENABLE_IMGUI

View file

@ -8,6 +8,13 @@
namespace D3 {
namespace ImGuiHooks {
enum D3ImGuiWindow {
D3_ImGuiWin_None = 0,
D3_ImGuiWin_Settings = 1, // advanced dhewm3 settings menu
D3_ImGuiWin_Demo = 2, // ImGui demo window
// next should be 4, then 8, etc so a bitmask can be used
};
#ifndef IMGUI_DISABLE
extern ImGuiContext* imguiCtx; // this is only here so IsImguiEnabled() can use it inline
@ -22,10 +29,20 @@ extern bool Init(void* sdlWindow, void* sdlGlContext);
extern void Shutdown();
extern void NewFrame();
extern void OpenWindow( D3ImGuiWindow win );
extern void CloseWindow( D3ImGuiWindow win );
// called with every SDL event by Sys_GetEvent()
// returns true if ImGui has handled the event (so it shouldn't be handled by D3)
extern bool ProcessEvent(const void* sdlEvent);
// NewFrame() is called once per D3 frame, after all events have been gotten
// => ProcessEvent() has already been called (probably multiple times)
extern void NewFrame();
// called at the end of the D3 frame, when all other D3 rendering is done
// renders ImGui menus then
extern void EndFrame();
#else // IMGUI_DISABLE - just stub out everything
@ -43,12 +60,16 @@ inline bool Init(void* sdlWindow, void* sdlGlContext)
inline void Shutdown() {}
inline void NewFrame() {}
inline bool ProcessEvent(const void* sdlEvent) { return false; }
inline void NewFrame() {}
inline void EndFrame() {}
inline void OpenWindow( D3ImGuiWindow win ) {}
inline void CloseWindow( D3ImGuiWindow win ) {}
#endif
}} //namespace D3::ImGuiHooks