Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate Dear ImGui and implement a new settings menu with it + more #576

Merged
merged 67 commits into from
Jun 17, 2024

Conversation

DanielGibson
Copy link
Member

@DanielGibson DanielGibson commented Jun 4, 2024

This integrates the Dear ImGui GUI toolkit and using that provides a new settings menu (which can be opened with F10 unless that key is bound already, or by entering dhewm3Settings in the console).
Dear ImGui support can be disabled when building dhewm3, and is automatically disabled for SDL1.2, as it requires SDL2.

The settings menu has many options that Doom3s options menu doesn't have, like:

  • Gamepad configuration and other advanced input settings
  • Enhanced keybinding menu that allows an arbitrary amount of keys bound per command, instead of limiting to three
  • Allow changing resolution without having to restart dhewm3 ("Apply" button does vid_restart)
  • Additional video settings
  • Additional audio settings, incl. selection of OpenAL device and enabling/disabling HRTF
  • More game options like toggle crouch or show FPS
  • Can be navigated also with gamepad or keyboard, instead of just with the mouse

While I implemented this I also added some features to dhewm3:

  • HighDPI support (by separating mouse coordinate space from physical GL framebuffer size; needs SDL2)
  • Invert Mouse look (both horizontally and vertically) with m_invertLook
  • CVar to allow always run in single player (still drains stamina though!): in_allowAlwaysRunInSP
  • VSync can be enabled/disabled on the fly, without restarting the renderer (still with r_swapInterval or in the menu, of course; needs SDL2)
  • Allow enabling/disabling HRTF with s_alHRTF
  • s_alOutputLimiter: Configure OpenAL's output-limiter which temporarily reduces the overall volume when too many too loud sounds play at once, to avoid issues like clipping
  • s_scaleDownAndClamp: Clamp and reduce volume of all sounds to prevent clipping or temporary downscaling by OpenAL's output limiter
  • Dropped the dependency on zlib, now miniz is used instead (built as part of dhewm3). This should also works around newer CMake versions fucking up their zlib library support (Echo of the of SSG shot became much quieter. #575 (comment))

As these are a lot of changes, this could need some testing!
Here's a current build for Windows: dhewm3-1.5.4pre-imgui3_win32.zip

still a bit hacky, but shows imgui windows that can be clicked etc
the integration of that at least, the menu is still a stub
idStr::(V)Format() is a static (v)printf-like function that returns
and idStr. Can be used like a better va(), or for
idStr mystr = idStr::Format( "number of items: %d", myarr.Num() );
I actually did this before the prototyping of a keybindings menu
in the imgui example code, so the prototype is actually based on this.
I'll merge the code from the prototype back once it's done.
The original binding menu uses #str_07183 between keys - this
should be " or ", but in the windows demo that entry is missing
in strings/english.lang
they're part of the regular list now. this will help with the actual
binding implementation I'll merge next
I first developed that as a prototype in
https://github.com/DanielGibson/dhewm3/blob/imgui/neo/libs/imgui/examples/example_sdl2_opengl2/main.cpp
there one can also find a commit history from writing that code, even
though not all commit messages are overly helpful :-p
Also fix MSVC build: For some reason Microsoft's sad excuse of a compiler
 only sets __cplusplus to a value from this millenium if the
/Zc:__cplusplus compiler option is set, but that's only supported from
VS2017 15.7 on. The alternative is to use _MSVC_LANG, which always holds
the version that __cplusplus *should* have...
You can pry X macros from my cold dead hands
it's nicely self-contained, I'll release it as a mini-library/addon
for Dear ImGui on https://github.com/DanielGibson/Snippets/
- write code uses fewer/shorter string literals
- code generated by WriteImGuiStyleToCode() has nicer alignment
- small improvements in some comments
Pause the game (with g_stopTime) when the settings menu is opened
while ingame, unpause it when it's closed.
If the menu is open while ingame and an ImGui window has focus,
the mouse cursor is shown. If the player clicks outside an ImGui window,
it gets unfocused and the cursor is hidden and the player can look
around. Pressing F10 (or whatever key is bound to "dhewm3Settings")
will give focus back to an open ImGui window, pressing it again then
will close the settings window, pressing it once again afterwards will
open the settings window again.

handleMouseGrab() (in sys/events.cpp) now checks if sys_imgui thinks
that a cursor should be shown (via D3::ImGuiHooks::ShouldShowCursor())
and if so, shows it and ungrabs the mouse. This, together with
D3::ImGuiHooks::NewFrame() checking ShouldShowCursor() to (unset)
ImGuiConfigFlags_NoMouseCursorChange, should prevent flickering cursor
problems that sometimes occurred when ImGui's SDL2 backend and dhewm3
disagreed on whether the cursor should be visible.
* Binding menu makes sure that the AllBindingsMenu always gets focus
  when opened
* Give binding-related popups slightly rounder edges
* Move Game Options tab behind Video and Audio Options
* Make warning overlays a bit less translucent
In the main menu the ImGui/SDL/System cursor was only drawn when it was
over an ImGui window, so only the Doom3 cursor is shown when outside
of ImGui windows.
The only problem with this is that the Doom3 cursor is only shown in
the parst of the window actually covered by the main menu, not the black
bars that are drawn on the left/right for widescreen-resolutions when
scaling the menu to 4:3 is enabled (which it is by default).
So now the ImGui cursor is also drawn when the cursor is on those
black bars (if any).

Also tweaked the windowtitle background colors a bit.
Not supported with SDL1.2 - but that's only still supported by dhewm3
because I'm too lazy to rip it out :-p
Upstream commit: "Disabled: nested tooltips or other non-child window
 within a BeginDisabled() block disable the disabled state. (dhewm#211, #7640)"

Should be in the next Dear ImGui release
the stb libs, miniz and minizip are now always optimized to speed up
performance, esp. level loading times, in debug builds.

So far the stb libs implementation were dragged into the source file
that uses them, now I created additional source files just for them so
those can be optimized while the engine source files using those libs
can remain unoptimized in debug builds.
ImGuiDir now is a proper enum, not just a typedef of int that happens
to have a similar name to the actual enum
@j4reporting
Copy link

I can crash dhewm on WIn10 with this procedure when switching between 'real fullscreen' and window mode (or vice versa)

  1. close imgui
  2. use ALT + RETURN to switch mode ( configured resolution does not matter)
  3. start imgui with F10

I can switch successfuly when the imgui is already open/visible.

the new options dialogs are great!

Seems like calling ImGui::CalcTextSize() is only safe after
(or at the end of) NewFrame()
@DanielGibson
Copy link
Member Author

Thanks for testing and reporting that bug - I just pushed a commit that should fix it :)

Glad you like the new menu!

@j4reporting
Copy link

I see these compile errors on MSYS2 and tried mingw32 on Linux.
compile errors with mingw32 (minizip)

[ 16%] Building CXX object CMakeFiles/dhewm3.dir/framework/File.cpp.obj
In file included from /src/dhewm3/dhewm3/neo/framework/minizip/ioapi.h:54,
                 from /src/dhewm3/dhewm3/neo/framework/minizip/unzip.h:56,
                 from /src/dhewm3/dhewm3/neo/framework/Unzip.h:32,
                 from /src/dhewm3/dhewm3/neo/framework/File.cpp:30:
/src/dhewm3/dhewm3/neo/framework/minizip/../miniz/minizconf.h:64:34: error: static assertion failed: z_off64_t should be a 64bit type
   64 | static_assert( sizeof(z_off64_t) == 8, "z_off64_t should be a 64bit type" );
      |                ~~~~~~~~~~~~~~~~~~^~~~
/src/dhewm3/dhewm3/neo/framework/minizip/../miniz/minizconf.h:64:34: note: the comparison reduces to '(4 == 8)'
make[2]: *** [CMakeFiles/dhewm3.dir/build.make:1097: CMakeFiles/dhewm3.dir/framework/File.cpp.obj] Error 1

$ i686-w64-mingw32-gcc --version
i686-w64-mingw32-gcc (GCC) 14.1.1 20240507 (Fedora MinGW 14.1.1-1.fc40)

is this really all that's needed?!
incl. setting in SettingsMenu

With SDL 2.0.5 and newer this change is applied immediately,
2.0.0 to 2.0.4 need a vid_restart
(with SDL1.2 we don't support it at all)
@DanielGibson
Copy link
Member Author

Here is an updated build for Windows: dhewm3-1.5.4pre-imgui4_win32.zip

Since the last one there are a few fixes and one new feature:
The dhewm3 window is now freely resizable! In windowed mode, you can drag the edges to resize, you can maximize (and restore) it, whatever.
Please test!

@j4reporting: Those mingw issues should be fixed, can you test the lastest code?

@j4reporting
Copy link

Mingw builds successfuly with latest updates.

"vid_restart partial" only changes the window size or its fullscreen
(or windowed) state, without recreating everything.
If that fails (or antialiasing settings have changed), it will fall back
to a full vid_restart (this behavior is different than original
 "vid_restart partial" that probably was implemented in Vanilla Doom3
 but not dhewm3)

This is used for Alt-Enter (which toggles between fullscreen and
windowed state) and when pressing the Apply button in the new Video Menu
@j4reporting
Copy link

vid_restart partial always switches back to windowed mode ignoring r_fullscreeen=1 setting
=> alt-enter never swirches from windowed to fullscreen mode.

Toggling with Alt-Enter relies on idRenderSystem::IsFullScreen() which
returns glConfig.isFullscreen

That can only work if GLimp_SetScreenParms() actually sets
glConfig.isFullscreen

Thanks j4reporting for reporting this! :)
@DanielGibson
Copy link
Member Author

Damn, how did I not notice this..

Thanks for reporting (and testing!), it should be fixed now :)

