Flutter Engine
The Flutter Engine
ImGuiLayer.cpp
Go to the documentation of this file.
1/*
2* Copyright 2017 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
9
16#include "include/core/SkRect.h"
24#include "src/base/SkTime.h"
26#include "tools/skui/Key.h"
27
28#include <cstdint>
29
30using namespace sk_app;
31
32static void build_ImFontAtlas(ImFontAtlas& atlas, SkPaint& fontPaint) {
33 int w, h;
34 unsigned char* pixels;
35 atlas.GetTexDataAsAlpha8(&pixels, &w, &h);
37 SkPixmap pmap(info, pixels, info.minRowBytes());
38 SkMatrix localMatrix = SkMatrix::Scale(1.0f / w, 1.0f / h);
39 auto fontImage = SkImages::RasterFromPixmap(pmap, nullptr, nullptr);
40 auto fontShader = fontImage->makeShader(SkSamplingOptions(SkFilterMode::kLinear), localMatrix);
41 fontPaint.setShader(fontShader);
42 fontPaint.setColor(SK_ColorWHITE);
43 atlas.TexID = &fontPaint;
44}
45
47 // ImGui initialization:
49 ImGuiIO& io = ImGui::GetIO();
50
51 // Keymap...
52 io.KeyMap[ImGuiKey_Tab] = (int)skui::Key::kTab;
53 io.KeyMap[ImGuiKey_LeftArrow] = (int)skui::Key::kLeft;
54 io.KeyMap[ImGuiKey_RightArrow] = (int)skui::Key::kRight;
55 io.KeyMap[ImGuiKey_UpArrow] = (int)skui::Key::kUp;
56 io.KeyMap[ImGuiKey_DownArrow] = (int)skui::Key::kDown;
57 io.KeyMap[ImGuiKey_PageUp] = (int)skui::Key::kPageUp;
58 io.KeyMap[ImGuiKey_PageDown] = (int)skui::Key::kPageDown;
59 io.KeyMap[ImGuiKey_Home] = (int)skui::Key::kHome;
60 io.KeyMap[ImGuiKey_End] = (int)skui::Key::kEnd;
61 io.KeyMap[ImGuiKey_Delete] = (int)skui::Key::kDelete;
62 io.KeyMap[ImGuiKey_Backspace] = (int)skui::Key::kBack;
63 io.KeyMap[ImGuiKey_Enter] = (int)skui::Key::kOK;
64 io.KeyMap[ImGuiKey_Escape] = (int)skui::Key::kEscape;
65 io.KeyMap[ImGuiKey_A] = (int)skui::Key::kA;
66 io.KeyMap[ImGuiKey_C] = (int)skui::Key::kC;
67 io.KeyMap[ImGuiKey_V] = (int)skui::Key::kV;
68 io.KeyMap[ImGuiKey_X] = (int)skui::Key::kX;
69 io.KeyMap[ImGuiKey_Y] = (int)skui::Key::kY;
70 io.KeyMap[ImGuiKey_Z] = (int)skui::Key::kZ;
71
72 build_ImFontAtlas(*io.Fonts, fFontPaint);
73}
74
76 ImGui::DestroyContext();
77}
78
79void ImGuiLayer::setScaleFactor(float scaleFactor) {
80 ImGui::GetStyle().ScaleAllSizes(scaleFactor);
81
82 ImFontAtlas& atlas = *ImGui::GetIO().Fonts;
83 atlas.Clear();
84 ImFontConfig cfg;
85 cfg.SizePixels = 13 * scaleFactor;
86 atlas.AddFontDefault(&cfg);
87 build_ImFontAtlas(atlas, fFontPaint);
88}
89
90#if defined(SK_BUILD_FOR_UNIX)
91static const char* get_clipboard_text(void* user_data) {
93 return w->getClipboardText();
94}
95
96static void set_clipboard_text(void* user_data, const char* text) {
98 w->setClipboardText(text);
99}
100#endif
101
103 fWindow = window;
104
105#if defined(SK_BUILD_FOR_UNIX)
106 ImGuiIO& io = ImGui::GetIO();
107 io.ClipboardUserData = fWindow;
108 io.GetClipboardTextFn = get_clipboard_text;
109 io.SetClipboardTextFn = set_clipboard_text;
110#endif
111}
112
114 ImGuiIO& io = ImGui::GetIO();
115 io.MousePos.x = static_cast<float>(x);
116 io.MousePos.y = static_cast<float>(y);
118 io.MouseDown[0] = true;
119 } else if (skui::InputState::kUp == state) {
120 io.MouseDown[0] = false;
121 }
122 return io.WantCaptureMouse;
123}
124
125bool ImGuiLayer::onMouseWheel(float delta, int, int, skui::ModifierKey modifiers) {
126 ImGuiIO& io = ImGui::GetIO();
127 io.MouseWheel += delta;
128 return io.WantCaptureMouse;
129}
130
131void ImGuiLayer::skiaWidget(const ImVec2& size, SkiaWidgetFunc func) {
132 intptr_t funcIndex = fSkiaWidgetFuncs.size();
133 fSkiaWidgetFuncs.push_back(func);
134 ImGui::Image((ImTextureID)funcIndex, size);
135}
136
138 // Update ImGui input
139 ImGuiIO& io = ImGui::GetIO();
140
141 static double previousTime = 0.0;
142 double currentTime = SkTime::GetSecs();
143 io.DeltaTime = static_cast<float>(currentTime - previousTime);
144 previousTime = currentTime;
145
146 io.DisplaySize.x = static_cast<float>(fWindow->width());
147 io.DisplaySize.y = static_cast<float>(fWindow->height());
148
149 io.KeyAlt = io.KeysDown[static_cast<int>(skui::Key::kOption)];
150 io.KeyCtrl = io.KeysDown[static_cast<int>(skui::Key::kCtrl)];
151 io.KeyShift = io.KeysDown[static_cast<int>(skui::Key::kShift)];
152 io.KeySuper = io.KeysDown[static_cast<int>(skui::Key::kSuper)];
153
154 ImGui::NewFrame();
155}
156
158 // This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
159 // (widgets, etc...) that have been issued
160 ImGui::Render();
161
162 // Then we fetch the most recent data, and convert it so we can render with Skia
163 const ImDrawData* drawData = ImGui::GetDrawData();
167
168 auto canvas = surface->getCanvas();
169
170 for (int i = 0; i < drawData->CmdListsCount; ++i) {
171 const ImDrawList* drawList = drawData->CmdLists[i];
172
173 // De-interleave all vertex data (sigh), convert to Skia types
174 pos.clear(); uv.clear(); color.clear();
175 for (int j = 0; j < drawList->VtxBuffer.size(); ++j) {
176 const ImDrawVert& vert = drawList->VtxBuffer[j];
177 pos.push_back(SkPoint::Make(vert.pos.x, vert.pos.y));
178 uv.push_back(SkPoint::Make(vert.uv.x, vert.uv.y));
179 color.push_back(vert.col);
180 }
181 // ImGui colors are RGBA
182 SkSwapRB(color.begin(), color.begin(), color.size());
183
184 int indexOffset = 0;
185
186 // Draw everything with canvas.drawVertices...
187 for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
188 const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];
189
190 SkAutoCanvasRestore acr(canvas, true);
191
192 // TODO: Find min/max index for each draw, so we know how many vertices (sigh)
193 if (drawCmd->UserCallback) {
194 drawCmd->UserCallback(drawList, drawCmd);
195 } else {
196 intptr_t idIndex = (intptr_t)drawCmd->TextureId;
197 if (idIndex < fSkiaWidgetFuncs.size()) {
198 // Small image IDs are actually indices into a list of callbacks. We directly
199 // examing the vertex data to deduce the image rectangle, then reconfigure the
200 // canvas to be clipped and translated so that the callback code gets to use
201 // Skia to render a widget in the middle of an ImGui panel.
202 ImDrawIdx rectIndex = drawList->IdxBuffer[indexOffset];
203 SkPoint tl = pos[rectIndex], br = pos[rectIndex + 2];
204 canvas->clipRect(SkRect::MakeLTRB(tl.fX, tl.fY, br.fX, br.fY));
205 canvas->translate(tl.fX, tl.fY);
206 fSkiaWidgetFuncs[idIndex](canvas);
207 } else {
208 SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
210
211 canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
212 drawCmd->ClipRect.z, drawCmd->ClipRect.w));
214 drawList->VtxBuffer.size(),
215 pos.begin(), uv.begin(), color.begin(),
216 drawCmd->ElemCount,
217 drawList->IdxBuffer.begin() + indexOffset);
218 canvas->drawVertices(vertices, SkBlendMode::kModulate, *paint);
219 }
220 indexOffset += drawCmd->ElemCount;
221 }
222 }
223 }
224
225 fSkiaWidgetFuncs.clear();
226}
227
229 ImGuiIO& io = ImGui::GetIO();
230 io.KeysDown[static_cast<int>(key)] = (skui::InputState::kDown == state);
231 return io.WantCaptureKeyboard;
232}
233
235 ImGuiIO& io = ImGui::GetIO();
236 if (io.WantTextInput) {
237 if (c > 0 && c < 0x10000) {
238 io.AddInputCharacter(c);
239 }
240 return true;
241 }
242 return false;
243}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static void build_ImFontAtlas(ImFontAtlas &atlas, SkPaint &fontPaint)
Definition: ImGuiLayer.cpp:32
SkPoint pos
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kModulate
r = s*d
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
SK_API void SkSwapRB(uint32_t *dest, const uint32_t *src, int count)
Definition: SkSwizzle.cpp:12
int32_t SkUnichar
Definition: SkTypes.h:175
bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override
Definition: ImGuiLayer.cpp:113
void onAttach(sk_app::Window *window) override
Definition: ImGuiLayer.cpp:102
void onPaint(SkSurface *) override
Definition: ImGuiLayer.cpp:157
void onPrePaint() override
Definition: ImGuiLayer.cpp:137
bool onMouseWheel(float delta, int x, int y, skui::ModifierKey modifiers) override
Definition: ImGuiLayer.cpp:125
~ImGuiLayer() override
Definition: ImGuiLayer.cpp:75
std::function< void(SkCanvas *)> SkiaWidgetFunc
Definition: ImGuiLayer.h:140
void setScaleFactor(float scaleFactor)
Definition: ImGuiLayer.cpp:79
bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override
Definition: ImGuiLayer.cpp:228
void skiaWidget(const ImVec2 &size, SkiaWidgetFunc func)
Definition: ImGuiLayer.cpp:131
bool onChar(SkUnichar c, skui::ModifierKey modifiers) override
Definition: ImGuiLayer.cpp:234
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setShader(sk_sp< SkShader > shader)
void push_back(const T &v)
Definition: SkTDArray.h:219
T * begin()
Definition: SkTDArray.h:150
void clear()
Definition: SkTDArray.h:175
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
Definition: SkVertices.cpp:200
@ kTriangles_VertexMode
Definition: SkVertices.h:31
int height() const
Definition: Window.cpp:130
int width() const
Definition: Window.cpp:123
int size() const
Definition: SkTArray.h:421
const Paint & paint
Definition: color_source.cc:38
DlColor color
GLFWwindow * window
Definition: main.cc:45
VkSurfaceKHR surface
Definition: main.cc:49
AtkStateType state
if(end==-1)
std::u16string text
double y
double x
SK_API sk_sp< SkImage > RasterFromPixmap(const SkPixmap &pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
sk_sp< const SkImage > atlas
Definition: SkRecords.h:331
double GetSecs()
Definition: SkTime.h:16
static EGLResult< EGLContext > CreateContext(EGLDisplay display, EGLConfig config, EGLContext share=EGL_NO_CONTEXT)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
CanvasImage Image
Definition: dart_ui.cc:55
SkSamplingOptions(SkFilterMode::kLinear))
InputState
Definition: InputState.h:6
ModifierKey
Definition: ModifierKey.h:9
Key
Definition: Key.h:6
@ kBack
(CLR)
@ kHome
the home key - added to match android
@ kEnd
the red key
@ kOK
the center key
SkScalar w
SkScalar h
static SkImageInfo MakeA8(int width, int height)
float fX
x-axis value
Definition: SkPoint_impl.h:164
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
float fY
y-axis value
Definition: SkPoint_impl.h:165
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646
void * user_data