pianobooster/src/Score.cpp

269 lines
8.7 KiB
C++

/*********************************************************************************/
/*!
@file Score.cpp
@brief xxxx.
@author L. J. Barman
Copyright (c) 2008-2013, L. J. Barman, all rights reserved
This file is part of the PianoBooster application
PianoBooster is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
PianoBooster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PianoBooster. If not, see <http://www.gnu.org/licenses/>.
*/
/*********************************************************************************/
#include "Cfg.h"
#include "Draw.h"
#include "Score.h"
CScore::CScore(CSettings* settings) : CDraw(settings)
{
m_piano = new CPiano(settings);
m_rating = nullptr;
for (int i=0; i< arraySize(m_scroll); i++)
{
m_scroll[i] = new CScroll(i, settings);
m_scroll[i]->setChannel(i);
}
m_activeScroll = -1;
m_stavesDisplayListId = 0;
m_scoreDisplayListId = 0;//glGenLists (1);
}
CScore::~CScore()
{
delete m_piano;
for (auto *const scroll : m_scroll)
delete scroll;
if (m_scoreDisplayListId != 0)
glDeleteLists(m_scoreDisplayListId, 1);
m_scoreDisplayListId = 0;
if (m_stavesDisplayListId != 0)
glDeleteLists(m_stavesDisplayListId, 1);
m_stavesDisplayListId = 0;
}
void CScore::init()
{
}
void CScore::drawScroll(bool refresh)
{
if (refresh == false)
{
float topY = CStavePos(PB_PART_right, MAX_STAVE_INDEX).getPosY();
float bottomY = CStavePos(PB_PART_left, MIN_STAVE_INDEX).getPosY();
drColor (Cfg::colorTheme().backgroundColor);
glRectf(Cfg::scrollStartX(), topY, static_cast<float>(Cfg::getAppWidth()), bottomY);
}
if (m_stavesDisplayListId == 0)
m_stavesDisplayListId = glGenLists (1);
if (getCompileRedrawCount())
{
glNewList (m_stavesDisplayListId, GL_COMPILE_AND_EXECUTE);
drawSymbol(CSymbol(PB_SYMBOL_playingZone, CStavePos(PB_PART_both, 0)), Cfg::playZoneX());
drawStaves(Cfg::scrollStartX(), Cfg::staveEndX());
glEndList ();
// decrement the compile count until is reaches zero
forceCompileRedraw(0);
}
else
glCallList(m_stavesDisplayListId);
if (m_settings->value("View/PianoKeyboard").toString()=="on"){
drawPianoKeyboard();
}
drawScrollingSymbols(true);
m_piano->drawPianoInput();
}
void CScore::drawPianoKeyboard(){
const static int keysCount = 88;
struct PianoKeyboard {
int i, k;
float yStart;
float xSize;
float ySize;
float xPlaceSize;
float xKeySize;
char state[keysCount];
bool stopped;
PianoKeyboard() {
i = 0; k = 0;
yStart = 0.0f;
xSize = Cfg::staveEndX() - Cfg::staveStartX();
ySize = 30;
xPlaceSize = xSize / 52.0f;
xKeySize = xPlaceSize - xPlaceSize * 0.1f;
stopped = false;
}
void drawBackground() {
const auto backgroundColor = CColor(0.0f, 0.0f, 0.0f);
const auto backgroundMargin = 2.5f;
const auto backgroundHight = ySize + 12.5f + backgroundMargin;
const auto backgroundX = Cfg::staveStartX() - backgroundMargin;
const auto backgroundRight = backgroundX + xSize + backgroundMargin;
CDraw::drColor(backgroundColor);
glPushMatrix();
glBegin(GL_QUADS);
glVertex2f(backgroundX, backgroundHight);
glVertex2f(backgroundRight, backgroundHight);
glVertex2f(backgroundRight, 0.0f);
glVertex2f(backgroundX, 0.0f);
glEnd();
glPopMatrix();
}
void drawBlackKey(int i, int k) {
glPushMatrix();
float yBlackShift = ySize / 2.5f;
float yBlackSize = ySize - yBlackShift;
glScalef(1.0f, 1.4f, 1.0f);
glTranslatef(Cfg::staveStartX() + xPlaceSize * static_cast<float>(i) - xPlaceSize / 3.0f,
yStart + yBlackShift, 0.0f);
float xKeySize = this->xKeySize / 1.5f;
CDraw::drColor (CColor(0.0, 0.0, 0.0));
if(state[k]==1) CDraw::drColor(stopped ? Cfg::colorTheme().playedStoppedColor : Cfg::colorTheme().noteColor);
if(state[k]==2) CDraw::drColor(Cfg::colorTheme().playedBadColor);
glBegin(GL_QUADS);
glVertex2f(0, yBlackSize);
glVertex2f(xKeySize, yBlackSize);
glVertex2f(xKeySize, 0);
glVertex2f(0, 0);
glEnd();
glPopMatrix();
state[k] = 0;
}
void drawWhiteKey() {
glPushMatrix();
glScalef(1.0f, 1.4f, 1.0f);
glTranslatef(Cfg::staveStartX() + xPlaceSize * static_cast<float>(i++), yStart, 0.0f);
const auto &theme = Cfg::colorTheme();
auto color = CColor(1.0, 1.0, 1.0);
if(state[k]==1) color = stopped ? theme.playedStoppedColor : theme.noteColor;
else if(state[k]==2) color = theme.playedBadColor;
color.ensureBrightness(0.4f); // ensure the color is bright enough to not blend too much with black keys
CDraw::drColor(color);
glBegin(GL_QUADS);
glVertex2f(0, ySize);
glVertex2f(xKeySize, ySize);
glVertex2f(xKeySize, 0);
glVertex2f(0, 0);
glEnd();
glPopMatrix();
state[k++] = 0;
}
void drawOctave() {
drawWhiteKey();
int b1 = i, k1 = k++;
drawWhiteKey();
int b2 = i, k2 = k++;
drawWhiteKey();
drawWhiteKey();
int b3 = i, k3 = k++;
drawWhiteKey();
int b4 = i, k4 = k++;
drawWhiteKey();
int b5 = i, k5 = k++;
drawWhiteKey();
drawBlackKey(b1, k1);
drawBlackKey(b2, k2);
drawBlackKey(b3, k3);
drawBlackKey(b4, k4);
drawBlackKey(b5, k5);
}
void drawKeyboard() {
drawBackground();
i = k = 0;
drawWhiteKey();
int b1 = i, k1 = k++;
drawWhiteKey();
drawBlackKey(b1, k1);
for(int i=0; i<7; ++i) drawOctave();
drawWhiteKey();
}
};
static PianoKeyboard pianoKeyboard;
CChord chord = m_piano->getBadChord();
for(int n=0; n<chord.length(); ++n) {
int pitch = chord.getNote(n).pitch();
int k = pitch - 21;
k = k < 0 ? 0 : (k >= keysCount ? (keysCount-1) : k);
pianoKeyboard.state[k] = 2;
}
for (auto *const scroll : m_scroll) {
int notes[64];
memset(notes, 0, sizeof(notes));
bool stopped = scroll->getKeyboardInfo(notes);
for(int *note=notes; *note; ++note) {
pianoKeyboard.stopped = stopped;
int k = *note - 21;
k = k < 0 ? 0 : (k >= keysCount ? (keysCount-1) : k);
pianoKeyboard.state[k] = 1;
}
}
pianoKeyboard.drawKeyboard();
}
void CScore::drawScore()
{
if (getCompileRedrawCount())
{
if (m_scoreDisplayListId == 0)
m_scoreDisplayListId = glGenLists (1);
glNewList (m_scoreDisplayListId, GL_COMPILE_AND_EXECUTE);
drColor (Cfg::colorTheme().staveColor);
if (m_settings->value("SidePanel/clefRight").toInt() == PB_SYMBOL_gClef)
drawSymbol(CSymbol(PB_SYMBOL_gClef, CStavePos(PB_PART_right, -1)), Cfg::clefX()); // The Treble Clef
else if (m_settings->value("SidePanel/clefRight").toInt() == PB_SYMBOL_fClef)
drawSymbol(CSymbol(PB_SYMBOL_fClef, CStavePos(PB_PART_right, 1)), Cfg::clefX());
if (m_settings->value("SidePanel/clefLeft").toInt() == PB_SYMBOL_gClef)
drawSymbol(CSymbol(PB_SYMBOL_gClef, CStavePos(PB_PART_left, -1)), Cfg::clefX());
else if (m_settings->value("SidePanel/clefLeft").toInt() == PB_SYMBOL_fClef)
drawSymbol(CSymbol(PB_SYMBOL_fClef, CStavePos(PB_PART_left, 1)), Cfg::clefX());
drawKeySignature(CStavePos::getKeySignature());
drawStaves(Cfg::staveStartX(), Cfg::scrollStartX());
glEndList ();
}
else
glCallList(m_scoreDisplayListId);
}