@j4reporting
Copy link

Damn, how did I not notice this..

was thinking the same ;)

Thanks for reporting (and testing!), it should be fixed now :)

nope. unchanged

only vid_restart works.

in windowed mode:

r_fullscreen 1
vid_restart partial  
=> nothing happens 
vid_restart
=> fullscreen mode
in fullscreen mode  
vid_restart partial 
 exits fullscreen mode  and  r_fullscreen  reports  "1"  still

r_customwidth / height is 1920x1080
desktop resolution 2560x1440
so the change windowed/fullscreen is abvious

@DanielGibson
Copy link
Member Author

try again, turns out I only tested with r_fullscreenDesktop 1 🙈

@j4reporting
Copy link

confirmed.

do you plan to make this the default for vid_restart and only attempt the complete vid_restart if the partial attempt failed?
and maybe introduce "vid_restart full" instead for the complete vid_restart?

@DanielGibson
Copy link
Member Author

My plan was to keep it like this.
When using the menu or Alt-Enter, vid_restart partial is already used, the remaining use cases are people explicitly running vid_restart in the console, and

  1. they should know what they're doing (I'll probably document the vid_restart behavior in Configuration.md)
  2. a full vid restart might help with weird bugs/glitches that the partial one doesn't, due to reloading everything and recreating the window
  3. I don't want to break the old behavior (also because of 2.)

it's queried from SDL so it should be up-to-date.
Using it in GLimp_SetScreenParms(), as it mostly did the same SDL calls
to get the current state for the partial vid_restart
…ions

Now the CVars are set immediately and "Apply" only does
`vid_restart partial`, while "Reset" resets the CVars to the values
that were set when opening the menu.
This also works the other way around: Changing a CVar (in the console
or other menu or r_fullscreen with Alt-Enter) is immediately reflected
in the menu.

Furthermore, "fullscreen desktop" now is its own setting (=> can be set
even if windowed mode is selected), to accommodate switchting between
windowed and fullscreen with Alt-Enter
@DanielGibson
Copy link
Member Author

I reworked the resolution/windowed/MSAA section of the Video Options.

Now the CVars are set immediately and "Apply" only does vid_restart partial, while "Reset" resets the CVars to the values that were set when opening the menu.
This also works the other way around: Changing a CVar (in the console or other menu or r_fullscreen with Alt-Enter) is immediately reflected in the menu

I think this is more consistent with how the rest of the menu works.

I also made "fullscreen desktop" a separate option, so one can configure windowed mode but still configure fullscreen desktop to specify what happens on Alt-Enter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants