• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #ifndef ImGuiLayer_DEFINED
9 #define ImGuiLayer_DEFINED
10 
11 #include "include/core/SkPaint.h"
12 #include "include/private/SkTArray.h"
13 #include "include/private/SkTPin.h"
14 #include "tools/sk_app/Window.h"
15 
16 #include "imgui.h"
17 
18 namespace ImGui {
19 
20 // Helper object for drawing in a widget region, with draggable points
21 struct DragCanvas {
22     DragCanvas(const void* id, SkPoint tl = { 0.0f, 0.0f }, SkPoint br = { 1.0f, 1.0f },
23                float aspect = -1.0f)
24             : fID(0), fDragging(false) {
25         ImGui::PushID(id);
26         fDrawList = ImGui::GetWindowDrawList();
27 
28         // Logical size
29         SkScalar w = SkTAbs(br.fX - tl.fX),
30                  h = SkTAbs(br.fY - tl.fY);
31 
32         // Determine aspect ratio automatically by default
33         if (aspect < 0) {
34             aspect = h / w;
35         }
36 
37         float availWidth = std::max(ImGui::GetContentRegionAvailWidth(), 1.0f);
38         fPos = ImGui::GetCursorScreenPos();
39         fSize = ImVec2(availWidth, availWidth * aspect);
40 
41         SkPoint local[4] = {
42             { tl.fX, tl.fY },
43             { br.fX, tl.fY },
44             { tl.fX, br.fY },
45             { br.fX, br.fY },
46         };
47         SkPoint screen[4] = {
48             { fPos.x          , fPos.y           },
49             { fPos.x + fSize.x, fPos.y           },
50             { fPos.x          , fPos.y + fSize.y },
51             { fPos.x + fSize.x, fPos.y + fSize.y },
52         };
53         fLocalToScreen.setPolyToPoly(local, screen, 4);
54         fScreenToLocal.setPolyToPoly(screen, local, 4);
55     }
56 
~DragCanvasDragCanvas57     ~DragCanvas() {
58         ImGui::SetCursorScreenPos(ImVec2(fPos.x, fPos.y + fSize.y));
59         ImGui::Spacing();
60         ImGui::PopID();
61     }
62 
fillColorDragCanvas63     void fillColor(ImU32 color) {
64         fDrawList->AddRectFilled(fPos, ImVec2(fPos.x + fSize.x, fPos.y + fSize.y), color);
65     }
66 
67     void dragPoint(SkPoint* p, bool tooltip = false, ImU32 color = 0xFFFFFFFF) {
68         // Transform points from logical coordinates to screen coordinates
69         SkPoint center = fLocalToScreen.mapXY(p->fX, p->fY);
70 
71         // Invisible 10x10 button
72         ImGui::PushID(fID++);
73         ImGui::SetCursorScreenPos(ImVec2(center.fX - 5, center.fY - 5));
74         ImGui::InvisibleButton("", ImVec2(10, 10));
75 
76         if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) {
77             // Update screen position to track mouse, clamped to our area
78             ImGuiIO& io = ImGui::GetIO();
79             center.set(SkTPin(io.MousePos.x, fPos.x, fPos.x + fSize.x),
80                        SkTPin(io.MousePos.y, fPos.y, fPos.y + fSize.y));
81 
82             // Update local coordinates for the caller
83             *p = fScreenToLocal.mapXY(center.fX, center.fY);
84             fDragging = true;
85         }
86 
87         if (tooltip && ImGui::IsItemHovered()) {
88             ImGui::SetTooltip("x: %.3f\ny: %.3f", p->fX, p->fY);
89         }
90 
91         ImGui::PopID();
92 
93         fScreenPoints.push_back(ImVec2(center.fX, center.fY));
94         fDrawList->AddCircle(fScreenPoints.back(), 5.0f, color);
95     }
96 
97     ImDrawList* fDrawList;
98 
99     // Location and dimensions (in screen coordinates)
100     ImVec2 fPos;
101     ImVec2 fSize;
102 
103     // Screen coordinates of points (for additional user drawing)
104     SkSTArray<4, ImVec2, true> fScreenPoints;
105 
106     // To simplify dragPoint
107     SkMatrix fLocalToScreen;
108     SkMatrix fScreenToLocal;
109 
110     int fID;
111     bool fDragging;
112 };
113 
114 }  // namespace ImGui
115 
116 class ImGuiLayer : public sk_app::Window::Layer {
117 public:
118     ImGuiLayer();
119     ~ImGuiLayer() override;
120 
121     void setScaleFactor(float scaleFactor);
122 
123     typedef std::function<void(SkCanvas*)> SkiaWidgetFunc;
124     void skiaWidget(const ImVec2& size, SkiaWidgetFunc func);
125 
126     void onAttach(sk_app::Window* window) override;
127     void onPrePaint() override;
128     void onPaint(SkSurface*) override;
129     bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override;
130     bool onMouseWheel(float delta, skui::ModifierKey modifiers) override;
131     bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override;
132     bool onChar(SkUnichar c, skui::ModifierKey modifiers) override;
133 
134 private:
135     sk_app::Window* fWindow;
136     SkPaint fFontPaint;
137     SkTArray<SkiaWidgetFunc> fSkiaWidgetFuncs;
138 };
139 
140 #endif
141