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