libs/imgui/src/eu/imgui/scurve.cc
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "eu/imgui/scurve.h" | ||
| 2 | |||
| 3 | #include "eu/assert/assert.h" | ||
| 4 | #include "eu/base/cint.h" | ||
| 5 | |||
| 6 | #include "eu/imgui/ui.h" | ||
| 7 | |||
| 8 | #include "dear_imgui/imgui.h" | ||
| 9 | |||
| 10 | #include <cmath> | ||
| 11 | |||
| 12 | #include "eu/core/scurve.h" | ||
| 13 | |||
| 14 | namespace eu::imgui | ||
| 15 | { | ||
| 16 | |||
| 17 | ✗ | SCurveGuiState::SCurveGuiState(float x, float y) | |
| 18 | ✗ | : drag(x, y) | |
| 19 | { | ||
| 20 | ✗ | } | |
| 21 | |||
| 22 | ✗ | SCurveGuiState SCurveGuiState::light_curve() | |
| 23 | { | ||
| 24 | ✗ | return {0.2f, 0.0f}; | |
| 25 | } | ||
| 26 | |||
| 27 | ✗ | bool imgui_s_curve_editor(const char* title, core::SCurve* curve, SCurveGuiState* gui, FlipX flip_x, const SCurveImguiSettings& settings, bool force_init_curve) | |
| 28 | { | ||
| 29 | ✗ | imgui_text(fmt::format("{} ({} {})", title, curve->slope, curve->threshold)); | |
| 30 | ✗ | if (ImGui::BeginChild(title, settings.widget_size, settings.widget_border ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove) | |
| 31 | ✗ | == false) | |
| 32 | { | ||
| 33 | ✗ | ImGui::EndChild(); | |
| 34 | ✗ | return false; | |
| 35 | } | ||
| 36 | |||
| 37 | ✗ | auto& points = gui->point_cache; | |
| 38 | |||
| 39 | ✗ | bool changed = false; | |
| 40 | |||
| 41 | ✗ | const auto widget_position = ImGui::GetWindowPos(); | |
| 42 | ✗ | const auto widget_size = ImGui::GetWindowSize(); | |
| 43 | |||
| 44 | ✗ | auto* draw = ImGui::GetWindowDrawList(); | |
| 45 | ✗ | draw->AddRectFilled(widget_position, widget_position + widget_size, settings.background_color); | |
| 46 | |||
| 47 | |||
| 48 | ✗ | if (points.max_size() != settings.num_points) | |
| 49 | { | ||
| 50 | ✗ | points.resize(settings.num_points); | |
| 51 | } | ||
| 52 | ✗ | for (std::size_t point_index = 0; point_index < settings.num_points; point_index += 1) | |
| 53 | { | ||
| 54 | ✗ | const float srcx = static_cast<float>(point_index) / static_cast<float>(settings.num_points - 1); // -1 here to include 1.0f when evaluating the curve | |
| 55 | ✗ | const float x = flip_x == FlipX::yes? 1 - srcx : srcx; | |
| 56 | ✗ | const float y = core::calculate_s_curve(srcx, curve->slope, curve->threshold); | |
| 57 | ✗ | points[point_index] = ImVec2{x * widget_size.x, (1 - y) * widget_size.y} + widget_position; | |
| 58 | } | ||
| 59 | ✗ | draw->AddPolyline(points.data(), int_from_sizet(settings.num_points), settings.line_color, ImDrawFlags_None, 1.0f); | |
| 60 | |||
| 61 | ✗ | if (settings.draw_points) | |
| 62 | { | ||
| 63 | ✗ | for (std::size_t point_index = 0; point_index < settings.num_points; point_index += 1) | |
| 64 | { | ||
| 65 | ✗ | draw->AddCircleFilled(points[point_index], settings.point_radius, settings.point_color); | |
| 66 | } | ||
| 67 | } | ||
| 68 | ✗ | draw->AddCircleFilled(ImVec2{gui->drag.x * widget_size.x, (1 - gui->drag.y) * widget_size.y} + widget_position, settings.drag_radius, settings.drag_color); | |
| 69 | |||
| 70 | ✗ | const auto t01 = [&widget_position, &widget_size](const ImVec2& mp) | |
| 71 | { | ||
| 72 | ✗ | const auto x = (mp.x - widget_position.x) / widget_size.x; | |
| 73 | ✗ | const auto y = 1 - ((mp.y - widget_position.y) / widget_size.y); | |
| 74 | ✗ | return ImVec2{x, y}; | |
| 75 | ✗ | }; | |
| 76 | |||
| 77 | ✗ | const auto within01 = [](const ImVec2& p) | |
| 78 | { | ||
| 79 | #define T(s) \ | ||
| 80 | do \ | ||
| 81 | { \ | ||
| 82 | if ((s) < 0.0f || (s) > 1.0f) \ | ||
| 83 | return false; \ | ||
| 84 | } while (false) | ||
| 85 | ✗ | T(p.x); | |
| 86 | ✗ | T(p.y); | |
| 87 | ✗ | return true; | |
| 88 | #undef T | ||
| 89 | }; | ||
| 90 | |||
| 91 | ✗ | if (ImGui::IsMouseDown(settings.button) && within01(t01(ImGui::GetIO().MouseClickedPos[settings.button]))) | |
| 92 | { | ||
| 93 | // mouse is down and drag started inside the component | ||
| 94 | ✗ | const auto mp = ImGui::GetMousePos(); | |
| 95 | ✗ | const auto n = t01(mp); | |
| 96 | ✗ | gui->drag.x = std::min(1.0f, std::max(n.x, 0.0f)); | |
| 97 | ✗ | gui->drag.y = std::min(1.0f, std::max(n.y, 0.0f)); | |
| 98 | ✗ | changed = true; | |
| 99 | } | ||
| 100 | |||
| 101 | ✗ | if (changed || force_init_curve) | |
| 102 | { | ||
| 103 | ✗ | *curve = core::s_curve_from_input(flip_x == FlipX::yes ? 1 - gui->drag.x : gui->drag.x, gui->drag.y); | |
| 104 | } | ||
| 105 | |||
| 106 | ✗ | ImGui::EndChild(); | |
| 107 | |||
| 108 | ✗ | return changed; | |
| 109 | } | ||
| 110 | |||
| 111 | } // namespace eu::imgui_extra | ||
| 112 |