13
0

get velocity editing working in both the cue editor and MIDI region views

Quite a bit of hairy coordinate system stuff in here that ought to be commented more
clearly
This commit is contained in:
Paul Davis 2024-09-18 12:27:43 -06:00
parent ee305a7169
commit afa15a0061
7 changed files with 65 additions and 24 deletions

View File

@ -254,6 +254,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider
samplepos_t canvas_event_sample (GdkEvent const * event, double* pcx = nullptr, double* pcy = nullptr) const; samplepos_t canvas_event_sample (GdkEvent const * event, double* pcx = nullptr, double* pcy = nullptr) const;
virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0; virtual bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
virtual bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
virtual bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*) = 0;
Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const; Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) const;
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const; Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const;

View File

@ -352,6 +352,11 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
/* we set up x/y dragging constraints on first move */ /* we set up x/y dragging constraints on first move */
_constraint_pressed = ArdourKeyboard::indicates_constraint (event->button.state); _constraint_pressed = ArdourKeyboard::indicates_constraint (event->button.state);
/* Note that pos is already adjusted for any timeline origin offset
* within the canvas. It reflects the true sample position of the event
* x coordinate.
*/
const samplepos_t pos = editing_context.canvas_event_sample (event, &_grab_x, &_grab_y); const samplepos_t pos = editing_context.canvas_event_sample (event, &_grab_x, &_grab_y);
if (_bounding_item) { if (_bounding_item) {
@ -7271,11 +7276,12 @@ LollipopDrag::setup_pointer_offset ()
/********/ /********/
template<typename OrderedPointList, typename OrderedPoint> template<typename OrderedPointList, typename OrderedPoint>
FreehandLineDrag<OrderedPointList,OrderedPoint>::FreehandLineDrag (EditingContext& ec, ArdourCanvas::Item* p, ArdourCanvas::Rectangle& r, Temporal::TimeDomain time_domain) FreehandLineDrag<OrderedPointList,OrderedPoint>::FreehandLineDrag (EditingContext& ec, ArdourCanvas::Item* p, ArdourCanvas::Rectangle& r, bool hbounded, Temporal::TimeDomain time_domain)
: Drag (ec, &r, time_domain, ec.get_trackview_group()) : Drag (ec, &r, time_domain, ec.get_trackview_group())
, parent (p) , parent (p)
, base_rect (r) , base_rect (r)
, dragging_line (nullptr) , dragging_line (nullptr)
, horizontally_bounded (hbounded)
, direction (0) , direction (0)
, edge_x (0) , edge_x (0)
, did_snap (false) , did_snap (false)
@ -7310,7 +7316,6 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::motion (GdkEvent* ev, bool firs
...start_grab() already occurred so this is non-trivial */ ...start_grab() already occurred so this is non-trivial */
/* Add a point correspding to the start of the drag */ /* Add a point correspding to the start of the drag */
maybe_add_point (ev, raw_grab_time(), true); maybe_add_point (ev, raw_grab_time(), true);
} else { } else {
maybe_add_point (ev, _drags->current_pointer_time(), false); maybe_add_point (ev, _drags->current_pointer_time(), false);
@ -7335,17 +7340,24 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
did_snap = true; did_snap = true;
} }
double const pointer_x = editing_context.time_to_pixel (pos); /* timeline_x is a pixel offset within the timeline; it is not an absolute
* canvas coordinate.
*/
double const timeline_x = editing_context.time_to_pixel (pos);
ArdourCanvas::Rect r = base_rect.item_to_canvas (base_rect.get()); ArdourCanvas::Rect r = base_rect.item_to_canvas (base_rect.get());
/* Adjust event coordinates to be relative to the base rectangle */ /* Adjust event coordinates to be relative to the base rectangle */
double x = pointer_x - r.x0; double x = timeline_x;
if (horizontally_bounded) {
x -= r.x0;
}
double y = ev->motion.y - r.y0; double y = ev->motion.y - r.y0;
if (drawn_points.empty()) { if (drawn_points.empty()) {
line_start_x = pointer_x; line_start_x = editing_context.timeline_to_canvas (timeline_x);
line_start_y = y; line_start_y = y;
} }
@ -7366,7 +7378,7 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
const bool straight_line = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier); const bool straight_line = Keyboard::modifier_state_equals (ev->motion.state, Keyboard::PrimaryModifier);
if (direction > 0) { if (direction > 0) {
if (x < r.width() && (straight_line || (pointer_x > edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y()))) { if (x < r.width() && (straight_line || (timeline_x > edge_x) || (timeline_x == edge_x && ev->motion.y != last_pointer_y()))) {
if (straight_line && dragging_line->get().size() > 1) { if (straight_line && dragging_line->get().size() > 1) {
pop_point = true; pop_point = true;
@ -7377,7 +7389,7 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
} else if (direction < 0) { } else if (direction < 0) {
if (x >= 0. && (straight_line || (pointer_x < edge_x) || (pointer_x == edge_x && ev->motion.y != last_pointer_y()))) { if (x >= 0. && (straight_line || (timeline_x < edge_x) || (timeline_x == edge_x && ev->motion.y != last_pointer_y()))) {
if (straight_line && dragging_line->get().size() > 1) { if (straight_line && dragging_line->get().size() > 1) {
pop_point = true; pop_point = true;
@ -7415,15 +7427,16 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
} }
if (child_call) { if (child_call) {
x = editing_context.timeline_to_canvas (timeline_x);
if (straight_line && !first_move) { if (straight_line && !first_move) {
line_extended (ArdourCanvas::Duple (line_start_x, line_start_y), ArdourCanvas::Duple (pointer_x, y), base_rect, first_move ? -1 : edge_x); line_extended (ArdourCanvas::Duple (line_start_x, line_start_y), ArdourCanvas::Duple (x, y), base_rect, first_move ? -1 : edge_x);
} else { } else {
point_added (ArdourCanvas::Duple (pointer_x, y), base_rect, first_move ? -1 : edge_x); point_added (ArdourCanvas::Duple (x, y), base_rect, first_move ? -1 : edge_x);
} }
} }
if (add_point) { if (add_point) {
edge_x = pointer_x; edge_x = timeline_x;
} }
} }
@ -7473,8 +7486,8 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::mid_drag_key_event (GdkEventKey
/**********************/ /**********************/
AutomationDrawDrag::AutomationDrawDrag (EditingContext& ec, ArdourCanvas::Item* p, ArdourCanvas::Rectangle& r, Temporal::TimeDomain time_domain) AutomationDrawDrag::AutomationDrawDrag (EditingContext& ec, ArdourCanvas::Item* p, ArdourCanvas::Rectangle& r, bool hbounded, Temporal::TimeDomain time_domain)
: FreehandLineDrag<Evoral::ControlList::OrderedPoints,Evoral::ControlList::OrderedPoint> (ec, p, r, time_domain) : FreehandLineDrag<Evoral::ControlList::OrderedPoints,Evoral::ControlList::OrderedPoint> (ec, p, r, hbounded, time_domain)
{ {
DEBUG_TRACE (DEBUG::Drags, "New AutomationDrawDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New AutomationDrawDrag\n");
} }
@ -7512,8 +7525,8 @@ AutomationDrawDrag::finished (GdkEvent* event, bool motion_occured)
/*****************/ /*****************/
VelocityLineDrag::VelocityLineDrag (EditingContext& ec, ArdourCanvas::Rectangle& r, Temporal::TimeDomain time_domain) VelocityLineDrag::VelocityLineDrag (EditingContext& ec, ArdourCanvas::Rectangle& r, bool hbounded, Temporal::TimeDomain time_domain)
: FreehandLineDrag<Evoral::ControlList::OrderedPoints,Evoral::ControlList::OrderedPoint> (ec, nullptr, r, time_domain) : FreehandLineDrag<Evoral::ControlList::OrderedPoints,Evoral::ControlList::OrderedPoint> (ec, nullptr, r, hbounded, time_domain)
, vd (static_cast<VelocityDisplay*> (r.get_data ("ghostregionview"))) , vd (static_cast<VelocityDisplay*> (r.get_data ("ghostregionview")))
, drag_did_change (false) , drag_did_change (false)
{ {

View File

@ -1597,7 +1597,7 @@ template<typename OrderedPointList, typename OrderedPoint>
class FreehandLineDrag : public Drag class FreehandLineDrag : public Drag
{ {
public: public:
FreehandLineDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain); FreehandLineDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, bool, Temporal::TimeDomain);
~FreehandLineDrag (); ~FreehandLineDrag ();
void motion (GdkEvent*, bool); void motion (GdkEvent*, bool);
@ -1612,6 +1612,7 @@ class FreehandLineDrag : public Drag
ArdourCanvas::Item* parent; /* we do not own this. If null, use base_rect as the parent */ ArdourCanvas::Item* parent; /* we do not own this. If null, use base_rect as the parent */
ArdourCanvas::Rectangle& base_rect; /* we do not own this */ ArdourCanvas::Rectangle& base_rect; /* we do not own this */
ArdourCanvas::PolyLine* dragging_line; ArdourCanvas::PolyLine* dragging_line;
bool horizontally_bounded;
int direction; int direction;
int edge_x; int edge_x;
bool did_snap; bool did_snap;
@ -1626,7 +1627,7 @@ class FreehandLineDrag : public Drag
class AutomationDrawDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint> class AutomationDrawDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint>
{ {
public: public:
AutomationDrawDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain); AutomationDrawDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, bool, Temporal::TimeDomain);
~AutomationDrawDrag (); ~AutomationDrawDrag ();
void finished (GdkEvent*, bool); void finished (GdkEvent*, bool);
@ -1636,7 +1637,7 @@ class AutomationDrawDrag : public FreehandLineDrag<Evoral::ControlList::OrderedP
class VelocityLineDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint> class VelocityLineDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint>
{ {
public: public:
VelocityLineDrag (EditingContext&, ArdourCanvas::Rectangle&, Temporal::TimeDomain); VelocityLineDrag (EditingContext&, ArdourCanvas::Rectangle&, bool, Temporal::TimeDomain);
~VelocityLineDrag (); ~VelocityLineDrag ();
void start_grab (GdkEvent *, Gdk::Cursor* c = 0); void start_grab (GdkEvent *, Gdk::Cursor* c = 0);

View File

@ -765,9 +765,8 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{ {
VelocityDisplay* vd = static_cast<VelocityDisplay*> (item->get_data ("ghostregionview")); VelocityDisplay* vd = static_cast<VelocityDisplay*> (item->get_data ("ghostregionview"));
VelocityGhostRegion* grv = dynamic_cast<VelocityGhostRegion*> (vd); VelocityGhostRegion* grv = dynamic_cast<VelocityGhostRegion*> (vd);
std::cerr << "VBI with item " << item << " vd " << vd << " data for grv pointed at " << grv << std::endl;
if (grv) { if (grv) {
_drags->set (new VelocityLineDrag (*this, grv->base_item(), Temporal::BeatTime), event); _drags->set (new VelocityLineDrag (*this, grv->base_item(), true, Temporal::BeatTime), event);
} }
} }
return true; return true;
@ -1207,7 +1206,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{ {
AutomationTimeAxisView* atv = static_cast<AutomationTimeAxisView*> (item->get_data ("trackview")); AutomationTimeAxisView* atv = static_cast<AutomationTimeAxisView*> (item->get_data ("trackview"));
if (atv) { if (atv) {
_drags->set (new AutomationDrawDrag (*this, nullptr, atv->base_item(), Temporal::AudioTime), event); _drags->set (new AutomationDrawDrag (*this, nullptr, atv->base_item(), false, Temporal::AudioTime), event);
} }
} }
break; break;
@ -1234,7 +1233,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
RegionView* rv; RegionView* rv;
if ((rv = dynamic_cast<RegionView*> (clicked_regionview))) { if ((rv = dynamic_cast<RegionView*> (clicked_regionview))) {
ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (rv->get_canvas_frame()); ArdourCanvas::Rectangle* r = dynamic_cast<ArdourCanvas::Rectangle*> (rv->get_canvas_frame());
_drags->set (new AutomationDrawDrag (*this, rv->get_canvas_group(), *r, Temporal::AudioTime), event); _drags->set (new AutomationDrawDrag (*this, rv->get_canvas_group(), *r, true, Temporal::AudioTime), event);
} }
} }
break; break;

View File

@ -41,6 +41,7 @@
#include "note_base.h" #include "note_base.h"
#include "prh.h" #include "prh.h"
#include "ui_config.h" #include "ui_config.h"
#include "velocity_ghost_region.h"
#include "verbose_cursor.h" #include "verbose_cursor.h"
#include "pbd/i18n.h" #include "pbd/i18n.h"
@ -400,6 +401,19 @@ MidiCueEditor::canvas_note_event (GdkEvent* event, ArdourCanvas::Item* item)
return typed_event (item, event, NoteItem); return typed_event (item, event, NoteItem);
} }
bool
MidiCueEditor::canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item* item)
{
return typed_event (item, event, VelocityBaseItem);
}
bool
MidiCueEditor::canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item* item)
{
return typed_event (item, event, VelocityItem);
}
Gtk::Widget& Gtk::Widget&
MidiCueEditor::viewport() MidiCueEditor::viewport()
{ {
@ -505,6 +519,17 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
} }
} }
return true; return true;
case VelocityItem:
_drags->set (new LollipopDrag (*this, item), event);
return true;
break;
case VelocityBaseItem:
_drags->set (new VelocityLineDrag (*this, *static_cast<ArdourCanvas::Rectangle*>(item), false, Temporal::BeatTime), event);
return true;
break;
default: default:
break; break;
} }

View File

@ -66,6 +66,8 @@ class MidiCueEditor : public CueEditor
Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const; Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) const;
bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*); bool canvas_note_event (GdkEvent* event, ArdourCanvas::Item*);
bool canvas_velocity_base_event (GdkEvent* event, ArdourCanvas::Item*);
bool canvas_velocity_event (GdkEvent* event, ArdourCanvas::Item*);
int32_t get_grid_beat_divisions (Editing::GridType gt) const { return 1; } int32_t get_grid_beat_divisions (Editing::GridType gt) const { return 1; }
int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; } int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }

View File

@ -49,7 +49,6 @@ MidiCueVelocityDisplay::set_colors ()
void void
MidiCueVelocityDisplay::remove_note (NoteBase* nb) MidiCueVelocityDisplay::remove_note (NoteBase* nb)
{ {
std::cerr << "mcVD:remove\n";
GhostEvent::EventList::iterator f = events.find (nb->note()); GhostEvent::EventList::iterator f = events.find (nb->note());
if (f == events.end()) { if (f == events.end()) {
return; return;
@ -64,12 +63,12 @@ MidiCueVelocityDisplay::remove_note (NoteBase* nb)
bool bool
MidiCueVelocityDisplay::base_event (GdkEvent* ev) MidiCueVelocityDisplay::base_event (GdkEvent* ev)
{ {
return true; // editing_context.canvas_velocity_base_event (ev, base_rect); return editing_context.canvas_velocity_base_event (ev, &base);
} }
bool bool
MidiCueVelocityDisplay::lollevent (GdkEvent* ev, GhostEvent* gev) MidiCueVelocityDisplay::lollevent (GdkEvent* ev, GhostEvent* gev)
{ {
return true; // editing_context.canvas_velocity_event (ev, gev->item); return editing_context.canvas_velocity_event (ev, gev->item);
} }