SatDump 2.0.0-alpha-520736c72
Loading...
Searching...
No Matches
context_wrapper.h
1#pragma once
2
3#include "core/backend.h"
4#include "imgui/imgui.h"
5#include "imgui/imgui_internal.h"
6#include <cmath>
7
8inline static void CopyIOEvents(ImGuiContext *src, ImGuiContext *dst, ImVec2 origin, float scale)
9{
10 dst->PlatformImeData = src->PlatformImeData;
11 dst->IO.DeltaTime = src->IO.DeltaTime;
12 dst->InputEventsQueue = src->InputEventsTrail;
13 for (ImGuiInputEvent &e : dst->InputEventsQueue)
14 {
15 if (e.Type == ImGuiInputEventType_MousePos)
16 {
17 e.MousePos.PosX = (e.MousePos.PosX - origin.x) / scale;
18 e.MousePos.PosY = (e.MousePos.PosY - origin.y) / scale;
19 }
20 }
21}
22
23inline static void AppendDrawData(ImDrawList *src, ImVec2 origin, float scale)
24{
25 // TODO optimize if vtx_start == 0 || if idx_start == 0
26 ImDrawList *dl = ImGui::GetWindowDrawList();
27 const int vtx_start = dl->VtxBuffer.size();
28 const int idx_start = dl->IdxBuffer.size();
29 dl->VtxBuffer.resize(dl->VtxBuffer.size() + src->VtxBuffer.size());
30 dl->IdxBuffer.resize(dl->IdxBuffer.size() + src->IdxBuffer.size());
31 dl->CmdBuffer.reserve(dl->CmdBuffer.size() + src->CmdBuffer.size());
32 dl->_VtxWritePtr = dl->VtxBuffer.Data + vtx_start;
33 dl->_IdxWritePtr = dl->IdxBuffer.Data + idx_start;
34 const ImDrawVert *vtx_read = src->VtxBuffer.Data;
35 const ImDrawIdx *idx_read = src->IdxBuffer.Data;
36 for (int i = 0, c = src->VtxBuffer.size(); i < c; ++i)
37 {
38 dl->_VtxWritePtr[i].uv = vtx_read[i].uv;
39 dl->_VtxWritePtr[i].col = vtx_read[i].col;
40 dl->_VtxWritePtr[i].pos = vtx_read[i].pos * scale + origin;
41 }
42 for (int i = 0, c = src->IdxBuffer.size(); i < c; ++i)
43 {
44 dl->_IdxWritePtr[i] = idx_read[i] + vtx_start;
45 }
46 for (auto cmd : src->CmdBuffer)
47 {
48 cmd.IdxOffset += idx_start;
49 IM_ASSERT(cmd.VtxOffset == 0);
50 cmd.ClipRect.x = cmd.ClipRect.x * scale + origin.x;
51 cmd.ClipRect.y = cmd.ClipRect.y * scale + origin.y;
52 cmd.ClipRect.z = cmd.ClipRect.z * scale + origin.x;
53 cmd.ClipRect.w = cmd.ClipRect.w * scale + origin.y;
54 dl->CmdBuffer.push_back(cmd);
55 }
56
57 dl->_VtxCurrentIdx += src->VtxBuffer.size();
58 dl->_VtxWritePtr = dl->VtxBuffer.Data + dl->VtxBuffer.size();
59 dl->_IdxWritePtr = dl->IdxBuffer.Data + dl->IdxBuffer.size();
60}
61
63{
64 bool extra_window_wrapper = false;
65 ImVec2 size = {0.f, 0.f};
66 ImU32 color = IM_COL32_WHITE;
67 bool zoom_enabled = true;
68 float zoom_min = 0.3f;
69 float zoom_max = 2.f;
70 float zoom_divisions = 10.f;
71 float zoom_smoothness = 5.f;
72 float default_zoom = 1.f;
73 ImGuiMouseButton scroll_button = ImGuiMouseButton_Middle;
74};
75
77{
78public:
80 ContainedContextConfig &config() { return m_config; }
81 void begin();
82 void end();
83 [[nodiscard]] ImVec2 size() const { return m_size; }
84 [[nodiscard]] float scale() const { return m_scale; }
85 [[nodiscard]] const ImVec2 &origin() const { return m_origin; }
86 [[nodiscard]] bool hovered() const { return m_hovered; }
87 [[nodiscard]] const ImVec2 &scroll() const { return m_scroll; }
88 [[nodiscard]] ImVec2 getScreenDelta() { return m_original_ctx->IO.MouseDelta / scale(); }
89 ImGuiContext *getRawContext() { return m_ctx; }
90 void setFontDensity();
91
92private:
94
95 ImVec2 m_origin;
96 ImVec2 m_pos;
97 ImVec2 m_size;
98 ImGuiContext *m_ctx = nullptr;
99 ImGuiContext *m_original_ctx = nullptr;
100
101 bool m_anyWindowHovered = false;
102 bool m_anyItemActive = false;
103 bool m_hovered = false;
104
105 float m_scale = m_config.default_zoom, m_scaleTarget = m_config.default_zoom;
106 ImVec2 m_scroll = {0.f, 0.f};
107};
108
109inline ContainedContext::~ContainedContext()
110{
111 if (m_ctx)
112 ImGui::DestroyContext(m_ctx);
113}
114
115// Call after Begin()
116inline void ContainedContext::setFontDensity()
117{
118#if IMGUI_VERSION_NUM >= 19198
119 ImGui::SetFontRasterizerDensity(roundf(m_scale * 100.0f) / 100.0f); // Round density to two digits.
120#endif
121}
122
123inline void ContainedContext::begin()
124{
125 ImGui::PushID(this);
126 ImGui::PushStyleColor(ImGuiCol_ChildBg, m_config.color);
127 ImGui::BeginChild("view_port", m_config.size, 0, ImGuiWindowFlags_NoMove);
128 setFontDensity();
129 ImGui::PopStyleColor();
130 m_pos = ImGui::GetWindowPos();
131
132 backend::mouse_set_offset_x += m_pos.x;
133 backend::mouse_set_offset_y += m_pos.y;
134
135 m_size = ImGui::GetContentRegionAvail();
136 m_origin = ImGui::GetCursorScreenPos();
137 m_original_ctx = ImGui::GetCurrentContext();
138 const ImGuiStyle &orig_style = ImGui::GetStyle();
139 if (!m_ctx)
140 {
141 // Also share clipboard between contexts
142 m_ctx = ImGui::CreateContext(ImGui::GetIO().Fonts);
143 m_ctx->PlatformIO.Platform_GetClipboardTextFn = m_original_ctx->PlatformIO.Platform_GetClipboardTextFn;
144 m_ctx->PlatformIO.Platform_SetClipboardTextFn = m_original_ctx->PlatformIO.Platform_SetClipboardTextFn;
145 }
146 ImGui::SetCurrentContext(m_ctx);
147 ImGuiStyle &new_style = ImGui::GetStyle();
148 new_style = orig_style;
149
150 CopyIOEvents(m_original_ctx, m_ctx, m_origin, m_scale);
151
152 ImGui::GetIO().DisplaySize = m_size / m_scale;
153 ImGui::GetIO().ConfigInputTrickleEventQueue = false;
154
155 // Copy the ImGuiBackendFlags_RendererHasTextures flag as they need to be matching.
156 // This will also copy the ImGuiBackendFlags_RendererHasVtxOffset flag which will be more optimal in case large draw calls are being made.
157 ImGui::GetIO().ConfigFlags = m_original_ctx->IO.ConfigFlags;
158 ImGui::GetIO().BackendFlags = m_original_ctx->IO.BackendFlags;
159#ifdef IMGUI_HAS_VIEWPORT
160 ImGui::GetIO().ConfigFlags &= ~(ImGuiConfigFlags_ViewportsEnable | ImGuiConfigFlags_DockingEnable);
161#endif
162
163 ImGui::NewFrame();
164
165 if (!m_config.extra_window_wrapper)
166 return;
167 ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Appearing);
168 ImGui::SetNextWindowSize(ImGui::GetMainViewport()->WorkSize);
169 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
170 ImGui::Begin("viewport_container", nullptr,
171 ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
172 setFontDensity();
173 ImGui::PopStyleVar();
174}
175
176inline void ContainedContext::end()
177{
178 m_anyWindowHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow);
179 if (m_config.extra_window_wrapper && ImGui::IsWindowHovered())
180 m_anyWindowHovered = false;
181
182 m_anyItemActive = ImGui::IsAnyItemActive();
183
184 if (m_config.extra_window_wrapper)
185 ImGui::End();
186
187 ImGui::Render();
188
189 ImDrawData *draw_data = ImGui::GetDrawData();
190
191 m_original_ctx->PlatformImeData = m_ctx->PlatformImeData;
192 ImGui::SetCurrentContext(m_original_ctx);
193 m_original_ctx = nullptr;
194
195 for (int i = 0; i < draw_data->CmdListsCount; ++i)
196 AppendDrawData(draw_data->CmdLists[i], m_origin, m_scale);
197
198 m_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows); //&& !m_anyWindowHovered;
199
200 // Zooming
201 if (m_config.zoom_enabled && m_hovered && ImGui::GetIO().MouseWheel != 0.f)
202 {
203 m_scaleTarget += ImGui::GetIO().MouseWheel / m_config.zoom_divisions;
204 m_scaleTarget = m_scaleTarget < m_config.zoom_min ? m_config.zoom_min : m_scaleTarget;
205 m_scaleTarget = m_scaleTarget > m_config.zoom_max ? m_config.zoom_max : m_scaleTarget;
206
207 if (m_config.zoom_smoothness == 0.f)
208 {
209 m_scroll += (ImGui::GetMousePos() - m_pos) / m_scaleTarget - (ImGui::GetMousePos() - m_pos) / m_scale;
210 m_scale = m_scaleTarget;
211 }
212 }
213 if (abs(m_scaleTarget - m_scale) >= 0.015f / m_config.zoom_smoothness)
214 {
215 float cs = (m_scaleTarget - m_scale) / m_config.zoom_smoothness;
216 m_scroll += (ImGui::GetMousePos() - m_pos) / (m_scale + cs) - (ImGui::GetMousePos() - m_pos) / m_scale;
217 m_scale += (m_scaleTarget - m_scale) / m_config.zoom_smoothness;
218
219 if (abs(m_scaleTarget - m_scale) < 0.015f / m_config.zoom_smoothness)
220 {
221 m_scroll += (ImGui::GetMousePos() - m_pos) / m_scaleTarget - (ImGui::GetMousePos() - m_pos) / m_scale;
222 m_scale = m_scaleTarget;
223 }
224 }
225
226 // Zoom reset
227 if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Middle))
228 m_scaleTarget = m_config.default_zoom;
229
230 // Scrolling
231 if (m_hovered && !m_anyItemActive && ImGui::IsMouseDragging(m_config.scroll_button, 0.f))
232 {
233 m_scroll += ImGui::GetIO().MouseDelta / m_scale;
234 }
235 this->m_ctx->IO.MousePos = (ImGui::GetMousePos() - m_origin) / m_scale;
236 ImGui::EndChild();
237 ImGui::PopID();
238
239 backend::mouse_set_offset_x -= m_pos.x;
240 backend::mouse_set_offset_y -= m_pos.y;
241}
Definition context_wrapper.h:77
Definition context_wrapper.h:63