2017-12-08 21:46:09 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2017 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef ImGuiLayer_DEFINED
|
|
|
|
#define ImGuiLayer_DEFINED
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkPaint.h"
|
|
|
|
#include "include/private/SkTArray.h"
|
|
|
|
#include "tools/sk_app/Window.h"
|
2018-09-19 15:31:27 +00:00
|
|
|
|
2017-12-08 21:46:09 +00:00
|
|
|
#include "imgui.h"
|
|
|
|
|
2019-02-09 21:32:58 +00:00
|
|
|
namespace ImGui {
|
|
|
|
|
|
|
|
// Helper object for drawing in a widget region, with draggable points
|
|
|
|
struct DragCanvas {
|
|
|
|
DragCanvas(const void* id, SkPoint tl = { 0.0f, 0.0f }, SkPoint br = { 1.0f, 1.0f },
|
|
|
|
float aspect = -1.0f)
|
|
|
|
: fID(0), fDragging(false) {
|
|
|
|
ImGui::PushID(id);
|
|
|
|
fDrawList = ImGui::GetWindowDrawList();
|
|
|
|
|
|
|
|
// Logical size
|
|
|
|
SkScalar w = SkTAbs(br.fX - tl.fX),
|
|
|
|
h = SkTAbs(br.fY - tl.fY);
|
|
|
|
|
|
|
|
// Determine aspect ratio automatically by default
|
|
|
|
if (aspect < 0) {
|
|
|
|
aspect = h / w;
|
|
|
|
}
|
|
|
|
|
2020-02-07 15:36:46 +00:00
|
|
|
float availWidth = std::max(ImGui::GetContentRegionAvailWidth(), 1.0f);
|
2019-02-09 21:32:58 +00:00
|
|
|
fPos = ImGui::GetCursorScreenPos();
|
|
|
|
fSize = ImVec2(availWidth, availWidth * aspect);
|
|
|
|
|
|
|
|
SkPoint local[4] = {
|
|
|
|
{ tl.fX, tl.fY },
|
|
|
|
{ br.fX, tl.fY },
|
|
|
|
{ tl.fX, br.fY },
|
|
|
|
{ br.fX, br.fY },
|
|
|
|
};
|
|
|
|
SkPoint screen[4] = {
|
|
|
|
{ fPos.x , fPos.y },
|
|
|
|
{ fPos.x + fSize.x, fPos.y },
|
|
|
|
{ fPos.x , fPos.y + fSize.y },
|
|
|
|
{ fPos.x + fSize.x, fPos.y + fSize.y },
|
|
|
|
};
|
|
|
|
fLocalToScreen.setPolyToPoly(local, screen, 4);
|
|
|
|
fScreenToLocal.setPolyToPoly(screen, local, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
~DragCanvas() {
|
|
|
|
ImGui::SetCursorScreenPos(ImVec2(fPos.x, fPos.y + fSize.y));
|
|
|
|
ImGui::Spacing();
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillColor(ImU32 color) {
|
|
|
|
fDrawList->AddRectFilled(fPos, ImVec2(fPos.x + fSize.x, fPos.y + fSize.y), color);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dragPoint(SkPoint* p, bool tooltip = false, ImU32 color = 0xFFFFFFFF) {
|
|
|
|
// Transform points from logical coordinates to screen coordinates
|
|
|
|
SkPoint center = fLocalToScreen.mapXY(p->fX, p->fY);
|
|
|
|
|
|
|
|
// Invisible 10x10 button
|
|
|
|
ImGui::PushID(fID++);
|
|
|
|
ImGui::SetCursorScreenPos(ImVec2(center.fX - 5, center.fY - 5));
|
|
|
|
ImGui::InvisibleButton("", ImVec2(10, 10));
|
|
|
|
|
|
|
|
if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) {
|
|
|
|
// Update screen position to track mouse, clamped to our area
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
center.set(SkTPin(io.MousePos.x, fPos.x, fPos.x + fSize.x),
|
|
|
|
SkTPin(io.MousePos.y, fPos.y, fPos.y + fSize.y));
|
|
|
|
|
|
|
|
// Update local coordinates for the caller
|
|
|
|
*p = fScreenToLocal.mapXY(center.fX, center.fY);
|
|
|
|
fDragging = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tooltip && ImGui::IsItemHovered()) {
|
|
|
|
ImGui::SetTooltip("x: %.3f\ny: %.3f", p->fX, p->fY);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
|
|
|
|
fScreenPoints.push_back(ImVec2(center.fX, center.fY));
|
|
|
|
fDrawList->AddCircle(fScreenPoints.back(), 5.0f, color);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImDrawList* fDrawList;
|
|
|
|
|
|
|
|
// Location and dimensions (in screen coordinates)
|
|
|
|
ImVec2 fPos;
|
|
|
|
ImVec2 fSize;
|
|
|
|
|
|
|
|
// Screen coordinates of points (for additional user drawing)
|
|
|
|
SkSTArray<4, ImVec2, true> fScreenPoints;
|
|
|
|
|
|
|
|
// To simplify dragPoint
|
|
|
|
SkMatrix fLocalToScreen;
|
|
|
|
SkMatrix fScreenToLocal;
|
|
|
|
|
|
|
|
int fID;
|
|
|
|
bool fDragging;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-12-08 21:46:09 +00:00
|
|
|
class ImGuiLayer : public sk_app::Window::Layer {
|
|
|
|
public:
|
|
|
|
ImGuiLayer();
|
2018-06-29 18:30:48 +00:00
|
|
|
~ImGuiLayer() override;
|
2017-12-08 21:46:09 +00:00
|
|
|
|
|
|
|
typedef std::function<void(SkCanvas*)> SkiaWidgetFunc;
|
|
|
|
void skiaWidget(const ImVec2& size, SkiaWidgetFunc func);
|
|
|
|
|
|
|
|
void onAttach(sk_app::Window* window) override;
|
|
|
|
void onPrePaint() override;
|
2019-03-04 16:00:10 +00:00
|
|
|
void onPaint(SkSurface*) override;
|
2019-08-29 14:39:22 +00:00
|
|
|
bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override;
|
|
|
|
bool onMouseWheel(float delta, skui::ModifierKey modifiers) override;
|
|
|
|
bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override;
|
|
|
|
bool onChar(SkUnichar c, skui::ModifierKey modifiers) override;
|
2017-12-08 21:46:09 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
sk_app::Window* fWindow;
|
|
|
|
SkPaint fFontPaint;
|
|
|
|
SkTArray<SkiaWidgetFunc> fSkiaWidgetFuncs;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|