summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-04-10 15:34:23 +0000
committerFlorian Jung <flo@windfisch.org>2011-04-10 15:34:23 +0000
commitaafa06d32be792680a489d4dd2c119e6b19fc5a1 (patch)
tree3da63f584a7fbca675abf89815e974cff877cb26
parentda8810c2e943da0c3ca6c44cbaa28a6c9470eac3 (diff)
colored notes and multiple tracks for the scoreeditor are now supported
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp134
-rw-r--r--muse2/muse/midiedit/scoreedit.h15
2 files changed, 97 insertions, 52 deletions
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index 2688f52b..49181776 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -33,6 +33,7 @@
#include <QMimeData>
#include <QScrollArea>
#include <QSettings>
+#include <QImage>
#include <stdio.h>
#include <math.h>
@@ -66,7 +67,6 @@ using namespace std;
#include "sig.h"
-
//---------------------------------------------------------
// ScoreEdit
//---------------------------------------------------------
@@ -162,7 +162,7 @@ void ScoreCanvas::song_changed(int)
{
cout << "song changed!" << endl;
pos_add_list.clear();
- eventlist=createAppropriateEventList(editor->parts(), editor->parts()->begin()->second->track());
+ eventlist=createAppropriateEventList(editor->parts());
itemlist=create_itemlist(eventlist);
process_itemlist(itemlist); // do note- and rest-grouping and collision avoiding
calc_item_pos(itemlist);
@@ -179,19 +179,52 @@ string IntToStr(int i)
return s.str();
}
+void load_colored_pixmaps(string file, QPixmap* array)
+{
+ QString fn(file.c_str());
+ QImage img(fn);
+
+ int bytes=img.byteCount();
+ uchar* bits=img.bits();
+ uchar* ptr;
+
+ array[BLACK_PIXMAP]=QPixmap::fromImage(img); //before anything was changed
+ //TODO: really color it black, don't rely on the userdata be correct
+
+ for (int color_index=0;color_index<NUM_PARTCOLORS; color_index++)
+ {
+ ptr=bits;
+ int r,g,b;
+ config.partColors[color_index].getRgb(&r,&g,&b);
+
+ for (int i=0; i<bytes/4; i++)
+ {
+ QRgb* rgb=((QRgb*)ptr);
+ (*rgb) = qRgba(r,g,b,qAlpha(*rgb));
+
+ ptr+=4;
+ }
+
+ array[color_index]=QPixmap::fromImage(img);
+ }
+}
void ScoreCanvas::load_pixmaps()
{
- pix_whole.load(FONT_PATH "whole.png");
- pix_half.load(FONT_PATH "half.png");
- pix_quarter.load(FONT_PATH "quarter.png");
+ load_colored_pixmaps(FONT_PATH "whole.png", pix_whole);
+ load_colored_pixmaps(FONT_PATH "half.png", pix_half);
+ load_colored_pixmaps(FONT_PATH "quarter.png", pix_quarter);
+ load_colored_pixmaps(FONT_PATH "dot.png", pix_dot);
+ load_colored_pixmaps(FONT_PATH "acc_none.png", pix_noacc);
+ load_colored_pixmaps(FONT_PATH "acc_sharp.png", pix_sharp);
+ load_colored_pixmaps(FONT_PATH "acc_b.png", pix_b);
+
pix_r1.load(FONT_PATH "rest1.png");
pix_r2.load(FONT_PATH "rest2.png");
pix_r4.load(FONT_PATH "rest4.png");
pix_r8.load(FONT_PATH "rest8.png");
pix_r16.load(FONT_PATH "rest16.png");
- pix_dot.load(FONT_PATH "dot.png");
pix_flag_up[0].load(FONT_PATH "flags8u.png");
pix_flag_up[1].load(FONT_PATH "flags16u.png");
pix_flag_up[2].load(FONT_PATH "flags32u.png");
@@ -200,9 +233,6 @@ void ScoreCanvas::load_pixmaps()
pix_flag_down[1].load(FONT_PATH "flags16d.png");
pix_flag_down[2].load(FONT_PATH "flags32d.png");
pix_flag_down[3].load(FONT_PATH "flags64d.png");
- pix_noacc.load(FONT_PATH "acc_none.png");
- pix_sharp.load(FONT_PATH "acc_sharp.png");
- pix_b.load(FONT_PATH "acc_b.png");
for (int i=0;i<10;i++)
pix_num[i].load(QString((string(FONT_PATH "")+IntToStr(i)+string(".png")).c_str()));
@@ -245,8 +275,8 @@ bool operator< (const note_pos_t& a, const note_pos_t& b)
* it stores them sorted by their time (quantized); if more
* events with the same time occur, the NOTE-OFFs are
* put before the NOTE-ONs
- * it only operates on parts which a) are selected by the
- * editor and b) belong to track
+ * it only operates on parts which were selected in the
+ * arranger when the score viewer was started
*
* this abstracts the rest of the renderer from muse's internal
* data structures, making this easy to port to another application
@@ -264,7 +294,7 @@ int flo_quantize_floor(int tick)
return int(tick / FLO_QUANT) * FLO_QUANT;
}
-ScoreEventList ScoreCanvas::createAppropriateEventList(PartList* pl, Track* track)
+ScoreEventList ScoreCanvas::createAppropriateEventList(PartList* pl)
{
using AL::sigmap;
using AL::iSigEvent;
@@ -277,26 +307,22 @@ ScoreEventList ScoreCanvas::createAppropriateEventList(PartList* pl, Track* trac
for (iPart partIt=pl->begin(); partIt!=pl->end(); partIt++)
{
Part* part=partIt->second;
- if (part->track()==track)
+ EventList* el=part->events();
+
+ for (iEvent it=el->begin(); it!=el->end(); it++)
{
- EventList* el=part->events();
+ Event& event=it->second;
- for (iEvent it=el->begin(); it!=el->end(); it++)
+ if (event.isNote() && !event.isNoteOff())
{
- Event& event=it->second;
-
- if (event.isNote() && !event.isNoteOff())
- {
- unsigned begin, end;
- begin=flo_quantize(event.tick()+part->tick());
- end=flo_quantize(event.endTick()+part->tick());
- cout <<"inserting note on at "<<begin<<" with pitch="<<event.pitch()<<" and len="<<end-begin<<endl;
- result.insert(pair<unsigned, FloEvent>(begin, FloEvent(begin,event.pitch(), event.velo(),end-begin,FloEvent::NOTE_ON,part,&it->second)));
- }
- //else ignore it
+ unsigned begin, end;
+ begin=flo_quantize(event.tick()+part->tick());
+ end=flo_quantize(event.endTick()+part->tick());
+ cout <<"inserting note on at "<<begin<<" with pitch="<<event.pitch()<<" and len="<<end-begin<<endl;
+ result.insert(pair<unsigned, FloEvent>(begin, FloEvent(begin,event.pitch(), event.velo(),end-begin,FloEvent::NOTE_ON,part,&it->second)));
}
+ //else ignore it
}
- //else ignore it
}
//insert bars and time signatures
@@ -702,7 +728,7 @@ list<note_len_t> ScoreCanvas::parse_note_len(int len_ticks, int begin_tick, vect
#define TIE_HEIGHT 6
#define TIE_THICKNESS 3
-void ScoreCanvas::draw_tie (QPainter& p, int x1, int x4, int yo, bool up)
+void ScoreCanvas::draw_tie (QPainter& p, int x1, int x4, int yo, bool up, QColor color)
{
QPainterPath path;
@@ -728,8 +754,8 @@ void ScoreCanvas::draw_tie (QPainter& p, int x1, int x4, int yo, bool up)
path.cubicTo( x2,y2 , x3,y2 , x4,y1 );
path.cubicTo( x3,y3 , x2,y3 , x1,y1 );
- p.setPen(Qt::black);
- p.setBrush(Qt::black);
+ p.setPen(color);
+ p.setBrush(color);
p.drawPath(path);
}
@@ -1338,6 +1364,8 @@ void ScoreCanvas::draw_note_lines(QPainter& p)
{
int xend=width();
+ p.setPen(Qt::black);
+
for (int i=0;i<5;i++)
p.drawLine(0,YDIST+i*YLEN,xend,YDIST+i*YLEN);
}
@@ -1362,9 +1390,9 @@ void ScoreCanvas::calc_item_pos(ScoreItemList& itemlist)
switch (it->len)
{
- case 0: it->pix=&pix_whole; break;
- case 1: it->pix=&pix_half; break;
- default: it->pix=&pix_quarter; break;
+ case 0: it->pix=pix_whole; break;
+ case 1: it->pix=pix_half; break;
+ default: it->pix=pix_quarter; break;
}
it->stem_x=it->x;
@@ -1544,17 +1572,21 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
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,YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos,YDIST+4*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,YDIST+4*YLEN - (i-2)*YLEN/2,it->x+it->pix->width()*AUX_LINE_LEN/2-x_pos,YDIST+4*YLEN - (i-2)*YLEN/2);
}
- draw_pixmap(p,it->x -x_pos,it->y,*it->pix);
+ draw_pixmap(p,it->x -x_pos,it->y,it->pix[it->source_part->colorIndex()]);
+ //TODO FINDMICH draw a margin around bright colors
+ //maybe draw the default color in black?
//draw dots
@@ -1571,7 +1603,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
for (int i=0;i<it->dots;i++)
{
- draw_pixmap(p,it->x+x_dot -x_pos,it->y+y_dot,pix_dot);
+ draw_pixmap(p,it->x+x_dot -x_pos,it->y+y_dot,pix_dot[it->source_part->colorIndex()]);
x_dot+=DOT_XDIST;
}
@@ -1583,11 +1615,11 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
QPixmap* acc_pix;
switch (it->pos.vorzeichen)
{
- case NONE: acc_pix=&pix_noacc; break;
- case SHARP: acc_pix=&pix_sharp; break;
- case B: acc_pix=&pix_b; break;
+ case NONE: acc_pix=pix_noacc; break;
+ case SHARP: acc_pix=pix_sharp; break;
+ case B: acc_pix=pix_b; break;
}
- draw_pixmap(p,it->x-ACCIDENTIAL_DIST -x_pos,it->y, *acc_pix);
+ draw_pixmap(p,it->x-ACCIDENTIAL_DIST -x_pos,it->y, acc_pix[it->source_part->colorIndex()]);
curr_accidential[modulo(it->pos.height,7)]=it->pos.vorzeichen;
}
@@ -1597,7 +1629,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
if (it->is_tie_dest)
{
cout << "drawing tie" << endl;
- draw_tie(p,it->tie_from_x-x_pos,it->x -x_pos,it->y, (it->len==0) ? true : (it->stem==DOWNWARDS) );
+ draw_tie(p,it->tie_from_x-x_pos,it->x -x_pos,it->y, (it->len==0) ? true : (it->stem==DOWNWARDS) , config.partColors[it->source_part->colorIndex()]);
// in english: "if it's a whole note, tie is upwards (true). if not, tie is upwards if
// stem is downwards and vice versa"
}
@@ -1625,7 +1657,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
for (int i=0;i<it->dots;i++)
{
- draw_pixmap(p,it->x+x_dot -x_pos,it->y+y_dot,pix_dot);
+ draw_pixmap(p,it->x+x_dot -x_pos,it->y+y_dot,pix_dot[BLACK_PIXMAP]);
x_dot+=DOT_XDIST;
}
}
@@ -1633,6 +1665,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
{
cout << "\tBAR" << endl;
+ p.setPen(Qt::black);
p.drawLine(it->x -x_pos,YDIST,it->x -x_pos,YDIST+4*YLEN);
for (int i=0;i<7;i++)
@@ -1659,11 +1692,11 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
for (list<int>::iterator acc_it=aufloes_list.begin(); acc_it!=aufloes_list.end(); acc_it++)
{
int y_coord=YDIST+4*YLEN - ( *acc_it -2)*YLEN/2; //Y_MARKER
- draw_pixmap(p,it->x + n_acc_drawn*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_LEFTDIST -x_pos,y_coord,pix_noacc);
+ draw_pixmap(p,it->x + n_acc_drawn*KEYCHANGE_ACC_DIST + KEYCHANGE_ACC_LEFTDIST -x_pos,y_coord,pix_noacc[BLACK_PIXMAP]);
n_acc_drawn++;
}
- QPixmap* pix = is_sharp_key(new_key) ? &pix_sharp : &pix_b;
+ QPixmap* pix = is_sharp_key(new_key) ? &pix_sharp[BLACK_PIXMAP] : &pix_b[BLACK_PIXMAP];
vorzeichen_t new_accidential = is_sharp_key(new_key) ? SHARP : B;
for (int i=0;i<7;i++)
@@ -1685,10 +1718,11 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
}
}
+ p.setPen(Qt::black);
//note: y1 is bottom, y2 is top!
if (upstem_x!=-1)
{
- upstem_x=upstem_x-pix_quarter.width()/2 +pix_quarter.width() -1;
+ upstem_x=upstem_x-pix_quarter[0].width()/2 +pix_quarter[0].width() -1;
p.drawLine(upstem_x -x_pos, upstem_y1, upstem_x -x_pos, upstem_y2-STEM_LEN);
if (upflag>=3) //if the note needs a flag
@@ -1696,7 +1730,7 @@ void ScoreCanvas::draw_items(QPainter& p, ScoreItemList& itemlist, ScoreItemList
}
if (downstem_x!=-1)
{
- downstem_x=downstem_x-pix_quarter.width()/2;
+ downstem_x=downstem_x-pix_quarter[0].width()/2;
p.drawLine(downstem_x -x_pos, downstem_y1+STEM_LEN, downstem_x -x_pos, downstem_y2);
if (downflag>=3) //if the note needs a flag
@@ -2171,16 +2205,18 @@ void ScoreCanvas::scroll_event(int x)
*
* IMPORTANT TODO
* o removing the part the score's working on isn't handled
- * o handle multiple tracks, with different color (QColor c(config.partColors[part->colorIndex()]);)
* o let the user select the currently edited part
+ * o let the user select between "colors after the parts",
+ * "colors after selected/unselected part" and "all black"
* o draw clef, maybe support clef changes
* o support violin and bass at one time
- * o eliminate overlapping notes (e.g. C from 0 with len=10 and C from 5 with len=10)
* o use correct scrolling bounds
* o automatically scroll when playing
* o support selections
*
* less important stuff
+ * o draw a margin about notes which are in a bright color
+ * o maybe override color 0 with "black"?
* o create nice functions for drawing keychange-accidentials
* o check if "moving away" works for whole notes [seems to NOT work properly]
* o use bars instead of flags over groups of 8ths / 16ths etc
@@ -2207,4 +2243,8 @@ void ScoreCanvas::scroll_event(int x)
* o offer dropdown-boxes for lengths of the inserted note
* (select between 16th, 8th, ... whole and "last used length")
* o offer a dropdown-box for the clef to use
+ * o offer some way to setup the colorizing method to be used
*/
+
+
+
diff --git a/muse2/muse/midiedit/scoreedit.h b/muse2/muse/midiedit/scoreedit.h
index 9382029d..4bb4c48b 100644
--- a/muse2/muse/midiedit/scoreedit.h
+++ b/muse2/muse/midiedit/scoreedit.h
@@ -22,6 +22,7 @@
#include "tools.h"
#include "event.h"
#include "view.h"
+#include "gconfig.h"
#include <set>
#include <map>
@@ -60,6 +61,9 @@ class QScrollBar;
class MidiTrackInfo;
class QScrollArea;
+
+
+
//---------------------------------------------------------
// ScoreEdit
//---------------------------------------------------------
@@ -396,18 +400,19 @@ struct cumulative_t
}
};
+#define BLACK_PIXMAP (NUM_PARTCOLORS)
class ScoreCanvas : public View
{
Q_OBJECT
private:
void load_pixmaps();
- ScoreEventList createAppropriateEventList(PartList* pl, Track* track);
+ ScoreEventList createAppropriateEventList(PartList* pl);
note_pos_t note_pos_(int note, tonart_t key);
note_pos_t note_pos (int note, tonart_t key, clef_t clef);
int calc_len(int l, int d);
list<note_len_t> parse_note_len(int len_ticks, int begin_tick, vector<int>& foo, bool allow_dots=true, bool allow_normal=true);
- void draw_tie (QPainter& p, int x1, int x4, int yo, bool up=true);
+ void draw_tie (QPainter& p, int x1, int x4, int yo, bool up=true, QColor color=Qt::black);
ScoreItemList create_itemlist(ScoreEventList& eventlist);
void process_itemlist(ScoreItemList& itemlist);
void draw_pixmap(QPainter& p, int x, int y, const QPixmap& pm);
@@ -433,10 +438,10 @@ class ScoreCanvas : public View
int x_to_tick(int x);
int calc_posadd(int t);
- QPixmap pix_whole, pix_half, pix_quarter;
+ QPixmap pix_whole[NUM_PARTCOLORS+1], pix_half[NUM_PARTCOLORS+1], pix_quarter[NUM_PARTCOLORS+1];
QPixmap pix_r1, pix_r2, pix_r4, pix_r8, pix_r16;
- QPixmap pix_dot, pix_flag_up[4], pix_flag_down[4];
- QPixmap pix_b, pix_sharp, pix_noacc;
+ QPixmap pix_dot[NUM_PARTCOLORS+1], pix_flag_up[4], pix_flag_down[4];
+ QPixmap pix_b[NUM_PARTCOLORS+1], pix_sharp[NUM_PARTCOLORS+1], pix_noacc[NUM_PARTCOLORS+1];
QPixmap pix_num[10];