blob: f7ee4daafc469465006a926e614132013286b9f3 [file] [log] [blame]
Brian Osmand67e5182017-12-08 16:46:09 -05001/*
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"
Hal Canary8a001442018-09-19 11:31:27 -040014
Brian Osmand67e5182017-12-08 16:46:09 -050015#include "imgui.h"
16
Brian Osman535c5e32019-02-09 16:32:58 -050017namespace ImGui {
18
19// Helper object for drawing in a widget region, with draggable points
20struct 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
56 ~DragCanvas() {
57 ImGui::SetCursorScreenPos(ImVec2(fPos.x, fPos.y + fSize.y));
58 ImGui::Spacing();
59 ImGui::PopID();
60 }
61
62 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
Brian Osmand67e5182017-12-08 16:46:09 -0500115class ImGuiLayer : public sk_app::Window::Layer {
116public:
117 ImGuiLayer();
Brian Osman7197e052018-06-29 14:30:48 -0400118 ~ImGuiLayer() override;
Brian Osmand67e5182017-12-08 16:46:09 -0500119
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;
Robert Phillips9882dae2019-03-04 11:00:10 -0500125 void onPaint(SkSurface*) override;
Brian Osmand67e5182017-12-08 16:46:09 -0500126 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
131private:
132 sk_app::Window* fWindow;
133 SkPaint fFontPaint;
134 SkTArray<SkiaWidgetFunc> fSkiaWidgetFuncs;
135};
136
137#endif