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