From 8ad5f7c39db55cab3f78fdefab323435261941fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nusser?= Date: Sat, 16 Jun 2018 12:52:48 +0200 Subject: Add hovering to visualization. --- plugingui/colour.h | 9 ----- plugingui/drumkittab.cc | 91 ++++++++++++++++++++++++++++++++----------------- plugingui/drumkittab.h | 16 +++++++-- plugingui/painter.h | 14 +++++++- src/grid.h | 23 ++++++++++--- 5 files changed, 104 insertions(+), 49 deletions(-) diff --git a/plugingui/colour.h b/plugingui/colour.h index 0bfe80d..3a135fc 100644 --- a/plugingui/colour.h +++ b/plugingui/colour.h @@ -54,13 +54,4 @@ private: std::array data; }; -struct ColourHasher -{ - // TODO: replace by something reasonable - std::size_t operator()(const Colour& colour) const - { - return 7*colour.red() + 11*colour.green() + 13*colour.blue()/* + 17*colour.alpha()*/; - } -}; - } // GUI:: diff --git a/plugingui/drumkittab.cc b/plugingui/drumkittab.cc index 388f43e..acc2c89 100644 --- a/plugingui/drumkittab.cc +++ b/plugingui/drumkittab.cc @@ -34,6 +34,9 @@ #include "painter.h" #include "settings.h" +// TODO: +// make consistent with clicks etc + namespace GUI { @@ -53,7 +56,9 @@ DrumkitTab::DrumkitTab(Widget* parent, velocity_label.resizeToText(); instrument_name_label.move(velocity_label.width()+30, height()-instrument_name_label.height()-5); - updateInstrumentLabel(); + updateInstrumentLabel(-1); + + pos_to_colour_index.setDefaultValue(-1); } void DrumkitTab::resize(std::size_t width, std::size_t height) @@ -126,7 +131,20 @@ void DrumkitTab::scrollEvent(ScrollEvent* scrollEvent) updateVelocityLabel(); velocity_label.resizeToText(); - triggerAudition(scrollEvent->x, scrollEvent->y, false); + triggerAudition(scrollEvent->x, scrollEvent->y); +} + +void DrumkitTab::mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) +{ + // change to image coordinates + auto const x = mouseMoveEvent->x - drumkit_image_x; + auto const y = mouseMoveEvent->y - drumkit_image_y; + + auto index = pos_to_colour_index(x, y); + + highlightInstrument(index); + updateInstrumentLabel(index); + redraw(); } void DrumkitTab::mouseLeaveEvent() @@ -135,39 +153,45 @@ void DrumkitTab::mouseLeaveEvent() Painter painter(*this); painter.clear(); painter.drawImage(drumkit_image_x, drumkit_image_y, *drumkit_image); - redraw(); shows_overlay = false; + redraw(); } } -void DrumkitTab::triggerAudition(int x, int y, bool show_hit) +void DrumkitTab::triggerAudition(int x, int y) { - // FIXME: introduce matrix/grid class and then make notation more beautiful. - auto pos = (x - drumkit_image_x) + (y - drumkit_image_y)*map_image->width(); - auto index = pos_to_colour_index[pos]; - if (index == -1) - { - return; - } - auto const& colour = colours[index]; - auto const& instrument = to_instrument_name[index]; + // change to image coordinates + x -= drumkit_image_x; + y -= drumkit_image_y; + + auto index = pos_to_colour_index(x, y); + if (index == -1) { return; } ++settings.audition_counter; - settings.audition_instrument = instrument; + settings.audition_instrument = to_instrument_name[index]; settings.audition_velocity = current_velocity; - if (show_hit) - { - Painter painter(*this); - painter.drawRestrictedImage(drumkit_image_x, drumkit_image_y, colour, *map_image); - shows_instrument_overlay = true; - } + redraw(); +} - current_instrument = instrument; - updateInstrumentLabel(); +void DrumkitTab::highlightInstrument(int index) +{ + if (index == current_index) { return; } + current_index = index; - redraw(); + Painter painter(*this); + painter.clear(); + painter.drawImage(drumkit_image_x, drumkit_image_y, *drumkit_image); + shows_overlay = false; + + if (index != -1) { + auto const& colour = colours[index]; + auto const& positions = colour_index_to_positions[index]; + painter.draw(positions.begin(), positions.end(), drumkit_image_x, drumkit_image_y, colour); + + shows_instrument_overlay = true; + } } void DrumkitTab::updateVelocityLabel() @@ -177,8 +201,9 @@ void DrumkitTab::updateVelocityLabel() velocity_label.setText("Velocity: " + stream.str()); } -void DrumkitTab::updateInstrumentLabel() +void DrumkitTab::updateInstrumentLabel(int index) { + current_instrument = (index == -1 ? "" : to_instrument_name[index]); instrument_name_label.setText("Instrument: " + current_instrument); instrument_name_label.resizeToText(); } @@ -193,7 +218,8 @@ void DrumkitTab::init(std::string const& image_file, std::string const& map_file auto const width = map_image->width(); colours.clear(); - pos_to_colour_index.assign(height*width, -1); + pos_to_colour_index.assign(width, height, -1); + colour_index_to_positions.clear(); to_instrument_name.clear(); for (std::size_t y = 0; y < map_image->height(); ++y) @@ -202,19 +228,20 @@ void DrumkitTab::init(std::string const& image_file, std::string const& map_file { auto colour = map_image->getPixel(x, y); - if (colour.alpha() == 1.) - { - continue; - } + if (colour.alpha() == 0.) { continue; } auto it = std::find(colours.begin(), colours.end(), colour); + int index = std::distance(colours.begin(), it); + if (it == colours.end()) { - colours.push_back(colour); + // XXX: avoids low alpha values due to feathering of edges + colours.emplace_back(colour.red(), colour.green(), colour.blue(), 0.7); + colour_index_to_positions.emplace_back(); } - int index = std::distance(colours.begin(), it); - pos_to_colour_index[x + y*width] = index; + pos_to_colour_index(x, y) = index; + colour_index_to_positions[index].emplace_back(x, y); } } diff --git a/plugingui/drumkittab.h b/plugingui/drumkittab.h index 1c99e6d..e42eb93 100644 --- a/plugingui/drumkittab.h +++ b/plugingui/drumkittab.h @@ -30,6 +30,8 @@ #include #include +#include + #include "image.h" #include "label.h" #include "widget.h" @@ -55,6 +57,7 @@ public: void resize(std::size_t width, std::size_t height) override; void buttonEvent(ButtonEvent* buttonEvent) override; void scrollEvent(ScrollEvent* scrollEvent) override; + void mouseMoveEvent(MouseMoveEvent* mouseMoveEvent) override; void mouseLeaveEvent() override; void init(std::string const& image_file, std::string const& map_file); @@ -62,9 +65,15 @@ public: private: float current_velocity{.5}; std::string current_instrument{""}; + int current_index{-1}; + + using IndexGrid = Grid; + using Position = IndexGrid::Pos; + using Positions = std::vector; std::vector colours; - std::vector pos_to_colour_index; + IndexGrid pos_to_colour_index; + std::vector colour_index_to_positions; std::vector to_instrument_name; struct ColourInstrumentPair @@ -95,9 +104,10 @@ private: // SettingsNotifier& settings_notifier; // Config& config; - void triggerAudition(int x, int y, bool show_hit = true); + void triggerAudition(int x, int y); + void highlightInstrument(int index); void updateVelocityLabel(); - void updateInstrumentLabel(); + void updateInstrumentLabel(int index); }; } // GUI:: diff --git a/plugingui/painter.h b/plugingui/painter.h index fc4ce2b..2630b0c 100644 --- a/plugingui/painter.h +++ b/plugingui/painter.h @@ -29,11 +29,11 @@ #include #include "colour.h" +#include "pixelbuffer.h" namespace GUI { -class PixelBufferAlpha; class Font; class Drawable; class Image; @@ -60,6 +60,9 @@ public: void drawImageStretched(int x, int y, const Drawable& image, int width, int height); + template + void draw(Iterator begin, Iterator end, int x_offset, int y_offset, Colour const& colour); + typedef struct { Image* topLeft; Image* top; @@ -90,4 +93,13 @@ private: Colour colour; }; +template +void Painter::draw(Iterator begin, Iterator end, int x_offset, int y_offset, Colour const& colour) +{ + for (auto it = begin; it != end; ++it) + { + pixbuf.addPixel(x_offset + it->x, y_offset + it->y, colour); + } +} + } // GUI:: diff --git a/src/grid.h b/src/grid.h index 6d3933b..85c7465 100644 --- a/src/grid.h +++ b/src/grid.h @@ -53,15 +53,18 @@ public: T operator()(Index x, Index y) const; T& operator()(Pos pos); T& operator()(Index x, Index y); + std::vector const& getAllEntries() const; void resize(Index width, Index height); void assign(Index width, Index height, T value); + void setDefaultValue(T value); private: Index _width; Index _height; std::vector _entries; + T default_value; }; template @@ -99,25 +102,31 @@ auto Grid::height() const -> Index template T Grid::operator()(Pos pos) const { - return _entries.at(pos.x + _width*pos.y); + return is_valid(pos) ? _entries[pos.x + _width*pos.y] : default_value; } template T Grid::operator()(Index x, Index y) const { - return _entries.at(x + _width*y); + return is_valid(x, y) ? _entries[x + _width*y] : default_value; } template T& Grid::operator()(Pos pos) { - return _entries.at(pos.x + _width*pos.y); + return is_valid(pos) ? _entries[pos.x + _width*pos.y] : default_value; } template T& Grid::operator()(Index x, Index y) { - return _entries.at(x + _width*y); + return is_valid(x, y) ? _entries[x + _width*y] : default_value; +} + +template +std::vector const& Grid::getAllEntries() const +{ + return _entries; } template @@ -135,3 +144,9 @@ void Grid::assign(Index width, Index height, T value) _height = height; _entries.assign(_width*_height, value); } + +template +void Grid::setDefaultValue(T value) +{ + default_value = value; +} -- cgit v1.2.3