in SkinDeep regs not being initialized caused random crashes
(in dhewm3 I haven't seen that so far, but fixing this won't hurt).
From SkinDeep commit message:
In idRegister::SetToRegs() at `registers[ regs[ i ] ] = v[i];`
regs[i] contained values like 21845 or 22010 or 32272, even though
the static registers array that's written to there only holds 4096
elements (it's `static float regs[MAX_EXPRESSION_REGISTERS];`
from `idWindow::EvalRegs()`).
So it overwrites other data, likely other global variables, like
`gameLocal.entities[4967]`, that now contain garbage and next time
someone tries to use them, bad things happen.
In this case, if someone tries to dereference gameLocal.entities[i]
and the pointer at i contains garbage, there's a segfault (crash).
462404af67
"gui::horPad" is now called "gui::cstHorPad", "gui::vertPad" is now
called "gui::cstVertPad", so it's clearer that they belong to the
CST anchor system.
I also added "gui::cstAspectRatio", the aspect ratio of screen or Doom3's
window resolution (when using windowed mode).
Furthermore "gui::cstWidth" and "gui::cstHeigh" with the screen
(or Doom3 window) resolution in *virtual* pixels, based on that GUI
640x480 coordinate system.
For widescreen resolutions, "gui::cstHeight" is always 480 and
"gui::cstWidth" is scaled according to the aspect ratio (>640).
For tall resolutions, "gui::cstWidth" is always 640 and "gui::cstHeight"
is scaled according to the aspect ratio (> 480).
So far one could only use either naturalmatscale or matscalex/matscaley.
Just "naturalmatscale 1" lets a texture repeat in its native size, i.e.
if you have a 64x32 texture and a 320x160 (in the 640x480 GUI coordinate
system) windowDef, it will be repeated 5 times in each direction.
If you resize the windowDef to 384x160, it will repeat the texture
6 times horizontally (and still 5 times vertically).
matscalex/y allow scaling that texture. If both values are set to 2,
(and naturalmatscale to 1) the 64x32 texture in a 384x160 windowDef
will be repeated 12 times horizontally and 10 times vertically, at half
the size per direction.
Without naturalmatscale it would be repeated 2 times in each direction,
no matter how big the windowDef is.
they are set before onActivate and also whenever the (Doom3 SDL) window
size changes, in that case additionally the "UpdateWindowSize" Named
Event is called in the script, in case you wanna do anything special
in that case:
onNamedEvent UpdateWindowSize {
set "print" "UpdateWindowSize - horPad:" "gui::horPad"
"vertPad:" "gui::vertPad";
}
horPad is the width of the padding border (empty space) between the
left/right border of Doom3's SDL window and a centered
(cstAnchor CST_ANCHOR_CENTER_CENTER) full-sized windowDef in virtual
pixels (in the Doom3 GUI coordinate system, which usually is 640x480).
vertPad is the same for the padding border between the top/bottom border
and a centered full-sized windowDef
One of those values will always be 0.
So for example if you play Doom3 at 1600x1200 (a 4:3 resolution like
640x480) both horPad and vertPad are 0.
If you play at 1680x1050 (16:10 resolution) and your windowDef Desktop
is 640x480 (the default), horPad is 64 (and vertPad is 0), because
there are 64 virtual pixels between the left window border and a
centered 640x480 windowDef (and also between the centered windowDef
and the right window border.
gui::horPad and gui::vertPad are useful for filling those otherwise
empty padding areas with windowDefs that you anchor to the corresponding
points of the window (like CST_ANCHOR_LEFT and CST_ANCHOR_RIGHT when
there's horizontal padding) that have just the right size.
Example of a green rectangle filling parts of the left padding area,
but not touching the center area (10 virtual pixels distance):
windowDef leftPadFiller {
cstAnchor CST_ANCHOR_LEFT
rect 0, 200, "gui::horPad" - 10, 40
backColor 0, 1, 0, 1
}
Example:
onActivate {
set "print" "this windowDefs rect:" "$rect";
}
(added to the Desktop of a GUI) prints
"GUI debug: this windowDefs rect: 0 0 640 480"
to the ingame console
especially useful when using cstAnchor
also providing an easy generic way to figure out if the window of an
idUserInterface is scaled to 4:3 aspect ratio or not, depending on
r_scaleMenusTo43 and the WIN_SCALETO43/WIN_NO_SCALETO43 window flags,
that come from "scaleto43 1" (or 0) set in the GUIs Desktop windowDef
for my scale to 4:3 hack idRenderWindow::Draw() already calls
if(dc->IsMenuScaleFixActive()) {
dc->AdjustCoords(&x, &y, &w, &h);
}
and AdjustCoords() already takes the cst offsets into account, so all
that was left to do was making idDeviceContext::IsMenuScaleFixActive()
aware of the cst stuff
even if r_scaleMenusTo43 1 and they'd usually be scaled to 4:3.
Useful when using anchors in fullscreen menus (like the PDA)
This is analogous to "scaleto43 1" in windowDefs which allows scaling
to 4:3 (with black/empty bars) even if by default it would *not* be
scaled.
incl. backwards compat for older savegames.
only partly useful: old savegames only work if you didn't change the
gamedata, with the CstDoom3 .gui files, loading them crashes. I don't
think that can be avoided, apparently Doom3 has no way to detect that
the GUIs have changed?
In idWindow::Redraw(), I had to make sure the menu scale fix (which,
if enabled for a window, renders that in 4:3 with empty or black bars
on the side if needed for widescreen etc, instead of stretching it)
is disabled if a window uses CST anchors, because the CST anchor code
also adjusts for the display aspect ratio and if we do both, things get
distorted in the other way.
The biggest change is that idDeviceContext::DrawStretchPic(Rotated) now
has code to adjust the coordinates for both CST and the menu scale fix,
so idDeviceContext::AdjustCoords() is mostly obsolete - it's only still
used by idRenderWindow.
Unlike DstDoom3 now that extra adjustCoords argument to those Draw
functions indicates that any coordinate adjustment should be done, so
if it's set by a caller, it's set to true.
I removed idDeviceContext::AdjustCursorCoords() because it was only used
in one place anyway
- the gamepad button (or trigger) bound to attack (fire) now always
acts like the left mouse button in menus
- Display correct button name for "Back" button on Playstation-like
gamepads, even depending on whether it's PS3-like ("Select") or
PS4/5-like ("Share")
- Log some more information about detected gamepads
- make moving the cursor more precise by using an exponential curve
for axis value => cursor speed
- emulate cursor keys with DPad and Enter with left trigger
- also use right trigger for leftclick, as it's usually used for firing
a weapon and thus used for "clicking" ingame UIs
- fix hovering/highlighting menu elements when moving cursor
with gamepad
- treat DPad as 4 regular buttons (was already the case mostly, but now
the code is simpler)
- rename in_invertLook to joy_invertLook and in_useJoystick to
in_useGamepad and remove unused CVars
- make controller Start button generate K_ESCAPE events, so it can
always be used to open/close the menu (similar to D3BFG)
- move mousecursor with sticks, A button (south) for left-click,
B button (east) for right-click (doesn't work in PDA yet)
- removed special handling of K_JOY_BTN_* in idWindow::HandleEvent()
by generating fake mouse button events for gamepad A/B
in idUserInterfaceLocal::HandleEvent()
There were lots of places in the code that called Sys_GrabInput(),
some of them each frame.
Most of this is unified in events.cpp now, in handleMouseGrab() which
is called once per frame by Sys_GenerateEvents() - this makes reasoning
about when the mouse is grabbed and when not a lot easier.
Sys_GrabInput(false) still is called in a few places, before operations
that tend to take long (like loading a map or vid_restart), but
(hopefully) not regularly anymore.
The other big change is that the game now uses SDLs absolute mouse mode
for fullscreen menus (except the PDA which is an ugly hack), so the
ingame cursor is at the same position as the system cursor, which
especially helps when debugging with `in_nograb 1` and should also help
if someone wants to integrate an additional GUI toolkit like Dear ImGui.
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
it wants to store a pointer to itself in an idWinVar - on 32bit idWinInt
was suitable for that, on 64bit it's not, so instead convert the pointer
to a hex-string and stuff it in a idWinStr
also fix a crash when adding a choiceDef in the gui editor
WIN_DESKTOP means that this can currently only be set for the top-level
window in a .gui (all its subwindows/widgets will be scaled implicitly)
There are two ways to make a GUI use this:
1. in the .gui add a window variable "scaleto43 1", like
windowDef Desktop {
rect 0 ,0 ,640 ,480
nocursor 1
float talk 0
scaleto43 1
// .. etc rest of windowDef
2. When creating the GUI from C++ code, you can afterwards make the
UserInterface scale to 4:3 like this:
idUserInterface* ui = Whatever(); // create it
ui->SetStateBool("scaleto43", true);
ui->StateChanged(gameLocal.time);
Both lines are important!
As you can see in my changes to Player.cpp, my primary usecase for this
is the cursor/crosshair GUI.
So stuff doesn't look so distorted in widescreen resolutions.
Implies that there are black bars on the left/right then..
Can be disabled with "r_scaleMenusTo43 0"
Does *not* affect the HUD (incl. crosshair) - scaling it automagically
would be very hard (or impossible), because it doesn't only render
the crosshair, healthpoints etc, but also fullscreen effects like the
screen turning red when the player is hit - and fullscreen effects
would look very shitty if they didn't cover the whole screen but had
"empty" bars on left/right.
(Mostly) fixes#188 and #189
Mods that have their own video settings menu can tell dhewm3 to replace
the "choices" and "values" entries in their choiceDef with the
resolutions supported by dhewm3 (and corresponding modes).
So if we add new video modes to dhewm3, they'll automatically appear in
the menu without changing the .gui
To enable this, the mod authors only need to add a "injectResolutions 1"
entry to their resolution choiceDef. By default, the first entry will
be "r_custom*" for r_mode -1, which means "custom resolution, use
r_customWidth and r_customHeight".
If that entry shoud be disabled for the mod, just add another entry:
"injectCustomResolutionMode 0"
Sometimes memory was allocated with new[] but freed with delete instead
of delete[], which is wrong.
And there were some small memory leaks, too.
Furtunately clang's AddressSanitizer detected all that so I could easily
fix it.
(There seem to be some more small memory leaks which are harder to fix,
though)
The fullscreen guis pretend to be 640x480 internally, also for the mouse
cursor position. So adding the actually moved pixels (when playing the
game at a higher resolution) to the GUIs cursor position makes it move
too fast.
To fix that I detect (hopefully that check is reliable!) if the
idUserInterfaceLocal instance is a fullscreen GUI and if so scale the
reported mouse moved pixels with 640/actual_window_width and
480/actual_window_height.
the resolutions are really hardcoded in an ugly combination of the
values r_mode supports, a string in strings/*.lang ("#str_04222")
describing the resolutions r_mode supports
("640x480;800x600;1024x768;1152x864;1280x1024;1600x1200")
and a string in mainmenu.gui with the corresponding r_mode values
("3;4;5;6;7;8").. as neither the strings nor mainmenu.gui are GPL'ed
I can't really redistribute a changed version of them.
So I added lots of resolutions to r_vidModes and wrote two functions
that generate the resolutions list string and r_mode value
string for the GUI.
Then I added a hack in the code that detects when the "window" for the
system options ("choiceDef OS2Primary") is created and overwrites the
hardcoded strings with custom ones from my new functions.
This is tested with both the main game and the official d3xp
(Resurrection of Evil) Addon.
No idea if it works with other mods, depends on whether they just copied
that part of the menu or wrote their own.
Don't include the lazy precompiled.h everywhere, only what's
required for the compilation unit.
platform.h needs to be included instead to provide all essential
defines and types.
All includes use the relative path to the neo or the game
specific root.
Move all idlib related includes from idlib/Lib.h to precompiled.h.
precompiled.h still exists for the MFC stuff in tools/.
Add some missing header guards.
hides overloaded virtual function
Fix member signatures of deriving classes to its super classes.
Removes the unused idGameBustOutWindow::Activate() and the
useless idMarkerWindow::GetWinVarByName().
variable set but not used
Removes some CollisionModel code under _DEBUG which was probably a
leftover, since it was completely useless (its done later anyways).