Skip to content

Commit c00460e

Browse files
SoapyManclaude
andcommitted
- sys: add CHostViewport to render app state inside an ImGui window (disabled in Retail and Profile)
- sys: route input to the state viewport in viewport coordinates - sys: draw EqUI, debug overlays and console in the state viewport, ImGui in a separate pass - render: debug overlay Draw takes color and depth targets - equi: Render takes color target - imgui_backend: add IsTextInputActive - egfman2: render scene in host viewport between model browser and bottom panel - docs: describe host viewport, add codestyle rule for ConVar and ConCommand placement Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 1237bae commit c00460e

16 files changed

Lines changed: 497 additions & 53 deletions

‎docs/codestyle.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ The reference shows the general layout; where it disagrees with this document, t
3535
4. the file's own header last.
3636
- Public interfaces live under `public/` (`I`-prefixed abstract classes); implementations live next
3737
to their module (`C`-prefixed classes).
38+
- In `.cpp` files, console variable and command declarations (`DECLARE_CVAR*`, `DECLARE_CMD*`,
39+
see `framework_core.md`) go at the top, after the includes and before function code: file-local
40+
helpers and other functions are placed below them.
3841
- Logical sections inside a file are separated with a dashed comment line:
3942

4043
```cpp

‎docs/sys_application_overview.md‎

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ input routing, configs and screenshots. An application links `sysLib` (premake p
1111
| `sys_window.cpp/.h` | Window creation, SDL init, game loop (`sysHostInit`, `sysHostGameLoop`, `sysHostTerminate`) |
1212
| `sys_host.cpp/.h` | `g_pHost` (`CGameHost`) — systems, frame, video modes, cursor, input events |
1313
| `sys_state.cpp/.h` | `CAppStateBase`, `eqAppStateMng` — app states |
14+
| `sys_viewport.cpp/.h` | `CHostViewport` — state rendering inside an ImGui window |
1415
| `sys_in_console.cpp/.h` | `g_consoleInput` (`CEqConsoleInput`) — developer console, log |
1516
| `sys_in_joystick.cpp/.h` | `CEqGameControllerSDL` — game controllers |
1617
| `cfgloader.cpp/.h` | `WriteCfgFile`, `writecfg` |
@@ -102,6 +103,7 @@ A state is one mode of the application (menu, game, editor). Derive from `CAppSt
102103
| `HandleKeyPress`, `HandleMouseClick`, `HandleMouseMove`, `HandleMouseWheel`, `HandleJoyAxis` | Input not consumed by console / ImGui / EqUI |
103104
| `GetMouseCursorProperties(visible, centered)` | Cursor visibility and relative (centered) mouse mode |
104105
| `GetTimescale()` | Time scale for this state's `dt` |
106+
| `GetViewport()` | `CHostViewport` the state renders to, `nullptr` for the whole window (see [Host viewport](#host-viewport--chostviewport)) |
105107

106108
State management (`eqAppStateMng`):
107109

@@ -140,7 +142,9 @@ frame the loop sleeps `sys_sleep` ms (default 1).
140142
6. Debug overlay with engine statistics (FPS, draw / dispatch counts, GPU and system memory),
141143
`r_showFPS`, `r_showFPSGraph`. Screenshot (without console / ImGui), then one render pass with
142144
the debug overlay, input debug drawing, console (`g_consoleInput->EndFrame`) and ImGui
143-
(`g_imGuiHost->EndFrame`).
145+
(`g_imGuiHost->EndFrame`). With a visible state viewport, EqUI, debug overlays, input debug
146+
drawing and the console go to the viewport target, ImGui is drawn in a separate backbuffer pass
147+
and the screenshot is taken after it (see [Host viewport](#host-viewport--chostviewport)).
144148
7. `EndScene`: `g_matSystem->EndFrame()`.
145149
8. Pending fullscreen toggle, `g_onEndFrame`.
146150

@@ -176,6 +180,11 @@ dispatched by `CGameHost`:
176180
| Touch | binder touch zones |
177181
| Text input | ImGui → console |
178182

183+
With a visible state viewport (`GetViewport()`), the console, EqUI and the state receive mouse
184+
buttons, movement and wheel only over the viewport, in viewport coordinates. Keys and text go past
185+
the ImGui check while the viewport window is focused or the console is open, unless an ImGui text
186+
field is active. See [Host viewport](#host-viewport--chostviewport).
187+
179188
Keyboard keys and mouse buttons reach command bindings only if the state forwards them to
180189
`g_inputCommandBinder->OnPressEvent` (see [input_overview.md](input_overview.md)). Input is ignored
181190
for 0.25 s after the window regains focus.
@@ -185,6 +194,56 @@ item is hovered, active or focused, or ImGui wants the mouse / keyboard
185194
(`g_imGuiHost->IsImGuiItemsInFocus()`), the event goes no further; key releases still reach the
186195
console so its modifier state does not stick.
187196

197+
## Host viewport — `CHostViewport`
198+
199+
A state can render into a render target shown in an ImGui window instead of the whole window
200+
(tools with panels around the scene). The state owns a `CHostViewport` and returns it from
201+
`CAppStateBase::GetViewport()`.
202+
203+
```cpp
204+
CHostViewport m_viewport{ "egfman2_scene" };
205+
206+
CHostViewport* GetViewport() override { return &m_viewport; }
207+
208+
// ImGui handler (runs in BeginScene, before Update)
209+
if (ImGui::Begin("Scene"))
210+
m_viewport.DrawImGui(); // fills the available content region
211+
ImGui::End();
212+
213+
// Update
214+
const IVector2D viewSize = m_viewport.GetSize();
215+
projMat = perspectiveMatrixY(fov, viewSize.x, viewSize.y, zNear, zFar);
216+
g_renderAPI->BeginRenderPass(
217+
Builder<RenderPassDesc>()
218+
.ColorTarget(m_viewport.GetColorTarget(), true, clearColor)
219+
.DepthStencilTarget(m_viewport.GetDepthTarget())
220+
.DepthClear()
221+
.End());
222+
```
223+
224+
- `DrawImGui(size)` resizes the color and depth targets (backbuffer formats, `ResizeRenderTarget`)
225+
to the drawn size and puts an invisible button with the image in the current ImGui window. The
226+
viewport is *visible* only in a frame where `DrawImGui` was called.
227+
- Viewports are disabled in `Retail` and `Profile` builds (`HOST_VIEWPORT_ENABLED` in
228+
`sys_viewport.h`): `DrawImGui` does nothing and the viewport is never visible.
229+
- When the viewport is not visible (ImGui window closed, `Retail` or `Profile` build),
230+
`GetColorTarget`, `GetDepthTarget` and `GetSize` return the backbuffer, the default depth buffer
231+
and the window size, and the host routes input as without a viewport.
232+
- Input: mouse coordinates passed to the state handlers are relative to the viewport. A button
233+
pressed over the viewport captures the mouse until all captured buttons are released, so drags
234+
continue outside the viewport. Mouse movement and wheel reach the state while the mouse is over
235+
the viewport or captured. Key releases always reach the state, so keys do not stick when focus
236+
moves away.
237+
- `CGameHost::SetCursorPosition` takes viewport coordinates, and a centered cursor
238+
(`GetMouseCursorProperties`) is warped to the viewport center.
239+
- `GetScreenRect`, `ToViewport`, `ToWindow` convert between window and viewport coordinates.
240+
- The state viewport is the main viewport: the host draws EqUI (`equi::Manager->Render(target)`,
241+
view frame of the viewport size), debug overlays (`debugoverlay->Draw` with the viewport targets),
242+
`r_showFPS`, input debug drawing and the console only into it. ImGui stays in the window
243+
backbuffer. Full-screen edge AA is skipped: its luma pass needs a storage source texture.
244+
- `screenshot` with a visible viewport saves the whole window with ImGui, since the viewport gets
245+
to the backbuffer only through ImGui.
246+
188247
## Developer console — `g_consoleInput`
189248
190249
- Opened by the key bound to `toggleconsole` (`bind GRAVE toggleconsole` in

‎docs/tools_overview.md‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ skeleton, animations and sequences, physics objects. Built on `sysLib` with an I
5555
come from `nfd` (`src_dependency/nfd`).
5656

5757
- `-model <path>` opens a model on start.
58+
- The scene is rendered into a `CHostViewport` (see
59+
[sys_application_overview.md](sys_application_overview.md)) shown in the ImGui window between the
60+
model browser and the bottom panel; camera and drag input and hotkeys work while the mouse is over
61+
the scene or the scene window is focused.
5862
- Model browser on the left (View → Model browser) lists `.egf` files under `models/` of the `SP_MOD`
5963
search paths; clicking a file opens it. Directories are scanned when first expanded, Refresh
6064
rescans them. The filter field shows a flat list of files whose names contain the text (case
@@ -63,13 +67,13 @@ come from `nfd` (`src_dependency/nfd`).
6367
waits for them. Their stdout and stderr go to the engine console through a pipe (no console window
6468
is opened); a single compiled model is opened afterwards.
6569
- Camera: Shift + left / right / middle mouse button drag rotates, zooms and pans; the cursor wraps
66-
around the window edges while the camera moves. Left button drag pulls physics objects while
70+
around the scene viewport edges while the camera moves. Left button drag pulls physics objects while
6771
physics simulation runs.
6872
- Physics preview runs eqPhysics with a fixed 1/60 s step on a floor box at zero height. All
6973
surface params of the model fall back to one built-in `default` param. Ragdolls
7074
(`ragdoll/physics_ragdoll.*`) use point and angular limit constraints with the joint limits
7175
from the `.pod`; ragdoll parts collide only with the floor.
72-
- Hotkeys: Ctrl+O open, R reset view, P physics objects, B bones, W wireframe.
76+
- Hotkeys (scene window focused): Ctrl+O open, R reset view, P physics objects, B bones, W wireframe.
7377
- Writes its ConVars to `cfg/egfman2.cfg` instead of the game `cfg/user.cfg` unless `-user_cfg` is
7478
given.
7579

‎public/render/IDebugOverlay.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
class IEqFont;
2525
class IGPURenderPassRecorder;
26+
class ITexture;
2627

2728
using OnDebugDrawFn = EqFunction<bool(IGPURenderPassRecorder* rendPassRecorder)>;
2829

@@ -306,7 +307,8 @@ class IDebugOverlay
306307
virtual void Graph_AddValue( DDGraphBucket* pBucket, float value) = 0;
307308

308309
virtual void SetMatrices( const Matrix4x4 &proj, const Matrix4x4 &view ) = 0;
309-
virtual void Draw(int winWide, int winTall, float timeScale = 1.0f) = 0;
310+
// targets are the backbuffer and the default depth buffer when not set
311+
virtual void Draw(int winWide, int winTall, float timeScale = 1.0f, ITexture* colorTarget = nullptr, ITexture* depthTarget = nullptr) = 0;
310312

311313
// Old interfaces for compatibility
312314

‎shared/equi/EqUI_Manager.cpp‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,16 +243,16 @@ bool CUIManager::IsWindowsVisible() const
243243
return false;
244244
}
245245

246-
void CUIManager::Render()
246+
void CUIManager::Render(ITexture* colorTarget)
247247
{
248-
PROF_EVENT("EqUI render");
249-
250-
if(!m_rootPanel)
248+
if (!m_rootPanel || !colorTarget)
251249
return;
252250

251+
PROF_EVENT("EqUI render");
252+
253253
IGPURenderPassRecorderPtr rendPassRecorder = g_renderAPI->BeginRenderPass(
254254
Builder<RenderPassDesc>()
255-
.ColorTarget(g_matSystem->GetCurrentBackbuffer())
255+
.ColorTarget(colorTarget)
256256
.End()
257257
);
258258
rendPassRecorder->DbgPushGroup("EqUI");

‎shared/equi/EqUI_Manager.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
class IEqFont;
1313
class IMaterial;
1414
class IGPURenderPassRecorder;
15+
class ITexture;
1516

1617
namespace equi
1718
{
@@ -62,7 +63,8 @@ class CUIManager
6263

6364
bool IsWindowsVisible() const;
6465

65-
void Render();
66+
// renders to the backbuffer when target is not set
67+
void Render(ITexture* colorTarget);
6668

6769
bool ProcessMouseEvents(float x, float y, int nMouseButtons, int flags);
6870
bool ProcessKeyboardEvents(int nKeyButtons, int flags);

‎shared/imgui_backend/imgui_host.cpp‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,16 @@ bool CEqImGuiHost::IsImGuiItemsInFocus() const
289289
return false;
290290
}
291291

292+
bool CEqImGuiHost::IsTextInputActive() const
293+
{
294+
#ifdef IMGUI_ENABLED
295+
if (!GImGui)
296+
return false;
297+
return ImGui::GetIO().WantTextInput;
298+
#endif
299+
return false;
300+
}
301+
292302
void CEqImGuiHost::AddDebugHandler(const char* name, IMGUI_HANDLER func)
293303
{
294304
#ifdef IMGUI_ENABLED

‎shared/imgui_backend/imgui_host.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class CEqImGuiHost
4646
void RemoveDebugHandler(const char* name);
4747

4848
bool IsImGuiItemsInFocus() const;
49+
bool IsTextInputActive() const;
4950

5051
private:
5152
struct Menu

‎shared/render/DebugOverlay.cpp‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,15 +1154,18 @@ void CDebugOverlay::SetMatrices( const Matrix4x4 &proj, const Matrix4x4 &view )
11541154
#endif // ENABLE_DEBUG_DRAWING_PROFILE
11551155
}
11561156

1157-
void CDebugOverlay::Draw(int winWide, int winTall, float timescale)
1157+
void CDebugOverlay::Draw(int winWide, int winTall, float timescale, ITexture* colorTarget, ITexture* depthTarget)
11581158
{
11591159
m_frameTime = m_timer.GetTime(true) * timescale;
11601160

11611161
#ifdef ENABLE_DEBUG_DRAWING_PROFILE
1162+
if (!colorTarget)
1163+
return;
1164+
11621165
IGPURenderPassRecorderPtr rendPassRecorder = g_renderAPI->BeginRenderPass(
11631166
Builder<RenderPassDesc>()
1164-
.ColorTarget(g_matSystem->GetCurrentBackbuffer())
1165-
.DepthStencilTarget(g_matSystem->GetDefaultDepthBuffer())
1167+
.ColorTarget(colorTarget)
1168+
.DepthStencilTarget(depthTarget)
11661169
.End()
11671170
);
11681171

‎shared/render/DebugOverlay.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class CDebugOverlay : public IDebugOverlay
6060
void Graph_AddValue(DDGraphBucket* pBucket, float value);
6161

6262
void SetMatrices(const Matrix4x4& proj, const Matrix4x4& view);
63-
void Draw(int winWide, int winTall, float timescale = 1.0f);
63+
void Draw(int winWide, int winTall, float timescale = 1.0f, ITexture* colorTarget = nullptr, ITexture* depthTarget = nullptr);
6464

6565
static void OnShowTextureChanged(ConVar* pVar, char const* pszOldValue);
6666
private:

0 commit comments

Comments
 (0)