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