mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:27:45 +00:00
Piano: Add UI support for different lengths of notes
This commit is contained in:
parent
27b990ec19
commit
b82f2df4c8
3 changed files with 52 additions and 23 deletions
|
@ -159,29 +159,58 @@ void RollWidget::mousedown_event(GUI::MouseEvent& event)
|
||||||
if (!widget_inner_rect().contains(event.x(), event.y()))
|
if (!widget_inner_rect().contains(event.x(), event.y()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int y = (event.y() + vertical_scrollbar().value()) - frame_thickness();
|
m_note_drag_start = event.position();
|
||||||
|
|
||||||
|
int y = (m_note_drag_start.value().y() + vertical_scrollbar().value()) - frame_thickness();
|
||||||
y /= note_height;
|
y /= note_height;
|
||||||
|
m_drag_note = (note_count - 1) - y;
|
||||||
|
|
||||||
// There's a case where we can't just use x / m_note_width. For example, if
|
mousemove_event(event);
|
||||||
// your m_note_width is 3.1 you will have a rect starting at 3. When that
|
}
|
||||||
// leftmost pixel of the rect is clicked you will do 3 / 3.1 which is 0
|
|
||||||
// and not 1. We can avoid that case by shifting x by 1 if m_note_width is
|
|
||||||
// fractional, being careful not to shift out of bounds.
|
|
||||||
int x = (event.x() + horizontal_scrollbar().value()) - frame_thickness();
|
|
||||||
bool note_width_is_fractional = m_note_width - static_cast<int>(m_note_width) != 0;
|
|
||||||
bool x_is_not_last = x != widget_inner_rect().width() - 1;
|
|
||||||
if (note_width_is_fractional && x_is_not_last)
|
|
||||||
++x;
|
|
||||||
x /= m_note_width;
|
|
||||||
|
|
||||||
int note = (note_count - 1) - y;
|
void RollWidget::mousemove_event(GUI::MouseEvent& event)
|
||||||
u32 on_sample = roll_length * (static_cast<double>(x) / m_num_notes);
|
{
|
||||||
u32 off_sample = (roll_length * (static_cast<double>(x + 1) / m_num_notes)) - 1;
|
if (!m_note_drag_start.has_value())
|
||||||
m_track_manager.current_track().set_roll_note(note, on_sample, off_sample);
|
return;
|
||||||
|
|
||||||
|
if (m_note_drag_location.has_value()) {
|
||||||
|
// Clear previous note
|
||||||
|
m_track_manager.current_track().set_roll_note(m_drag_note, m_note_drag_location.value().on_sample, m_note_drag_location.value().off_sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto get_note_x = [&](int x0) {
|
||||||
|
// There's a case where we can't just use x / m_note_width. For example, if
|
||||||
|
// your m_note_width is 3.1 you will have a rect starting at 3. When that
|
||||||
|
// leftmost pixel of the rect is clicked you will do 3 / 3.1 which is 0
|
||||||
|
// and not 1. We can avoid that case by shifting x by 1 if m_note_width is
|
||||||
|
// fractional, being careful not to shift out of bounds.
|
||||||
|
int x = (x0 + horizontal_scrollbar().value()) - frame_thickness();
|
||||||
|
bool note_width_is_fractional = m_note_width - static_cast<int>(m_note_width) != 0;
|
||||||
|
bool x_is_not_last = x != widget_inner_rect().width() - 1;
|
||||||
|
if (note_width_is_fractional && x_is_not_last)
|
||||||
|
++x;
|
||||||
|
x /= m_note_width;
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
|
int x0 = get_note_x(m_note_drag_start.value().x());
|
||||||
|
int x1 = get_note_x(event.x());
|
||||||
|
|
||||||
|
u32 on_sample = roll_length * (static_cast<double>(min(x0, x1)) / m_num_notes);
|
||||||
|
u32 off_sample = (roll_length * (static_cast<double>(max(x0, x1) + 1) / m_num_notes)) - 1;
|
||||||
|
m_track_manager.current_track().set_roll_note(m_drag_note, on_sample, off_sample);
|
||||||
|
m_note_drag_location = RollNote({ on_sample, off_sample });
|
||||||
|
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RollWidget::mouseup_event(GUI::MouseEvent& event)
|
||||||
|
{
|
||||||
|
(void)event;
|
||||||
|
m_note_drag_start = {};
|
||||||
|
m_note_drag_location = {};
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Implement zoom and horizontal scroll events in LibGUI, not here.
|
// FIXME: Implement zoom and horizontal scroll events in LibGUI, not here.
|
||||||
void RollWidget::mousewheel_event(GUI::MouseEvent& event)
|
void RollWidget::mousewheel_event(GUI::MouseEvent& event)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,6 +46,8 @@ private:
|
||||||
|
|
||||||
virtual void paint_event(GUI::PaintEvent&) override;
|
virtual void paint_event(GUI::PaintEvent&) override;
|
||||||
virtual void mousedown_event(GUI::MouseEvent& event) override;
|
virtual void mousedown_event(GUI::MouseEvent& event) override;
|
||||||
|
virtual void mousemove_event(GUI::MouseEvent& event) override;
|
||||||
|
virtual void mouseup_event(GUI::MouseEvent& event) override;
|
||||||
virtual void mousewheel_event(GUI::MouseEvent&) override;
|
virtual void mousewheel_event(GUI::MouseEvent&) override;
|
||||||
|
|
||||||
TrackManager& m_track_manager;
|
TrackManager& m_track_manager;
|
||||||
|
@ -55,4 +57,8 @@ private:
|
||||||
int m_num_notes { 0 };
|
int m_num_notes { 0 };
|
||||||
double m_note_width { 0.0 };
|
double m_note_width { 0.0 };
|
||||||
int m_zoom_level { 1 };
|
int m_zoom_level { 1 };
|
||||||
|
|
||||||
|
Optional<Gfx::IntPoint> m_note_drag_start;
|
||||||
|
Optional<RollNote> m_note_drag_location;
|
||||||
|
int m_drag_note;
|
||||||
};
|
};
|
||||||
|
|
|
@ -287,7 +287,7 @@ void Track::set_roll_note(int note, u32 on_sample, u32 off_sample)
|
||||||
sync_roll(note);
|
sync_roll(note);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (it->on_sample == new_roll_note.on_sample && it->off_sample == new_roll_note.off_sample) {
|
if (it->on_sample <= new_roll_note.on_sample && it->off_sample >= new_roll_note.on_sample) {
|
||||||
if (m_time >= it->on_sample && m_time <= it->off_sample)
|
if (m_time >= it->on_sample && m_time <= it->off_sample)
|
||||||
set_note(note, Off);
|
set_note(note, Off);
|
||||||
m_roll_notes[note].remove(it);
|
m_roll_notes[note].remove(it);
|
||||||
|
@ -301,12 +301,6 @@ void Track::set_roll_note(int note, u32 on_sample, u32 off_sample)
|
||||||
it = m_roll_notes[note].begin();
|
it = m_roll_notes[note].begin();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (it->on_sample < new_roll_note.on_sample && it->off_sample >= new_roll_note.on_sample) {
|
|
||||||
if (m_time >= new_roll_note.off_sample && m_time <= it->off_sample)
|
|
||||||
set_note(note, Off);
|
|
||||||
it->off_sample = new_roll_note.on_sample - 1;
|
|
||||||
ASSERT(it->length() >= 2);
|
|
||||||
}
|
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue