the basics of lollipop dragging
This commit is contained in:
parent
2977205f3a
commit
cf7ba80fc1
|
@ -674,7 +674,7 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C
|
|||
bool
|
||||
Editor::canvas_velocity_event (GdkEvent *event, ArdourCanvas::Item* item)
|
||||
{
|
||||
std::cerr << "Velocity event: " << Gtkmm2ext::event_type_string (event->type) << std::endl;
|
||||
// std::cerr << "Velocity event: " << Gtkmm2ext::event_type_string (event->type) << std::endl;
|
||||
return typed_event (item, event, VelocityItem);
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "ardour/session_playlists.h"
|
||||
|
||||
#include "canvas/canvas.h"
|
||||
#include "canvas/lollipop.h"
|
||||
#include "canvas/scroll_group.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
|
@ -77,6 +78,7 @@
|
|||
#include "region_gain_line.h"
|
||||
#include "selection.h"
|
||||
#include "ui_config.h"
|
||||
#include "velocity_ghost_region.h"
|
||||
#include "verbose_cursor.h"
|
||||
#include "video_timeline.h"
|
||||
|
||||
|
@ -7178,9 +7180,11 @@ RegionMarkerDrag::setup_pointer_sample_offset ()
|
|||
_pointer_offset = model_abs_pos.distance (raw_grab_time ());
|
||||
}
|
||||
|
||||
LollipopDrag::LollipopDrag (Editor* ed, MidiRegionView* r, ArdourCanvas::Item* i)
|
||||
: Drag (ed, i, r->region ()->position ().time_domain ())
|
||||
LollipopDrag::LollipopDrag (Editor* ed, ArdourCanvas::Item* l)
|
||||
: Drag (ed, l, Temporal::BeatTime)
|
||||
, _primary (dynamic_cast<ArdourCanvas::Lollipop*> (l))
|
||||
{
|
||||
_region = reinterpret_cast<VelocityGhostRegion*> (_item->get_data ("ghostregionview"));
|
||||
}
|
||||
|
||||
LollipopDrag::~LollipopDrag ()
|
||||
|
@ -7191,25 +7195,48 @@ void
|
|||
LollipopDrag::start_grab (GdkEvent *ev, Gdk::Cursor* c)
|
||||
{
|
||||
Drag::start_grab (ev, c);
|
||||
|
||||
NoteBase* note = static_cast<NoteBase*> (_primary->get_data (X_("note")));
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&_region->parent_rv);
|
||||
assert (mrv);
|
||||
|
||||
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
|
||||
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
|
||||
|
||||
mrv->note_selected (note, add, extend);
|
||||
}
|
||||
|
||||
void
|
||||
LollipopDrag::motion (GdkEvent *ev, bool first_move)
|
||||
{
|
||||
_region->drag_lolli (_primary, &ev->motion);
|
||||
}
|
||||
|
||||
void
|
||||
LollipopDrag::finished (GdkEvent *ev, bool did_move)
|
||||
{
|
||||
if (!did_move) {
|
||||
return;
|
||||
}
|
||||
|
||||
int velocity = _region->y_position_to_velocity (_primary->y0());
|
||||
NoteBase* note = static_cast<NoteBase*> (_primary->get_data (X_("note")));
|
||||
MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (&_region->parent_rv);
|
||||
assert (mrv);
|
||||
|
||||
mrv->set_velocity (note, velocity);
|
||||
}
|
||||
|
||||
void
|
||||
LollipopDrag::aborted (bool)
|
||||
{
|
||||
/* XXX get ghost velocity view etc. to redraw with original values */
|
||||
}
|
||||
|
||||
void
|
||||
LollipopDrag::setup_pointer_sample_offset ()
|
||||
{
|
||||
NoteBase* note = static_cast<NoteBase*> (_primary->get_data (X_("note")));
|
||||
_pointer_offset = _region->parent_rv.region()->source_beats_to_absolute_time (note->note()->time ()).distance (raw_grab_time ());
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ namespace ArdourCanvas {
|
|||
class Item;
|
||||
class Line;
|
||||
class Rectangle;
|
||||
class Lollipop;
|
||||
}
|
||||
|
||||
namespace PBD {
|
||||
|
@ -81,6 +82,7 @@ class ControlPoint;
|
|||
class AudioRegionView;
|
||||
class AutomationLine;
|
||||
class AutomationTimeAxisView;
|
||||
class VelocityGhostRegion;
|
||||
|
||||
/** Class to manage current drags */
|
||||
class DragManager
|
||||
|
@ -1550,7 +1552,7 @@ class RegionMarkerDrag : public Drag
|
|||
class LollipopDrag : public Drag
|
||||
{
|
||||
public:
|
||||
LollipopDrag (Editor*, MidiRegionView*, ArdourCanvas::Item*);
|
||||
LollipopDrag (Editor*, ArdourCanvas::Item*);
|
||||
~LollipopDrag ();
|
||||
|
||||
void start_grab (GdkEvent *, Gdk::Cursor* c = 0);
|
||||
|
@ -1573,8 +1575,8 @@ class LollipopDrag : public Drag
|
|||
void setup_pointer_sample_offset ();
|
||||
|
||||
private:
|
||||
MidiRegionView* _region;
|
||||
NoteBase* _primary;
|
||||
VelocityGhostRegion* _region;
|
||||
ArdourCanvas::Lollipop* _primary;
|
||||
};
|
||||
|
||||
#endif /* __gtk2_ardour_editor_drag_h_ */
|
||||
|
|
|
@ -897,6 +897,11 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
|
|||
return true;
|
||||
break;
|
||||
|
||||
case VelocityItem:
|
||||
_drags->set (new LollipopDrag (this, item), event);
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -221,8 +221,7 @@ MidiGhostRegion::GhostEvent::GhostEvent (NoteBase* e, ArdourCanvas::Container* g
|
|||
: event (e)
|
||||
{
|
||||
if (dynamic_cast<Note*>(e)) {
|
||||
item = new ArdourCanvas::Rectangle(
|
||||
g, ArdourCanvas::Rect(e->x0(), e->y0(), e->x1(), e->y1()));
|
||||
item = new ArdourCanvas::Rectangle (g, ArdourCanvas::Rect(e->x0(), e->y0(), e->x1(), e->y1()));
|
||||
is_hit = false;
|
||||
} else {
|
||||
Hit* hit = dynamic_cast<Hit*>(e);
|
||||
|
|
|
@ -28,7 +28,7 @@ using namespace ARDOUR;
|
|||
using ArdourCanvas::Coord;
|
||||
using ArdourCanvas::Duple;
|
||||
|
||||
Lollipop::Lollipop (
|
||||
NoteVelocityLollipop (
|
||||
MidiRegionView& region, ArdourCanvas::Item* parent, const std::shared_ptr<NoteType> note, bool with_events)
|
||||
: NoteBase (region, with_events, note)
|
||||
, _lollipop (new ArdourCanvas::Lollipop (parent))
|
||||
|
@ -37,73 +37,74 @@ Lollipop::Lollipop (
|
|||
set_item (_lollipop);
|
||||
}
|
||||
|
||||
Lollipop::~Lollipop ()
|
||||
NoteVelocity~Lollipop ()
|
||||
{
|
||||
delete _lollipop;
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::move_event (double dx, double dy)
|
||||
NoteVelocitymove_event (double dx, double dy)
|
||||
{
|
||||
std::cerr << "move lolli to: " << (Duple (_lollipop->x(), _lollipop->y0()).translate (Duple (dx, dy)), _lollipop->length(), _lollipop->radius()) << std::endl;
|
||||
_lollipop->set (Duple (_lollipop->x(), _lollipop->y0()).translate (Duple (dx, dy)), _lollipop->length(), _lollipop->radius());
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_outline_color (uint32_t color)
|
||||
NoteVelocityset_outline_color (uint32_t color)
|
||||
{
|
||||
_lollipop->set_outline_color (color);
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_fill_color (uint32_t color)
|
||||
NoteVelocityset_fill_color (uint32_t color)
|
||||
{
|
||||
_lollipop->set_fill_color (color);
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::show ()
|
||||
NoteVelocityshow ()
|
||||
{
|
||||
_lollipop->show ();
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::hide ()
|
||||
NoteVelocityhide ()
|
||||
{
|
||||
_lollipop->hide ();
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set (ArdourCanvas::Duple const & d, ArdourCanvas::Coord len, ArdourCanvas::Coord radius)
|
||||
NoteVelocityset (ArdourCanvas::Duple const & d, ArdourCanvas::Coord len, ArdourCanvas::Coord radius)
|
||||
{
|
||||
_lollipop->set (d, len, radius);
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_x (Coord x)
|
||||
NoteVelocityset_x (Coord x)
|
||||
{
|
||||
_lollipop->set_x (x);
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_len (Coord l)
|
||||
NoteVelocityset_len (Coord l)
|
||||
{
|
||||
_lollipop->set_length (l);
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_outline_what (ArdourCanvas::Rectangle::What what)
|
||||
NoteVelocityset_outline_what (ArdourCanvas::Rectangle::What what)
|
||||
{
|
||||
// _lollipop->set_outline_what (what);
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_outline_all ()
|
||||
NoteVelocityset_outline_all ()
|
||||
{
|
||||
// _lollipop->set_outline_all ();
|
||||
}
|
||||
|
||||
void
|
||||
Lollipop::set_ignore_events (bool ignore)
|
||||
NoteVelocityset_ignore_events (bool ignore)
|
||||
{
|
||||
_lollipop->set_ignore_events (ignore);
|
||||
}
|
||||
|
|
|
@ -31,17 +31,17 @@ namespace ArdourCanvas {
|
|||
class Lollipop;
|
||||
}
|
||||
|
||||
class Lollipop : public NoteBase
|
||||
class NoteVelocity : public NoteBase
|
||||
{
|
||||
public:
|
||||
typedef Evoral::Note<Temporal::Beats> NoteType;
|
||||
|
||||
Lollipop (MidiRegionView& region,
|
||||
NoteVelocity (MidiRegionView& region,
|
||||
ArdourCanvas::Item* parent,
|
||||
const std::shared_ptr<NoteType> note = std::shared_ptr<NoteType>(),
|
||||
bool with_events = true);
|
||||
|
||||
~Lollipop ();
|
||||
~NoteVelocity ();
|
||||
|
||||
void set (ArdourCanvas::Duple const &, ArdourCanvas::Coord, ArdourCanvas::Coord);
|
||||
void set_x (ArdourCanvas::Coord);
|
||||
|
@ -58,6 +58,8 @@ public:
|
|||
|
||||
void set_ignore_events (bool);
|
||||
|
||||
ArdourCanvas::Lollipop& lolli() { return *_lollipop; }
|
||||
|
||||
void move_event (double dx, double dy);
|
||||
|
||||
private:
|
||||
|
|
|
@ -3369,6 +3369,31 @@ MidiRegionView::change_note_length (NoteBase* event, Temporal::Beats t)
|
|||
note_diff_add_change (event, MidiModel::NoteDiffCommand::Length, t);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::set_velocity (NoteBase* note, int velocity)
|
||||
{
|
||||
if (_selection.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int delta = velocity - note->note()->velocity();
|
||||
|
||||
std::cerr << "vel delta = " << delta << std::endl;
|
||||
|
||||
start_note_diff_command (_("set velocities"));
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end();) {
|
||||
Selection::iterator next = i;
|
||||
++next;
|
||||
|
||||
change_note_velocity (*i, delta, true);
|
||||
|
||||
i = next;
|
||||
}
|
||||
|
||||
apply_note_diff();
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegionView::change_velocities (bool up, bool fine, bool allow_smush, bool all_together)
|
||||
{
|
||||
|
|
|
@ -54,10 +54,10 @@ namespace MIDI {
|
|||
};
|
||||
|
||||
class SysEx;
|
||||
class NoteBase;
|
||||
class Note;
|
||||
class Hit;
|
||||
class MidiTimeAxisView;
|
||||
class NoteBase;
|
||||
class GhostRegion;
|
||||
class AutomationTimeAxisView;
|
||||
class AutomationRegionView;
|
||||
|
@ -67,6 +67,7 @@ class EditNoteDialog;
|
|||
class PatchChange;
|
||||
class ItemCounts;
|
||||
class CursorContext;
|
||||
class VelocityGhostRegion;
|
||||
|
||||
class MidiRegionView : public RegionView
|
||||
{
|
||||
|
@ -286,6 +287,7 @@ public:
|
|||
void goto_next_note (bool add_to_selection);
|
||||
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 transpose (bool up, bool fine, bool allow_smush);
|
||||
void nudge_notes (bool forward, bool fine);
|
||||
void channel_edit ();
|
||||
|
@ -502,6 +504,7 @@ public:
|
|||
std::shared_ptr<PatchChange> find_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr p);
|
||||
std::shared_ptr<SysEx> find_canvas_sys_ex (ARDOUR::MidiModel::SysExPtr s);
|
||||
|
||||
friend class VelocityGhostRegion;
|
||||
void update_note (NoteBase*, bool update_ghost_regions = true);
|
||||
void update_sustained (Note *, bool update_ghost_regions = true);
|
||||
void update_hit (Hit *, bool update_ghost_regions = true);
|
||||
|
|
|
@ -79,6 +79,8 @@ VelocityGhostRegion::add_note (NoteBase* nb)
|
|||
events.insert (std::make_pair (nb->note(), event));
|
||||
l->Event.connect (sigc::bind (sigc::mem_fun (*this, &VelocityGhostRegion::lollevent), event));
|
||||
l->raise_to_top ();
|
||||
l->set_data (X_("ghostregionview"), this);
|
||||
l->set_data (X_("note"), nb);
|
||||
|
||||
event->item->set_fill_color (UIConfiguration::instance().color_mod(nb->base_color(), "ghost track midi fill"));
|
||||
event->item->set_outline_color (_outline);
|
||||
|
@ -125,3 +127,45 @@ VelocityGhostRegion::set_colors ()
|
|||
{
|
||||
base_rect->set_fill_color (Gtkmm2ext::Color (0xff000085));
|
||||
}
|
||||
|
||||
void
|
||||
VelocityGhostRegion::drag_lolli (ArdourCanvas::Lollipop* l, GdkEventMotion* ev)
|
||||
{
|
||||
ArdourCanvas::Rect r (base_rect->item_to_window (base_rect->get()));
|
||||
|
||||
/* translate event y-coord so that zero matches the top of base_rect */
|
||||
|
||||
ev->y -= r.y0;
|
||||
|
||||
/* clamp y to be within the range defined by the base_rect height minus
|
||||
* the lollipop radius at top and bottom
|
||||
*/
|
||||
|
||||
const double effective_y = std::max (lollipop_radius, std::min (r.height() - (2.0 * lollipop_radius), ev->y));
|
||||
|
||||
std::cerr << "new y " << effective_y << std::endl;
|
||||
|
||||
l->set (ArdourCanvas::Duple (l->x(), effective_y), r.height() - effective_y - lollipop_radius, lollipop_radius);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
VelocityGhostRegion::y_position_to_velocity (double y) const
|
||||
{
|
||||
const ArdourCanvas::Rect r (base_rect->get());
|
||||
int velocity;
|
||||
|
||||
std::cerr << "y = " << y << " h = " << r.height() << std::endl;
|
||||
|
||||
if (y >= r.height() - (2.0 * lollipop_radius)) {
|
||||
velocity = 0;
|
||||
} else if (y <= lollipop_radius) {
|
||||
velocity = 127;
|
||||
} else {
|
||||
velocity = floor (127. * ((r.height() - y) / r.height()));
|
||||
}
|
||||
|
||||
std::cerr << " y = " << y << " vel = " << velocity << std::endl;
|
||||
|
||||
return velocity;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
#include "ghostregion.h"
|
||||
|
||||
namespace ArdourCanvas {
|
||||
class Lollipop;
|
||||
}
|
||||
|
||||
class VelocityGhostRegion : public MidiGhostRegion
|
||||
{
|
||||
public:
|
||||
|
@ -36,6 +40,9 @@ public:
|
|||
void remove_note (NoteBase*);
|
||||
|
||||
void set_colors ();
|
||||
void drag_lolli (ArdourCanvas::Lollipop* l, GdkEventMotion* ev);
|
||||
|
||||
int y_position_to_velocity (double y) const;
|
||||
|
||||
private:
|
||||
bool lollevent (GdkEvent*, MidiGhostRegion::GhostEvent*);
|
||||
|
|
|
@ -152,7 +152,6 @@ gtk2_ardour_sources = [
|
|||
'level_meter.cc',
|
||||
'library_download_dialog.cc',
|
||||
'location_ui.cc',
|
||||
'lollipop.cc',
|
||||
'loudness_dialog.cc',
|
||||
'loudness_settings.cc',
|
||||
'lua_script_manager.cc',
|
||||
|
|
Loading…
Reference in New Issue