From 27ec46c64e0ece3208c4d733638a7e9ce62a7636 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Sat, 2 Sep 2023 12:48:00 +0200 Subject: [PATCH] New Slider to control Mouse Pointer strength --- src/MousePointer.cpp | 49 +++++++++++++++++++++++------------- src/MousePointer.h | 7 +++--- src/UserInterfaceManager.cpp | 38 ++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/MousePointer.cpp b/src/MousePointer.cpp index a6ad35f..26e913f 100644 --- a/src/MousePointer.cpp +++ b/src/MousePointer.cpp @@ -21,7 +21,6 @@ #include "imgui.h" -#include "defines.h" #include "Metronome.h" #include "View.h" #include "Mixer.h" @@ -30,13 +29,13 @@ #define IMVEC_IO(v) ImVec2( v.x / ImGui::GetIO().DisplayFramebufferScale.x, v.y / ImGui::GetIO().DisplayFramebufferScale.y) -std::vector< std::tuple > Pointer::Modes = { - { ICON_POINTER_DEFAULT, std::string("Default") }, - { ICON_POINTER_GRID, std::string("Grid") }, - { ICON_POINTER_LINEAR, std::string("Linear") }, - { ICON_POINTER_SPRING, std::string("Spring") }, - { ICON_POINTER_WIGGLY, std::string("Wiggly") }, - { ICON_POINTER_METRONOME, std::string("Metronome") } +std::vector< std::tuple > Pointer::Modes = { + { ICON_POINTER_DEFAULT, "Default", "Default" }, + { ICON_POINTER_GRID, "Grid", "Step" }, + { ICON_POINTER_LINEAR, "Line", "Speed" }, + { ICON_POINTER_SPRING, "Spring", "Mass" }, + { ICON_POINTER_WIGGLY, "Wiggly", "Radius" }, + { ICON_POINTER_METRONOME, "Metronome", "Jump" } }; void PointerGrid::initiate(const glm::vec2&) @@ -106,7 +105,7 @@ void PointerLinear::draw() } #define POINTER_WIGGLY_MIN_RADIUS 3.f -#define POINTER_WIGGLY_MAX_RADIUS 300.f +#define POINTER_WIGGLY_MAX_RADIUS 400.f #define POINTER_WIGGLY_SMOOTHING 10 void PointerWiggly::update(const glm::vec2 &pos, float) @@ -131,14 +130,28 @@ void PointerWiggly::draw() ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), radius * 0.5f, color, 0, 2.f + 4.f * strength_); } -#define POINTER_METRONOME_RADIUS 30.f +#define POINTER_METRONOME_RADIUS 36.f + +void PointerMetronome::initiate(const glm::vec2 &pos) +{ + Pointer::initiate(pos); + beat_pos_ = pos; +} void PointerMetronome::update(const glm::vec2 &pos, float dt) { current_ = pos; - if ( Metronome::manager().timeToBeat() < std::chrono::milliseconds( (uint)floor(dt * 1000.f) )) { - target_ = pos; - } + // aim for the position at the cursor at each beat + if ( Metronome::manager().timeToBeat() < std::chrono::milliseconds( (uint)ceil(dt * 1000.f) )) + beat_pos_ = pos; + + // calculate min jump ratio for current fps and current tempo + // and considering it takes 10 frames to reach the beat_pos, + float ratio = 10.f / ((60.f / Metronome::manager().tempo()) / glm::max(dt,0.001f)); + + // animate the target cursor position to reach beat_pos_ + glm::vec2 delta = target_ - beat_pos_; + target_ -= delta * (ratio + strength_ * (1.f-ratio) ); } void PointerMetronome::draw() @@ -148,13 +161,13 @@ void PointerMetronome::draw() ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), POINTER_METRONOME_RADIUS, color, 0, 3.f); ImGui::GetBackgroundDrawList()->AddCircleFilled(IMVEC_IO(target_), 6.0, color); - double t = Metronome::manager().phase(); + double t = Metronome::manager().beats(); t -= floor(t); ImGui::GetBackgroundDrawList()->AddCircleFilled(IMVEC_IO(current_), t * POINTER_METRONOME_RADIUS, color, 0); } #define POINTER_SPRING_MIN_MASS 6.f -#define POINTER_SPRING_MAX_MASS 40.f +#define POINTER_SPRING_MAX_MASS 60.f void PointerSpring::initiate(const glm::vec2 &pos) { @@ -167,13 +180,13 @@ void PointerSpring::update(const glm::vec2 &pos, float dt) current_ = pos; // percentage of loss of energy at every update - const float viscousness = 0.75; + const float viscousness = 0.7; // force applied on the mass, as percent of the Maximum mass const float stiffness = 0.8; // damping : opposite direction of force, non proportional to mass const float damping = 60.0; // mass as a percentage of min to max - const float mass = POINTER_SPRING_MAX_MASS - (POINTER_SPRING_MAX_MASS - POINTER_SPRING_MIN_MASS) * strength_; + const float mass = POINTER_SPRING_MIN_MASS + (POINTER_SPRING_MAX_MASS - POINTER_SPRING_MIN_MASS) * strength_; // compute delta betwen initial and current position glm::vec2 delta = pos - target_; @@ -215,7 +228,7 @@ void PointerSpring::draw() ImGui::GetBackgroundDrawList()->AddBezierCurve(IMVEC_IO(current_), IMVEC_IO(_third), IMVEC_IO(_twothird), IMVEC_IO(_end), color, 5.f); // represent the weight with a filled circle - const float mass = POINTER_SPRING_MAX_MASS - (POINTER_SPRING_MAX_MASS - POINTER_SPRING_MIN_MASS) * strength_; + const float mass = POINTER_SPRING_MIN_MASS + (POINTER_SPRING_MAX_MASS - POINTER_SPRING_MIN_MASS) * strength_; ImGui::GetBackgroundDrawList()->AddCircleFilled(IMVEC_IO(_end), mass, color, 0); } diff --git a/src/MousePointer.h b/src/MousePointer.h index 66cf8f9..7bb00d1 100644 --- a/src/MousePointer.h +++ b/src/MousePointer.h @@ -36,7 +36,7 @@ public: POINTER_METRONOME, POINTER_INVALID } Mode; - static std::vector< std::tuple > Modes; + static std::vector< std::tuple > Modes; Pointer() : strength_(0.5) {} virtual ~Pointer() {} @@ -49,7 +49,7 @@ public: inline void setStrength(float percent) { strength_ = glm::clamp(percent, 0.f, 1.f); } inline void incrementStrength(float inc) { setStrength( strength_ + inc); } - inline float strength() const { return strength_; } + inline float strength() const { return strength_; } protected: glm::vec2 current_; @@ -67,7 +67,6 @@ public: void initiate(const glm::vec2&) override; void update(const glm::vec2 &pos, float) override; void terminate() override; -// void draw() override; }; /// @@ -114,8 +113,10 @@ public: /// class PointerMetronome : public Pointer { + glm::vec2 beat_pos_; public: PointerMetronome() {} + void initiate(const glm::vec2 &pos) override; void update(const glm::vec2 &pos, float dt) override; void draw() override; }; diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index e428a09..a856812 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -4767,7 +4767,7 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); ImVec2 t = top + size - ImVec2(g.FontSize, g.FontSize) - ImVec2(g.Style.FramePadding.y, g.Style.FramePadding.y); ImGui::SetCursorPos( t ); - std::tuple mode = Pointer::Modes.at( (size_t) Settings::application.mouse_pointer); + std::tuple mode = Pointer::Modes.at( (size_t) Settings::application.mouse_pointer); ImGuiToolkit::Icon(std::get<0>(mode), std::get<1>(mode)); ImGui::PopFont(); } @@ -4788,7 +4788,7 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) // loop over all mouse pointer modes for ( size_t m = Pointer::POINTER_GRID; m < Pointer::POINTER_INVALID; ++m) { bool on = m == (size_t) Settings::application.mouse_pointer; - std::tuple mode = Pointer::Modes.at(m); + const std::tuple mode = Pointer::Modes.at(m); // show icon of mouse mode and set mouse pointer if selected if (ImGuiToolkit::IconToggle( std::get<0>(mode), std::get<1>(mode), &on, std::get<2>(mode).c_str()) ) Settings::application.mouse_pointer = (int) m; @@ -4797,17 +4797,45 @@ void Navigator::RenderMousePointerSelector(const ImVec2 &size) } ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT); + + // button to lock the ALT activation ImGui::SetCursorPosY(margin.y); - ImGui::TextDisabled(" |"); - ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SameLine(0, IMGUI_SAME_LINE * 3); ImGuiToolkit::ButtonToggle(Settings::application.mouse_pointer_lock ? ICON_FA_LOCK ALT_LOCK : ICON_FA_UNLOCK ALT_LOCK, &Settings::application.mouse_pointer_lock, "Activate the selected snap mouse pointer by pressing the [" ALT_MOD "] key.\n\n" ICON_FA_LOCK ALT_LOCK " keeps the snap mouse pointer active."); + + // slider to adjust strength of the mouse pointer + ImGui::SetNextItemWidth( IMGUI_RIGHT_ALIGN ); + float *val = &Settings::application.mouse_pointer_strength[ Settings::application.mouse_pointer ]; + // General case + if (Settings::application.mouse_pointer != Pointer::POINTER_GRID) { + int percent = *val * 100.f; + if (ImGui::SliderInt( "##sliderstrenght", &percent, 0, 100, percent < 1 ? "Min" : "%d%%") ) + *val = 0.01f * (float) percent; + if (ImGui::IsItemHovered() && g.IO.MouseWheel != 0.f ){ + *val += 0.1f * g.IO.MouseWheel; + *val = CLAMP( *val, 0.f, 1.f); + } + } + // special case of GRID + else { + static const char* grid_names[Grid::UNIT_ONE+1] = { "Precise (0.05)", "Small (0.1)", "Default (0.2)", "Large (0.5)", "Huge (1.0)"}; + int grid_current = (Grid::Units) round( *val * 4.f) ; + const char* grid_current_name = (grid_current >= 0 && grid_current <= Grid::UNIT_ONE) ? + grid_names[grid_current] : "Unknown"; + if (ImGui::SliderInt("##slidergrid", &grid_current, 0, Grid::UNIT_ONE, grid_current_name) ) { + *val = (float) grid_current * 0.25f; + } + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton( std::get<3>(Pointer::Modes.at(Settings::application.mouse_pointer)).c_str() )) + *val = 0.5f; ImGui::PopFont(); // timer to close menu like a tooltip - if (ImGui::IsWindowHovered()) + if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) counter_menu_timeout=0; else if (++counter_menu_timeout > 10) ImGui::CloseCurrentPopup();