From 37324e38cf2015fe8e46ac72b14a3a7f2efbb287 Mon Sep 17 00:00:00 2001 From: lgdevel Date: Sat, 17 Apr 2021 16:33:41 +0200 Subject: [PATCH 1/2] Added a brand new knob widget --- CMakeLists.txt | 3 ++ include/nanogui/knob.h | 58 ++++++++++++++++++++ src/example_knob.cpp | 88 ++++++++++++++++++++++++++++++ src/knob.cpp | 118 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 include/nanogui/knob.h create mode 100644 src/example_knob.cpp create mode 100644 src/knob.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f5936d22..c7a7ce88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -356,6 +356,7 @@ add_library(nanogui ${NANOGUI_LIBRARY_TYPE} include/nanogui/combobox.h src/combobox.cpp include/nanogui/progressbar.h src/progressbar.cpp include/nanogui/slider.h src/slider.cpp + include/nanogui/knob.h src/knob.cpp include/nanogui/messagedialog.h src/messagedialog.cpp include/nanogui/textbox.h src/textbox.cpp include/nanogui/textarea.h src/textarea.cpp @@ -468,12 +469,14 @@ if (NANOGUI_BUILD_EXAMPLES) add_executable(example3 src/example3.cpp) add_executable(example4 src/example4.cpp) add_executable(example_icons src/example_icons.cpp) + add_executable(example_knob src/example_knob.cpp) target_link_libraries(example1 nanogui) target_link_libraries(example2 nanogui) target_link_libraries(example3 nanogui ${NANOGUI_LIBS}) # For OpenGL target_link_libraries(example4 nanogui) target_link_libraries(example_icons nanogui) + target_link_libraries(example_knob nanogui) # Copy icons for example application file(COPY resources/icons DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/include/nanogui/knob.h b/include/nanogui/knob.h new file mode 100644 index 00000000..f4cfea02 --- /dev/null +++ b/include/nanogui/knob.h @@ -0,0 +1,58 @@ +#ifndef KNOB_H +#define KNOB_H + +#include + +/* Ottimizzazione funzioni trigonometriche + https://github.com/kthohr/gcem + */ + +NAMESPACE_BEGIN(nanogui) + +class NANOGUI_EXPORT Knob : public Widget { +public: + Knob(Widget *parent, int rad=100); + + float value() const { return m_value; } + void set_value(float value) { m_value = value; } + + int notches() const { return m_notches; } + void set_notches(int n) { m_notches = n; } + + const Color &highlight_color() const { return m_highlight_color; } + void set_highlight_color(const Color &highlight_color) { m_highlight_color = highlight_color; } + + std::pair range() const { return m_range; } + void set_range(std::pair range) { m_range = range; } + + std::pair highlighted_range() const { return m_highlighted_range; } + void set_highlighted_range(std::pair highlighted_range) { m_highlighted_range = highlighted_range; } + + std::function callback() const { return m_callback; } + void set_callback(const std::function &callback) { m_callback = callback; } + + std::function final_callback() const { return m_final_callback; } + void set_final_callback(const std::function &callback) { m_final_callback = callback; } + + virtual Vector2i preferred_size(NVGcontext *ctx) const override; + virtual bool mouse_drag_event(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; + virtual bool mouse_button_event(const Vector2i &p, int button, bool down, int modifiers) override; + virtual void draw(NVGcontext* ctx) override; + +protected: + float m_value; + int m_notches; + std::function m_callback; + std::function m_final_callback; + std::pair m_range; + std::pair m_highlighted_range; + Color m_highlight_color; + +private: + void set_value_by_mouse_position(const Vector2i &p); + static const float m_pi; +}; + +NAMESPACE_END(nanogui) + +#endif // KNOB_H diff --git a/src/example_knob.cpp b/src/example_knob.cpp new file mode 100644 index 00000000..f9f9c209 --- /dev/null +++ b/src/example_knob.cpp @@ -0,0 +1,88 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace nga { +using namespace nanogui; +using std::cout, std::endl; + +class ExampleApplication : public Screen { +public: + ExampleApplication() : Screen(Vector2i(1024, 768), "Knob example") { + inc_ref(); + Window *window = new Window(this, "Knob example"); + window->set_position(Vector2i(15, 15)); + window->set_fixed_size(Vector2i(400, 650)); + + Theme* th = new Theme(this->nvg_context()); + th->m_window_fill_focused = m_theme->m_border_light; + th->m_window_fill_unfocused = m_theme->m_border_light; + window->set_theme(th); + + window->set_layout(new BoxLayout(Orientation::Vertical,Alignment::Middle,40,20 )); + + new Label(window, "Vertical layout", "sans-bold"); + + Slider *slider = new Slider(window); //provare argomento this + slider->set_value(0.5f); + slider->set_fixed_width(150); + slider->set_highlighted_range({0.3f,0.5f}); + + Knob* k = new Knob(window); + k->set_value(0.25f); + k->set_final_callback([](float f){ std::cout << "Knob k final value: " << f << endl; }); + k->set_callback([](float f){ std::cout << "Knob k value: " << f << endl; }); + k->set_range({35.0f,97.0f}); + k->set_highlighted_range({50.0f,60.0f}); + + Knob* k2 = new Knob(window, 30); + k2->set_value(0.45f); + k2->set_notches(0); + + Knob* k3 = new Knob(window, 300); + k3->set_value(0.45f); + k3->set_notches(24); + k3->set_final_callback([](float f){ std::cout << "Knob k3 final value: " << f << endl; }); + k3->set_callback([](float f){ std::cout << "Knob k3 value: " << f << endl; }); + k3->set_highlighted_range({0.90f,1.0f}); + + perform_layout(); + } +}; + +} + +int main() +{ + using std::cout, std::endl; + cout << "Nano GUI Knob example" << endl; + cout << "---------------------" << endl; + + try { + nanogui::init(); + + /* scoped variables */ { + nanogui::ref app = new nga::ExampleApplication(); + app->dec_ref(); + app->draw_all(); + app->set_visible(true); + nanogui::mainloop(1 / 60.f * 1000); + } + + nanogui::shutdown(); + } catch (const std::exception &e) { + std::string error_msg = std::string("Caught a fatal error: ") + std::string(e.what()); + std::cerr << error_msg << std::endl; + return -1; + } catch (...) { + std::cerr << "Caught an unknown error!" << std::endl; + } + + return 0; +} diff --git a/src/knob.cpp b/src/knob.cpp new file mode 100644 index 00000000..e1f78462 --- /dev/null +++ b/src/knob.cpp @@ -0,0 +1,118 @@ +#include +#include +#include + +NAMESPACE_BEGIN(nanogui) + +Knob::Knob(Widget *parent, int rad) + : Widget(parent), m_value(0.0f), m_notches{12}, m_range(0.f, 1.f), + m_highlighted_range(0.f, 0.f) +{ + m_highlight_color = Color(255, 80, 80, 70); + Widget::set_size({rad,rad}); +} + +const float Knob::m_pi = std::acos(-1.0f); + +Vector2i Knob::preferred_size(NVGcontext *) const { + return m_size; +} + +bool Knob::mouse_drag_event(const Vector2i &p, const Vector2i & /* rel */, + int /* button */, int /* modifiers */) { + if (!m_enabled) + return false; + + set_value_by_mouse_position(p); + if (m_callback) + m_callback(m_value); + + return true; +} + +bool Knob::mouse_button_event(const Vector2i &p, int /* button */, bool down, int /* modifiers */) { + if (!m_enabled) + return false; + + set_value_by_mouse_position(p); + if (m_final_callback && !down) + m_final_callback(m_value); + + return true; +} + +void Knob::draw(NVGcontext* ctx) { + Vector2f center = Vector2f(m_pos) + Vector2f(m_size) * 0.5f; + float radius = static_cast( width()/2 - 1 ); + + NVGpaint knob_gradient = nvgRadialGradient(ctx, + center.x(), center.y(), radius * 0.65f, radius, + m_theme->m_border_light, m_theme->m_border_medium); + + nvgBeginPath(ctx); + nvgCircle(ctx, center.x(), center.y(), radius); + nvgFillPaint(ctx, knob_gradient); + nvgStroke(ctx); + nvgFill(ctx); + + nvgBeginPath(ctx); + nvgMoveTo(ctx,center.x() + 0.7f * radius, center.y()); + nvgLineTo(ctx,center.x() + radius, center.y()); + nvgFillColor(ctx, Color(200, 200, 200, 200) ); + nvgFill(ctx); + + float angle_step = (2.0f * m_pi) / static_cast(m_notches); + for(int i=1; i(i) * angle_step; + float begin_radius = 0.9f * radius; + auto begin_notch = center + Vector2f{begin_radius * std::cos(angle), begin_radius * std::sin(angle)}; + auto end_notch = center + Vector2f{radius * std::cos(angle), radius * std::sin(angle)}; + nvgMoveTo(ctx,begin_notch.x(), begin_notch.y()); + nvgLineTo(ctx,end_notch.x(), end_notch.y()); + nvgFillColor(ctx, Color(200, 200, 200, 200) ); + nvgFill(ctx); + } + + auto clove_radius = 0.7f * radius; + nvgBeginPath(ctx); + nvgArc(ctx, center.x(), center.y(), clove_radius, 0.3f * m_pi, 0, NVGwinding::NVG_CCW); + nvgArc(ctx, center.x() + 0.34f * radius, center.y(), 0.5f * clove_radius, 0, 0.5f * m_pi, NVGwinding::NVG_CW); + nvgFillColor(ctx, Color(200, 200, 200, 200) ); + nvgStroke(ctx); + nvgFill(ctx); + + if( m_highlighted_range.second > m_highlighted_range.first && + m_highlighted_range.first >= m_range.first && + m_highlighted_range.second <= m_range.second ){ + float angle_begin = 2.0f * m_pi * (m_highlighted_range.first - m_range.first) / (m_range.second - m_range.first); + float angle_end = 2.0f * m_pi * (m_highlighted_range.second - m_range.first) / (m_range.second - m_range.first); + + nvgBeginPath(ctx); + nvgArc(ctx, center.x(), center.y(), radius, angle_end, angle_begin, NVGwinding::NVG_CCW); + nvgArc(ctx, center.x(), center.y(), 0.85f * radius, angle_begin, angle_end, NVGwinding::NVG_CW); + nvgFillColor(ctx, m_highlight_color); + nvgFill(ctx); + } + + float hand_angle = 2.0f * m_pi * (value() - range().first) / (range().second - range().first); + float hand_dist = 0.8f * radius; + Vector2f hand_center = center + Vector2f{hand_dist * std::cos(hand_angle), hand_dist * std::sin(hand_angle)}; + float hand_radius = radius / 8; + + nvgBeginPath(ctx); + nvgCircle(ctx, hand_center.x(), hand_center.y(), hand_radius); + nvgFillColor(ctx, Color(200, 200, 200, 255)); + nvgStroke(ctx); + nvgFill(ctx); +} + +void Knob::set_value_by_mouse_position(const Vector2i &p) +{ + Vector2f center = Vector2f(m_pos) + Vector2f(m_size) * 0.5f; + float angle = m_pi/2 - std::atan( ( static_cast(p.x() ) - center.x()) / ( static_cast(p.y() ) - center.y()) ); + float value01 = 0.5f * angle / m_pi + ( static_cast(p.y()) - center.y() < 0 ? 0.5f : 0.0f); + m_value = m_range.first + value01 * (m_range.second - m_range.first); +} + +NAMESPACE_END(nanogui) From 077baa9985e57a55ddc389497cc6d3927f7cf994 Mon Sep 17 00:00:00 2001 From: lgdevel Date: Sat, 17 Apr 2021 17:05:32 +0200 Subject: [PATCH 2/2] fixed knob.h --- include/nanogui/knob.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/nanogui/knob.h b/include/nanogui/knob.h index f4cfea02..beb9ec95 100644 --- a/include/nanogui/knob.h +++ b/include/nanogui/knob.h @@ -3,10 +3,6 @@ #include -/* Ottimizzazione funzioni trigonometriche - https://github.com/kthohr/gcem - */ - NAMESPACE_BEGIN(nanogui) class NANOGUI_EXPORT Knob : public Widget {