@@ -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
106108State management (` eqAppStateMng ` ):
107109
@@ -140,7 +142,9 @@ frame the loop sleeps `sys_sleep` ms (default 1).
1401426 . 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 ) ).
1441487 . ` EndScene ` : ` g_matSystem->EndFrame() ` .
1451498 . 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+
179188Keyboard 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
181190for 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
186195console 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
0 commit comments