summaryrefslogtreecommitdiff
path: root/plugingui/powerwidget.cc
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2020-05-02 13:17:18 +0200
committerBent Bisballe Nyeng <deva@aasimon.org>2020-05-02 13:17:18 +0200
commitc9134d86d393e3acba278d886482b84d3e4bf722 (patch)
treec57d51fe730dc1c5d641b0fe345275a3c82cb0da /plugingui/powerwidget.cc
parent8e5b1e0b171d0e4ff326a3ff1af162805d82a3d6 (diff)
Add new PowerWidget for setting and showing control points of the powermap.
Diffstat (limited to 'plugingui/powerwidget.cc')
-rw-r--r--plugingui/powerwidget.cc332
1 files changed, 332 insertions, 0 deletions
diff --git a/plugingui/powerwidget.cc b/plugingui/powerwidget.cc
new file mode 100644
index 0000000..02e7253
--- /dev/null
+++ b/plugingui/powerwidget.cc
@@ -0,0 +1,332 @@
+/* -*- Mode: c++ -*- */
+/***************************************************************************
+ * powerwidget.cc
+ *
+ * Fri Apr 24 17:30:45 CEST 2020
+ * Copyright 2020 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "powerwidget.h"
+
+#include "painter.h"
+
+#include <notifier.h>
+#include <settings.h>
+#include <colour.h>
+#include <powermap.h>
+
+#include <hugin.hpp>
+#include <cmath>
+
+PowerWidget::PowerWidget(GUI::Widget* parent,
+ Settings& settings,
+ SettingsNotifier& settings_notifier)
+ : GUI::Widget(parent)
+ , canvas(this, settings, settings_notifier)
+ , settings(settings)
+{
+ canvas.move(7, 7);
+
+ CONNECT(&shelf_checkbox, stateChangedNotifier, this, &PowerWidget::chk_shelf);
+
+ shelf_label.setText("Shelf");
+ shelf_label.setAlignment(GUI::TextAlignment::center);
+ shelf_label.resize(59, 16);
+ shelf_checkbox.resize(59, 40);
+
+ CONNECT(&settings_notifier, powermap_shelf, &shelf_checkbox,
+ &GUI::CheckBox::setChecked);
+}
+
+void PowerWidget::chk_shelf(bool v)
+{
+ settings.powermap_shelf.store(v);
+}
+
+void PowerWidget::repaintEvent(GUI::RepaintEvent *repaintEvent)
+{
+ GUI::Painter p(*this);
+ box.setSize(width() - 59 - 64, height());
+ p.drawImage(0, 0, box);
+}
+
+void PowerWidget::resize(std::size_t width, std::size_t height)
+{
+ Widget::resize(width, height);
+ if(width < (14 + 59 + 64) || height < 14)
+ {
+ canvas.resize(1, 1);
+ return;
+ }
+ canvas.resize(width - 14 - 59 - 64, height - 14);
+
+ shelf_label.move(width - 59 + 5 - 32 , 0);
+ shelf_checkbox.move(width - 59 + 5 - 32, 16);
+}
+
+PowerWidget::Canvas::Canvas(GUI::Widget* parent,
+ Settings& settings,
+ SettingsNotifier& settings_notifier)
+ : GUI::Widget(parent)
+ , settings_notifier(settings_notifier)
+ , settings(settings)
+{
+ CONNECT(this, settings_notifier.enable_powermap,
+ this, &PowerWidget::Canvas::parameterChangedBool);
+ CONNECT(this, settings_notifier.powermap_fixed0_x,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_fixed0_y,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_fixed1_x,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_fixed1_y,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_fixed2_x,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_fixed2_y,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_shelf,
+ this, &PowerWidget::Canvas::parameterChangedBool);
+ CONNECT(this, settings_notifier.powermap_input,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+ CONNECT(this, settings_notifier.powermap_output,
+ this, &PowerWidget::Canvas::parameterChangedFloat);
+
+ parameterChangedFloat(0);
+}
+
+void PowerWidget::Canvas::repaintEvent(GUI::RepaintEvent *repaintEvent)
+{
+ if(width() < 1 || height() < 1)
+ {
+ return;
+ }
+
+ const float x0 = brd;
+ const float y0 = brd;
+ const float width0 = (int)width() - 2 * brd;
+ const float height0 = (int)height() - 2 * brd;
+
+ GUI::Painter p(*this);
+
+ p.clear();
+
+ p.setColour(GUI::Colour(1.0f, 1.0f, 1.0f, 0.2f));
+ p.drawRectangle(x0, y0 + height0, x0 + width0, y0);
+
+ if(enabled)
+ {
+ // draw 1:1 line in grey in the background to indicate where 1:1 is
+ p.setColour(GUI::Colour(0.5));
+ p.drawLine(x0, y0 + height0, x0 + width0, y0);
+ }
+
+ if(enabled)
+ {
+ // enabled green
+ p.setColour(GUI::Colour(0.0f, 1.0f, 0.0f, 1.0f));
+ }
+ else
+ {
+ // disabled grey
+ p.setColour(GUI::Colour(0.5f));
+ }
+
+ // Draw very short line segments across the region
+ std::pair<int, int> old{};
+ for(std::size_t x = 0; x < width0; ++x)
+ {
+ int y = power_map.map((float)x / width0) * height0;
+ if(x > 0)
+ {
+ p.drawLine(x0 + old.first, y0 + old.second, x0 + x, y0 + height0 - y);
+ }
+ old = { x, height0 - y };
+ }
+
+ int x = width0;
+ int y = power_map.map((float)x / width0) * height0;
+ p.drawLine(x0 + old.first, y0 + old.second, x0 + x, y0 + height0 - y);
+ old = { x, height0 - y };
+
+ if(!enabled)
+ {
+ // draw 1:1 line in green in the foreground
+ p.setColour(GUI::Colour(0.0f, 1.0f, 0.0f, 1.0f));
+ p.drawLine(x0, y0 + height0, x0 + width0, y0);
+ }
+
+ // draw the input/output of the last hit
+ if(settings.powermap_input.load() != -1 && settings.powermap_output.load() != -1)
+ {
+ p.setColour(GUI::Colour(.8f, 0.0f, .2f, .5f));
+ p.drawLine(x0 + settings.powermap_input.load()*width0, y0 + height0,
+ x0 + settings.powermap_input.load()*width0, y0);
+ p.drawLine(x0, y0 + height0 - settings.powermap_output.load()*height0,
+ x0 + width0, y0 + height0 - settings.powermap_output.load()*height0);
+ }
+
+ // draw the fixed nodes of the spline
+ float rad = radius * width();
+ p.setColour(GUI::Colour{0.0f, 1.0f, 0.0f, 0.7f});
+ p.drawFilledCircle(x0 + std::round(settings.powermap_fixed0_x.load() * width0),
+ y0 + height0 - std::round(settings.powermap_fixed0_y.load() * height0), rad);
+ p.drawCircle(x0 + std::round(power_map.getFixed0().in * width0),
+ y0 + height0 - std::round(power_map.getFixed0().out * height0), rad + 1);
+
+ p.setColour(GUI::Colour{1.0f, 1.0f, 0.0f, 0.7f});
+ p.drawFilledCircle(x0 + std::round(settings.powermap_fixed1_x.load() * width0),
+ y0 + height0 - std::round(settings.powermap_fixed1_y.load() * height0), rad);
+ p.drawCircle(x0 + std::round(power_map.getFixed1().in * width0),
+ y0 + height0 - std::round(power_map.getFixed1().out * height0), rad + 1);
+
+ p.setColour(GUI::Colour{1.0f, 0.0f, 0.0f, 0.7f});
+ p.drawFilledCircle(x0 + std::round(settings.powermap_fixed2_x.load() * width0),
+ y0 + height0 - std::round(settings.powermap_fixed2_y.load() * height0), rad);
+ p.drawCircle(x0 + std::round(power_map.getFixed2().in * width0),
+ y0 + height0 - std::round(power_map.getFixed2().out * height0), rad + 1);
+
+ p.setColour(GUI::Colour(1.0f, 1.0f, 1.0f, 0.2f));
+ p.drawText(width() / 2 - (font.textWidth("in") / 2), height() - 8, font, "in");
+ p.drawText(8, height() / 2 - (font.textWidth("out") / 2), font, "out", false, true);
+}
+
+void PowerWidget::Canvas::buttonEvent(GUI::ButtonEvent* buttonEvent)
+{
+ const float x0 = brd;
+ const float y0 = brd;
+ const float width0 = (int)width() - 2 * brd;
+ const float height0 = (int)height() - 2 * brd;
+
+ float mx0 = (float)(buttonEvent->x - x0) / width0;
+ float my0 = (float)(((int)height() - buttonEvent->y) - y0) / height0;
+
+ float radius_x = radius * 2;
+ float radius_y = radius * width0 / height0 * 2;
+
+ switch(buttonEvent->direction)
+ {
+ case GUI::Direction::up:
+ in_point = -1;
+ break;
+ case GUI::Direction::down:
+ if(std::abs(mx0 - settings.powermap_fixed0_x.load()) < radius_x &&
+ std::abs(my0 - settings.powermap_fixed0_y.load()) < radius_y)
+ {
+ in_point = 0;
+ }
+
+ if(std::abs(mx0 - settings.powermap_fixed1_x.load()) < radius_x &&
+ std::abs(my0 - settings.powermap_fixed1_y.load()) < radius_y)
+ {
+ in_point = 1;
+ }
+
+ if(std::abs(mx0 - settings.powermap_fixed2_x.load()) < radius_x &&
+ std::abs(my0 - settings.powermap_fixed2_y.load()) < radius_y)
+ {
+ in_point = 2;
+ }
+ break;
+ }
+}
+
+namespace
+{
+float clamp(float val, float min, float max)
+{
+ return std::max(min, std::min(max, val));
+}
+}
+
+void PowerWidget::Canvas::mouseMoveEvent(GUI::MouseMoveEvent* mouseMoveEvent)
+{
+ const float x0 = brd;
+ const float y0 = brd;
+ const float width0 = (int)width() - 2 * brd;
+ const float height0 = (int)height() - 2 * brd;
+
+ float mx0 = (float)(mouseMoveEvent->x - x0) / width0;
+ float my0 = (float)(((int)height() - mouseMoveEvent->y) - y0) / height0;
+
+ switch(in_point)
+ {
+ case 0:
+ settings.powermap_fixed0_x.store(clamp(mx0, 0, 1));
+ settings.powermap_fixed0_y.store(clamp(my0, 0, 1));
+ redraw();
+ break;
+ case 1:
+ settings.powermap_fixed1_x.store(clamp(mx0, 0, 1));
+ settings.powermap_fixed1_y.store(clamp(my0, 0, 1));
+ redraw();
+ break;
+ case 2:
+ settings.powermap_fixed2_x.store(clamp(mx0, 0, 1));
+ settings.powermap_fixed2_y.store(clamp(my0, 0, 1));
+ redraw();
+ break;
+ default:
+ break;
+ }
+/*
+ switch(in_point)
+ {
+ case 0:
+ settings.fixed0_x.store(clamp((float)mouseMoveEvent->x / width()));
+ settings.fixed0_y.store(1.0f - clamp((float)mouseMoveEvent->y / height()));
+ redraw();
+ break;
+ case 1:
+ settings.fixed1_x.store(clamp((float)mouseMoveEvent->x / width()));
+ settings.fixed1_y.store(1.0f - clamp((float)mouseMoveEvent->y / height()));
+ redraw();
+ break;
+ case 2:
+ settings.fixed2_x.store(clamp((float)mouseMoveEvent->x / width()));
+ settings.fixed2_y.store(1.0f - clamp((float)mouseMoveEvent->y / height()));
+ redraw();
+ break;
+ default:
+ break;
+ }
+*/
+}
+
+void PowerWidget::Canvas::mouseLeaveEvent()
+{
+ //in_point = -1;
+}
+
+void PowerWidget::Canvas::parameterChangedFloat(float)
+{
+ power_map.setFixed0({settings.powermap_fixed0_x.load(), settings.powermap_fixed0_y.load()});
+ power_map.setFixed1({settings.powermap_fixed1_x.load(), settings.powermap_fixed1_y.load()});
+ power_map.setFixed2({settings.powermap_fixed2_x.load(), settings.powermap_fixed2_y.load()});
+ power_map.setShelf(settings.powermap_shelf.load());
+ enabled = settings.enable_powermap.load();
+ redraw();
+}
+
+void PowerWidget::Canvas::parameterChangedBool(bool)
+{
+ parameterChangedFloat(0);
+}