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