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