summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp153
-rw-r--r--muse2/muse/midiedit/scoreedit.h18
2 files changed, 131 insertions, 40 deletions
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index 94baad4c..8393ce97 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -96,7 +96,7 @@ using namespace std;
#define STAFF_DISTANCE 100
-
+#define GRANDSTAFF_DISTANCE 30
KeyList keymap;
@@ -221,6 +221,7 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent,
//each track gets its own staff
staff_t staff;
+ staff.type=NORMAL;
set<Track*> tracks;
for (ciPart it=editor->parts()->begin(); it!=editor->parts()->end(); it++)
@@ -236,7 +237,7 @@ ScoreCanvas::ScoreCanvas(MidiEditor* pr, QWidget* parent,
staffs.push_back(staff);
}
-
+ recalc_staff_pos();
scroll_speed=0;
@@ -810,7 +811,6 @@ list<note_len_t> ScoreCanvas::parse_note_len(int len_ticks, int begin_tick, vect
#define USED_CLEF VIOLIN
#define YLEN 10
-#define YDIST (2*YLEN)
#define NOTE_XLEN 10
#define NOTE_SHIFT 3
#define PIXELS_PER_WHOLE (320) //how many px are between two wholes?
@@ -908,7 +908,7 @@ void ScoreCanvas::draw_accidentials(QPainter& p, int x, int y_offset, const list
for (list<int>::const_iterator acc_it=acc_list.begin(); acc_it!=acc_list.end(); acc_it++)
{
- int y_coord=YDIST+4*YLEN - ( *acc_it -2)*YLEN/2; //Y_MARKER
+ int y_coord=2*YLEN - ( *acc_it -2)*YLEN/2;
draw_pixmap(p,x + n_acc_drawn*KEYCHANGE_ACC_DIST,y_offset + y_coord,pix);
n_acc_drawn++;
}
@@ -1534,7 +1534,7 @@ void ScoreCanvas::draw_note_lines(QPainter& p, int y)
p.setPen(Qt::black);
for (int i=0;i<5;i++)
- p.drawLine(0,y + YDIST+i*YLEN,xend,y + YDIST+i*YLEN);
+ p.drawLine(0,y + i*YLEN - 2*YLEN,xend,y + i*YLEN - 2*YLEN);
}
@@ -1547,9 +1547,9 @@ void ScoreCanvas::calc_item_pos(ScoreItemList& itemlist)
{
for (set<FloItem, floComp>::iterator it=it2->second.begin(); it!=it2->second.end();it++)
{
- //if this changes, also change the line(s) with Y_MARKER
it->x=it2->first * PIXELS_PER_WHOLE/TICKS_PER_WHOLE +pos_add;
- it->y=YDIST+4*YLEN - (it->pos.height-2)*YLEN/2;
+ //if this changes, also change the line(s) with YLEN (but not all). don't change it.
+ it->y=2*YLEN - (it->pos.height-2)*YLEN/2;
if (it->type==FloItem::NOTE)
{
@@ -1771,16 +1771,16 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, ScoreItemList::iterator
if (it->pos.height <= 0) //we need auxiliary lines on the bottom?
- { //Y_MARKER
+ {
p.setPen(Qt::black);
for (int i=0; i>=it->pos.height; i-=2)
- p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2);
+ p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2);
}
else if (it->pos.height >= 12) //we need auxiliary lines on the top?
- { //Y_MARKER
+ {
p.setPen(Qt::black);
for (int i=12; i<=it->pos.height; i+=2)
- p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + YDIST+4*YLEN - (i-2)*YLEN/2);
+ p.drawLine(it->x-it->pix->width()*AUX_LINE_LEN/2 -x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos+x_left,y_offset + 2*YLEN - (i-2)*YLEN/2);
}
it->is_active= ( (song->cpos() >= it->source_event->tick() + it->source_part->tick()) &&
@@ -1872,8 +1872,8 @@ void ScoreCanvas::draw_items(QPainter& p, int y_offset, ScoreItemList::iterator
{
cout << "\tBAR" << endl;
- p.setPen(Qt::black); //Y_MARKER
- p.drawLine(it->x -x_pos+x_left,y_offset + YDIST,it->x -x_pos+x_left,y_offset + YDIST+4*YLEN);
+ p.setPen(Qt::black);
+ p.drawLine(it->x -x_pos+x_left,y_offset -2*YLEN,it->x -x_pos+x_left,y_offset +2*YLEN);
for (int i=0;i<7;i++)
curr_accidential[i]=default_accidential[i];
@@ -2010,7 +2010,7 @@ void ScoreCanvas::draw_preamble(QPainter& p, int y_offset)
// draw clef --------------------------------------------------------
QPixmap* pix_clef= (USED_CLEF==BASS) ? pix_clef_bass : pix_clef_violin;
- int y_coord=YDIST+4*YLEN - ( clef_height(USED_CLEF) -2)*YLEN/2; //Y_MARKER
+ int y_coord=2*YLEN - ( clef_height(USED_CLEF) -2)*YLEN/2;
draw_pixmap(p,CLEF_LEFTMARGIN + pix_clef->width()/2,y_offset + y_coord,*pix_clef);
@@ -2035,8 +2035,8 @@ void ScoreCanvas::draw_preamble(QPainter& p, int y_offset)
x_left+=calc_timesig_width(timesig.num, timesig.denom)+TIMESIG_RIGHTMARGIN;
// draw bar ---------------------------------------------------------
- p.setPen(Qt::black); //Y_MARKER
- p.drawLine(x_left,y_offset + YDIST,x_left,y_offset + YDIST+4*YLEN);
+ p.setPen(Qt::black);
+ p.drawLine(x_left,y_offset -2*YLEN,x_left,y_offset +2*YLEN);
if (x_left_old!=x_left)
@@ -2051,10 +2051,9 @@ void ScoreCanvas::draw_timesig(QPainter& p, int x, int y_offset, int num, int de
int width=((num_width > denom_width) ? num_width : denom_width);
int num_indent=(width-num_width)/2 + TIMESIG_LEFTMARGIN;
int denom_indent=(width-denom_width)/2 + TIMESIG_LEFTMARGIN;
- int y=YDIST+2*YLEN;
- draw_number(p, x+num_indent, y_offset + y-DIGIT_YDIST, num);
- draw_number(p, x+denom_indent, y_offset + y+DIGIT_YDIST, denom);
+ draw_number(p, x+num_indent, y_offset -DIGIT_YDIST, num);
+ draw_number(p, x+denom_indent, y_offset +DIGIT_YDIST, denom);
}
int ScoreCanvas::calc_timesig_width(int num, int denom)
@@ -2092,16 +2091,13 @@ void ScoreCanvas::draw(QPainter& p, const QRect&)
p.setPen(Qt::black);
- int y=0;
for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++)
{
- draw_note_lines(p,y);
- draw_preamble(p,y);
+ draw_note_lines(p,it->y_draw);
+ draw_preamble(p,it->y_draw);
p.setClipRect(x_left+1,0,p.device()->width(),p.device()->height());
- draw_items(p,y, it->itemlist);
+ draw_items(p,it->y_draw, it->itemlist);
p.setClipping(false);
-
- y+=STAFF_DISTANCE;
}
}
@@ -2233,8 +2229,7 @@ int ScoreCanvas::height_to_pitch(int h, clef_t clef, tonart_t key)
int ScoreCanvas::y_to_height(int y)
{
- //Y_MARKER
- return int(nearbyint(float(YDIST+4*YLEN - y)*2.0/YLEN))+2 ;
+ return int(nearbyint(float(2*YLEN - y)*2.0/YLEN))+2 ;
}
int ScoreCanvas::y_to_pitch(int y, int t, clef_t clef)
@@ -2251,19 +2246,13 @@ void ScoreCanvas::mousePressEvent (QMouseEvent* event)
// denn der "bereich" eines schlags geht von schlag_begin bis nächsterschlag_begin-1
// noten werden aber genau in die mitte dieses bereiches gezeichnet
- int staff_no= event->y() / STAFF_DISTANCE;
-
- cout << "STAFF NO = " << staff_no << endl;
-
- int y=event->y() - staff_no*STAFF_DISTANCE;
+ list<staff_t>::iterator it=staff_at_y(event->y());
+
+ int y=event->y() - it->y_draw;
int x=event->x()+x_pos-x_left;
int tick=flo_quantize_floor(x_to_tick(x));
//TODO quantizing must (maybe?) be done with the proper functions
- list<staff_t>::iterator it=staffs.begin();
- for (int i=0; i<staff_no && it!=staffs.end(); i++)
- it++;
-
if (it!=staffs.end())
{
ScoreItemList& itemlist=it->itemlist;
@@ -2614,6 +2603,44 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll)
}
}
+
+void ScoreCanvas::recalc_staff_pos()
+{
+ int y=0;
+
+ for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++)
+ {
+ it->y_top=y;
+ switch (it->type)
+ {
+ case NORMAL:
+ it->y_draw = it->y_top + STAFF_DISTANCE/2;
+ it->y_bottom = it->y_draw + STAFF_DISTANCE/2;
+ break;
+ case GRAND_TOP:
+ it->y_draw = it->y_top + STAFF_DISTANCE/2;
+ it->y_bottom = it->y_draw + GRANDSTAFF_DISTANCE/2;
+ break;
+ case GRAND_BOTTOM:
+ it->y_draw = it->y_top + GRANDSTAFF_DISTANCE/2;
+ it->y_bottom = it->y_draw + STAFF_DISTANCE/2;
+ break;
+ default:
+ cout << "THIS SHOULD NEVER HAPPEN: invalid staff type!" << endl;
+ }
+ y=it->y_bottom;
+ }
+}
+
+list<staff_t>::iterator ScoreCanvas::staff_at_y(int y)
+{
+ for (list<staff_t>::iterator it=staffs.begin(); it!=staffs.end(); it++)
+ if ((y >= it->y_top) && (y < it->y_bottom))
+ return it;
+
+ return staffs.end();
+}
+
//the following assertions are made:
// pix_quarter.width() == pix_half.width()
@@ -2641,13 +2668,13 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll)
*
* CURRENT TODO
* o menu entries etc for creating new staves etc.
- * o proper mouse.y -> staff_no translation (plus rounding problems)
+ * o drag-and-dropping staves to merge them
+ * o right-click-menu for staves to select clef(s), remove it etc
+ * o consider both small staves from a grand stave as ONE staff
*
* IMPORTANT TODO
* o support adding staves to existing score window
* o support changing between "all into one" and "each gets one staff"
- * o do the STAFF_DISTANCE thingy better
- * (grand staffs have to be nearer, user-definable distance etc)
* o support grand staves
* o let the user select which clef to use
* o removing the part the score's working on isn't handled
@@ -2694,6 +2721,7 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll)
* o set distances properly [looks okay, doesn't it?]
* o change iterators into const iterators
* o add tracks in correct order to score
+ * o rename staffs to staves
*
* stuff for the other muse developers
* o OFFER A WAY TO EDIT THE KEYMAP (and integrate the keymap properly)
@@ -2746,3 +2774,50 @@ void ScoreCanvas::pos_changed(int index, unsigned tick, bool scroll)
* pos_add_list stays the same for each staff, so we only need one
*/
+/* R O A D M A P
+ * =============
+ *
+ * 1. finish the score editor, without transposing instruments and
+ * with only a global keymap
+ *
+ * REASON: a score editor with few functions is better than
+ * no score editor at all
+ *
+ *
+ * 2. support transposing by octave-steps
+ *
+ * REASON: the main problem with transposing is, that the
+ * editor needs different key signatures and needs
+ * to align them against each other. this problem
+ * doesn't exist when only transposing by octaves
+ *
+ *
+ * 3. support transposing instruments, but only one
+ * transposing-setting per score window. that is, you won't be
+ * able to display your (C-)strings in the same window as your
+ * B-trumpet. this will be very easy to implement
+ *
+ * REASON: the above problem still exists, but is circumvented
+ * by simply not having to align them against each other
+ * (because they're in different windows)
+ *
+ *
+ * 4. support different transposing instruments in the same score
+ * window. this will be some hassle, because we need to align
+ * the scores properly. for example, when the C-violin has
+ * C-major (no accidentials), then the B-trumpet need some
+ * accidentials. we now must align the staves so that the
+ * "note-after-keychange"s of both staves are again at the
+ * same x-position
+ *
+ * REASON: some solution for that problem must be written.
+ * this is a large step, which atm isn't very important
+ *
+ *
+ * 5. support different keys per track. this wouldn't be that
+ * hard, when 4) is already done; because we then already have
+ * the "align it properly" functionality, and can use it
+ *
+ * REASON: this is only a nice-to-have, which can however be
+ * easily implemented when 4) is done
+ */
diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h
index 95dde6c2..189e9e0b 100644
--- a/muse2/muse/midiedit/scoreedit.h
+++ b/muse2/muse/midiedit/scoreedit.h
@@ -451,11 +451,24 @@ struct timesig_t
int denom;
};
+enum staff_type_t
+{
+ NORMAL,
+ GRAND_TOP,
+ GRAND_BOTTOM
+};
+
struct staff_t
{
set<Part*> parts;
ScoreEventList eventlist;
ScoreItemList itemlist;
+
+ int y_top;
+ int y_draw;
+ int y_bottom;
+
+ staff_type_t type;
};
class ScoreCanvas : public View
@@ -504,7 +517,10 @@ class ScoreCanvas : public View
void draw_items(QPainter& p, int y, ScoreItemList& itemlist);
void calc_item_pos(ScoreItemList& itemlist);
void calc_pos_add_list();
-
+
+
+ void recalc_staff_pos();
+ list<staff_t>::iterator staff_at_y(int y);
timesig_t timesig_at_tick(int t);