prototyping mouse-drag-paint velocity

This commit is contained in:
Paul Davis 2023-06-22 17:31:53 -06:00
parent 31de7e93bf
commit 6d4bbae48c
4 changed files with 110 additions and 0 deletions

View File

@ -3384,6 +3384,33 @@ MidiRegionView::change_note_length (NoteBase* event, Temporal::Beats t)
{
note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t);
}
void
MidiRegionView::set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity)
{
/* Does not use selection, used when drawing/dragging in velocity lane */
bool changed = false;
start_note_diff_command (_("set velocities"));
for (auto & note : notes) {
int delta = velocity - note->note()->velocity();
if (!delta) {
continue;
}
changed = true;
change_note_velocity (note, delta, true);
}
if (changed) {
apply_note_diff ();
} else {
abort_note_diff ();
}
}
void
MidiRegionView::set_velocity (NoteBase* note, int velocity)
@ -3394,6 +3421,10 @@ MidiRegionView::set_velocity (NoteBase* note, int velocity)
int delta = velocity - note->note()->velocity();
if (!delta) {
return;
}
start_note_diff_command (_("set velocities"));
for (Selection::iterator i = _selection.begin(); i != _selection.end();) {

View File

@ -288,6 +288,7 @@ public:
void change_note_lengths (bool, bool, Temporal::Beats beats, bool start, bool end);
void change_velocities (bool up, bool fine, bool allow_smush, bool all_together);
void set_velocity (NoteBase* primary, int velocity);
void set_velocity_for_notes (std::vector<NoteBase*> notes, int velocity);
void transpose (bool up, bool fine, bool allow_smush);
void nudge_notes (bool forward, bool fine);
void channel_edit ();

View File

@ -28,6 +28,7 @@
#include "ardour/session.h"
#include "gtkmm2ext/keyboard.h"
#include "gtkmm2ext/utils.h"
#include "canvas/lollipop.h"
@ -51,13 +52,53 @@ static double const lollipop_radius = 8.0;
VelocityGhostRegion::VelocityGhostRegion (MidiRegionView& mrv, TimeAxisView& tv, TimeAxisView& source_tv, double initial_unit_pos)
: MidiGhostRegion (mrv, tv, source_tv, initial_unit_pos)
, dragging (false)
{
base_rect->Event.connect (sigc::mem_fun (*this, &VelocityGhostRegion::base_event));
}
VelocityGhostRegion::~VelocityGhostRegion ()
{
}
bool
VelocityGhostRegion::base_event (GdkEvent* ev)
{
std::vector<NoteBase*> affected_lollis;
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&parent_rv);
ArdourCanvas::Rect r = base_rect->item_to_canvas (base_rect->get());
switch (ev->type) {
case GDK_MOTION_NOTIFY:
if (dragging) {
lollis_close_to_x (ev->motion.x, 20., affected_lollis);
if (!affected_lollis.empty()) {
int velocity = y_position_to_velocity (r.height() - (r.y1 - ev->motion.y));
mrv->set_velocity_for_notes (affected_lollis, velocity);
}
}
break;
case GDK_BUTTON_PRESS:
if (ev->button.button == 1) {
desensitize_lollis ();
dragging = true;
}
break;
case GDK_BUTTON_RELEASE:
if (ev->button.button == 1) {
sensitize_lollis ();
dragging = false;
}
break;
default:
// std::cerr << "vgr event type " << Gtkmm2ext::event_type_string (ev->type) << std::endl;
break;
}
return false;
}
void
VelocityGhostRegion::update_contents_height ()
{
@ -81,6 +122,7 @@ VelocityGhostRegion::add_note (NoteBase* nb)
GhostEvent* event = new GhostEvent (nb, _note_group, l);
events.insert (std::make_pair (nb->note(), event));
l->Event.connect (sigc::bind (sigc::mem_fun (*this, &VelocityGhostRegion::lollevent), event));
l->set_ignore_events (true);
l->raise_to_top ();
l->set_data (X_("ghostregionview"), this);
l->set_data (X_("note"), nb);
@ -240,3 +282,33 @@ VelocityGhostRegion::note_selected (NoteBase* ev)
lolli->set_outline_color (ev->selected() ? UIConfiguration::instance().color ("midi note selected outline") : 0x000000ff);
}
void
VelocityGhostRegion::lollis_close_to_x (int x, double distance, std::vector<NoteBase*>& within)
{
for (auto & gev : events) {
ArdourCanvas::Lollipop* l = dynamic_cast<ArdourCanvas::Lollipop*> (gev.second->item);
if (l) {
ArdourCanvas::Duple pos = l->item_to_canvas (ArdourCanvas::Duple (l->x(), l->y0()));
if (std::abs (pos.x - x) < distance) {
within.push_back (gev.second->event);
}
}
}
}
void
VelocityGhostRegion::desensitize_lollis ()
{
for (auto & gev : events) {
gev.second->item->set_ignore_events (true);
}
}
void
VelocityGhostRegion::sensitize_lollis ()
{
for (auto & gev : events) {
gev.second->item->set_ignore_events (false);
}
}

View File

@ -46,8 +46,14 @@ public:
int y_position_to_velocity (double y) const;
private:
bool dragging;
bool base_event (GdkEvent*);
bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*);
void set_size_and_position (MidiGhostRegion::GhostEvent&);
void lollis_close_to_x (int x, double distance, std::vector<NoteBase*>& events);
void desensitize_lollis ();
void sensitize_lollis ();
};
#endif /* __gtk_ardour_velocity_region_view_h__ */