diff --git a/rsc/images/icons.dds b/rsc/images/icons.dds
index 02e1613..5322571 100644
Binary files a/rsc/images/icons.dds and b/rsc/images/icons.dds differ
diff --git a/src/MousePointer.cpp b/src/MousePointer.cpp
index 75cc0ca..0f82159 100644
--- a/src/MousePointer.cpp
+++ b/src/MousePointer.cpp
@@ -17,6 +17,7 @@
* along with this program. If not, see .
**/
+#include
#include // for diskRand
#include "imgui.h"
@@ -37,6 +38,7 @@ std::vector< std::tuple > Pointer::Modes = {
{ ICON_POINTER_LINEAR, "Line", "Speed" },
{ ICON_POINTER_SPRING, "Spring", "Mass" },
{ ICON_POINTER_WIGGLY, "Wiggly", "Radius" },
+ { ICON_POINTER_BROWNIAN, "Brownian", "Radius" },
{ ICON_POINTER_METRONOME, "Metronome", "Jump" }
};
@@ -138,6 +140,49 @@ void PointerWiggly::draw()
ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), max * 0.5f, color, 0, 2.f + 4.f * strength_);
}
+void PointerBrownian::update(const glm::vec2 &pos, float)
+{
+ current_ = pos;
+ radius_ = (POINTER_WIGGLY_MAX_RADIUS - POINTER_WIGGLY_MIN_RADIUS) * strength_;
+ radius_ += POINTER_WIGGLY_MIN_RADIUS;
+
+ // Brownian motion: add small random displacement in 2D
+ // Generate random step using gaussian distribution for each axis
+ glm::vec2 random_step = glm::gaussRand(glm::vec2(0.0f), glm::vec2(1.f) );
+
+ // Scale by radius and apply damping to keep motion bounded
+ float factor = 0.3f;
+ if (TabletInput::instance().hasPressure() && TabletInput::instance().isPressed()) {
+ factor *= TabletInput::instance().getPressure();
+ }
+ float damping = 0.92f;
+ brownian_offset_ = brownian_offset_ * damping + random_step * radius_ * factor;
+
+ // Clamp offset to stay within maximum radius
+ float offset_length = glm::length(brownian_offset_);
+ if (offset_length > radius_) {
+ brownian_offset_ = brownian_offset_ * (radius_ / offset_length);
+ }
+
+ glm::vec2 p = pos + brownian_offset_;
+
+ // smooth a little and apply
+ const float emaexp = 2.0 / float( POINTER_WIGGLY_SMOOTHING + 1);
+ target_ = emaexp * p + (1.f - emaexp) * target_;
+}
+
+void PointerBrownian::draw()
+{
+ const ImU32 color = ImGui::GetColorU32(ImGuiCol_HeaderActive);
+ ImGui::GetBackgroundDrawList()->AddLine(IMVEC_IO(current_), IMVEC_IO(target_), color, 5.f);
+
+ const float max = POINTER_WIGGLY_MIN_RADIUS + (POINTER_WIGGLY_MAX_RADIUS - POINTER_WIGGLY_MIN_RADIUS) * strength_;
+ if (TabletInput::instance().hasPressure() && TabletInput::instance().isPressed())
+ ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), radius_ * 0.8f, color, 0);
+ ImGui::GetBackgroundDrawList()->AddCircle(IMVEC_IO(current_), max * 0.8f, color, 0, 2.f + 4.f * strength_);
+}
+
+
#define POINTER_METRONOME_RADIUS 36.f
void PointerMetronome::initiate(const glm::vec2 &pos)
@@ -256,6 +301,7 @@ MousePointer::MousePointer() : mode_(Pointer::POINTER_DEFAULT)
pointer_[Pointer::POINTER_LINEAR] = new PointerLinear;
pointer_[Pointer::POINTER_SPRING] = new PointerSpring;
pointer_[Pointer::POINTER_WIGGLY] = new PointerWiggly;
+ pointer_[Pointer::POINTER_BROWNIAN] = new PointerBrownian;
pointer_[Pointer::POINTER_METRONOME] = new PointerMetronome;
}
@@ -266,5 +312,6 @@ MousePointer::~MousePointer()
delete pointer_[Pointer::POINTER_LINEAR];
delete pointer_[Pointer::POINTER_SPRING];
delete pointer_[Pointer::POINTER_WIGGLY];
+ delete pointer_[Pointer::POINTER_BROWNIAN];
delete pointer_[Pointer::POINTER_METRONOME];
}
diff --git a/src/MousePointer.h b/src/MousePointer.h
index 73fc9d1..e2d524d 100644
--- a/src/MousePointer.h
+++ b/src/MousePointer.h
@@ -12,6 +12,7 @@
#define ICON_POINTER_LINEAR 14, 9
#define ICON_POINTER_GRID 15, 9
#define ICON_POINTER_WIGGLY 16, 9
+#define ICON_POINTER_BROWNIAN 11, 9
#define ICON_POINTER_METRONOME 6, 13
///
@@ -33,6 +34,7 @@ public:
POINTER_LINEAR,
POINTER_SPRING,
POINTER_WIGGLY,
+ POINTER_BROWNIAN,
POINTER_METRONOME,
POINTER_INVALID
} Mode;
@@ -104,7 +106,21 @@ class PointerWiggly : public Pointer
{
float radius_;
public:
- PointerWiggly() {}
+ PointerWiggly() : radius_(0.0f) {}
+ void update(const glm::vec2 &pos, float) override;
+ void draw() override;
+};
+
+///
+/// \brief The PointerBrownian moves with a Brownian movement
+/// Strength modulates the radius of the movement
+///
+class PointerBrownian : public Pointer
+{
+ float radius_;
+ glm::vec2 brownian_offset_;
+public:
+ PointerBrownian() : brownian_offset_(0.0f, 0.0f) {}
void update(const glm::vec2 &pos, float) override;
void draw() override;
};