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;
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_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 */
_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);
if (_bounding_item) {
@ -7271,11 +7276,12 @@ LollipopDrag::setup_pointer_offset ()
/********/
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())
, parent (p)
, base_rect (r)
, dragging_line (nullptr)
, horizontally_bounded (hbounded)
, direction (0)
, edge_x (0)
, did_snap (false)
@ -7310,7 +7316,6 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::motion (GdkEvent* ev, bool firs
...start_grab() already occurred so this is non-trivial */
/* Add a point correspding to the start of the drag */
maybe_add_point (ev, raw_grab_time(), true);
} else {
maybe_add_point (ev, _drags->current_pointer_time(), false);
@ -7335,17 +7340,24 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
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());
/* 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;
if (drawn_points.empty()) {
line_start_x = pointer_x;
line_start_x = editing_context.timeline_to_canvas (timeline_x);
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);
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) {
pop_point = true;
@ -7377,7 +7389,7 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
} 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) {
pop_point = true;
@ -7415,15 +7427,16 @@ FreehandLineDrag<OrderedPointList,OrderedPoint>::maybe_add_point (GdkEvent* ev,
}
if (child_call) {
x = editing_context.timeline_to_canvas (timeline_x);
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 {
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) {
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)
: FreehandLineDrag<Evoral::ControlList::OrderedPoints,Evoral::ControlList::OrderedPoint> (ec, p, r, 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, hbounded, time_domain)
{
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)
: FreehandLineDrag<Evoral::ControlList::OrderedPoints,Evoral::ControlList::OrderedPoint> (ec, nullptr, r, 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, hbounded, time_domain)
, vd (static_cast<VelocityDisplay*> (r.get_data ("ghostregionview")))
, drag_did_change (false)
{

View File

@ -1597,7 +1597,7 @@ template<typename OrderedPointList, typename OrderedPoint>
class FreehandLineDrag : public Drag
{
public:
FreehandLineDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
FreehandLineDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, bool, Temporal::TimeDomain);
~FreehandLineDrag ();
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::Rectangle& base_rect; /* we do not own this */
ArdourCanvas::PolyLine* dragging_line;
bool horizontally_bounded;
int direction;
int edge_x;
bool did_snap;
@ -1626,7 +1627,7 @@ class FreehandLineDrag : public Drag
class AutomationDrawDrag : public FreehandLineDrag<Evoral::ControlList::OrderedPoints, Evoral::ControlList::OrderedPoint>
{
public:
AutomationDrawDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
AutomationDrawDrag (EditingContext&, ArdourCanvas::Item*, ArdourCanvas::Rectangle&, bool, Temporal::TimeDomain);
~AutomationDrawDrag ();
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>
{
public:
VelocityLineDrag (EditingContext&, ArdourCanvas::Rectangle&, Temporal::TimeDomain);
VelocityLineDrag (EditingContext&, ArdourCanvas::Rectangle&, bool, Temporal::TimeDomain);
~VelocityLineDrag ();
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"));
VelocityGhostRegion* grv = dynamic_cast<VelocityGhostRegion*> (vd);
std::cerr << "VBI with item " << item << " vd " << vd << " data for grv pointed at " << grv << std::endl;
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;
@ -1207,7 +1206,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
{
AutomationTimeAxisView* atv = static_cast<AutomationTimeAxisView*> (item->get_data ("trackview"));
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;
@ -1234,7 +1233,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
RegionView* rv;
if ((rv = dynamic_cast<RegionView*> (clicked_regionview))) {
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;

View File

@ -41,6 +41,7 @@
#include "note_base.h"
#include "prh.h"
#include "ui_config.h"
#include "velocity_ghost_region.h"
#include "verbose_cursor.h"
#include "pbd/i18n.h"
@ -400,6 +401,19 @@ MidiCueEditor::canvas_note_event (GdkEvent* event, ArdourCanvas::Item* item)
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&
MidiCueEditor::viewport()
{
@ -505,6 +519,17 @@ MidiCueEditor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event
}
}
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:
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;
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_music_divisions (Editing::GridType gt, uint32_t event_state) const { return 1; }

View File

@ -49,7 +49,6 @@ MidiCueVelocityDisplay::set_colors ()
void
MidiCueVelocityDisplay::remove_note (NoteBase* nb)
{
std::cerr << "mcVD:remove\n";
GhostEvent::EventList::iterator f = events.find (nb->note());
if (f == events.end()) {
return;
@ -64,12 +63,12 @@ MidiCueVelocityDisplay::remove_note (NoteBase* nb)
bool
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
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);
}