You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
4.8 KiB
121 lines
4.8 KiB
//Standard lib
|
|
#include <stdio.h>
|
|
|
|
//Third party
|
|
#include "raylib.h"
|
|
|
|
//Our own files
|
|
#include "constants.h"
|
|
#include "programstate.h"
|
|
#include "drawhelper.h"
|
|
#include "draw_port_grids.h"
|
|
|
|
/* Each port is a grid square, ordered in rows, like text
|
|
* Pitches are put on a 12x12 square for octaves.
|
|
* The screen does not move or scroll. Notes fade out and make room for the next note-on.
|
|
*/
|
|
|
|
extern ProgramState programState;
|
|
|
|
static Rectangle backgroundRects[VIS_PORTS]; // 4 floats: x, y, w, h
|
|
|
|
static void reposition(Note *allGUINotes) {
|
|
//This is both init and update. We only call it internally, the name of the function doesn't matter.
|
|
//Once guaranteed called on program start and then each window resize
|
|
int screenWidth = GetScreenWidth();
|
|
int screenHeight = GetScreenHeight();
|
|
int blockSize = 13 * (NOTE_SMALL_SIDE + NOTE_GAP); //space the blocks one row/column apart = 13
|
|
int xOffset = (int)(screenWidth/2) - (VIS_PORTS_SQRT/2)*blockSize; //shift half of the grid blocks from the center to the left
|
|
int yOffset = (int)(screenHeight/2) - (VIS_PORTS_SQRT/2)*blockSize; //shift half of the grid blocks from the center to the left
|
|
|
|
//top left corner of each block
|
|
int blockX;
|
|
int blockY;
|
|
int portRow;
|
|
int portColumn;
|
|
int pitchRow;
|
|
int pitchColumn;
|
|
|
|
programState.modeDescription = "Each port is one grid.\
|
|
\nEach pitch is one square, from top left\nto bottom right.\
|
|
\nPitch rows wrap, just like normal text.\n\n\
|
|
\n\
|
|
The higher the velocity of a note the more\nvibrant its color.\n\
|
|
\n\
|
|
Notes are only lit up when they are played.\n\
|
|
There is no time-dimension.";
|
|
|
|
for (int port=0; port<VIS_PORTS; port++) {
|
|
//We loop in a way that is guaranteed to have >= grid blocks available for all notes
|
|
//But we will never try to access more notes than exist in allGUINotes.
|
|
portRow = port / VIS_PORTS_SQRT;
|
|
portColumn = port % VIS_PORTS_SQRT;
|
|
blockY = portRow * blockSize;
|
|
blockX = portColumn * blockSize;
|
|
|
|
backgroundRects[port].x = (float)(xOffset + blockX);
|
|
backgroundRects[port].y = (float)(yOffset + blockY);
|
|
backgroundRects[port].width = (float)(12 * (NOTE_SMALL_SIDE + NOTE_GAP)); //blocksize without filling the extra gap
|
|
backgroundRects[port].height = (float)(12 * (NOTE_SMALL_SIDE + NOTE_GAP));
|
|
//Build a 12x12 Grid for octaves.
|
|
for (int midiPitch=0; midiPitch<128; midiPitch++) {
|
|
pitchRow = midiPitch / 12 +1; //shift one down because it is prettier
|
|
pitchColumn = midiPitch % 12;
|
|
allGUINotes[port*128 + midiPitch].x = xOffset + blockX + pitchColumn * (NOTE_SMALL_SIDE + NOTE_GAP);
|
|
allGUINotes[port*128 + midiPitch].y = yOffset + blockY + pitchRow * (NOTE_SMALL_SIDE + NOTE_GAP);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void drawBackground() {
|
|
//Each port is one track
|
|
//The background rects already have their positions and dimensions set.
|
|
if (programState.showPortBackground) {
|
|
for (int port=0; port<VIS_PORTS; port++) {
|
|
if (portShouldDraw(port)) {
|
|
DrawRectangleRec(backgroundRects[port], programState.colors[backgroundLight]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw_port_grids(Note *allGUINotes, int redrawNeeded) {
|
|
Note * nt;
|
|
float ft = GetFrameTime();
|
|
|
|
if (redrawNeeded) {
|
|
reposition(allGUINotes);
|
|
}
|
|
|
|
//Z-Order is created by call-order. First is bottom.
|
|
drawBackground();
|
|
|
|
if (programState.showConnectedPortnames) {
|
|
for (int port=0; port<VIS_PORTS; port++) {
|
|
nt = &allGUINotes[port*128]; // top left note of each port
|
|
drawJackPortName(programState.connectedPortNames[port], nt->x, nt->y-1.5*(NOTE_SMALL_SIDE + NOTE_GAP), 18, RAYWHITE, false); //text, x, y, int fontsize, color, vertical
|
|
}
|
|
}
|
|
|
|
if (programState.showPitchMarker) {
|
|
//Each block has a pitch marker at one note that we draw with a different color.
|
|
//We use the already set note positions but create a background note behind the real one.
|
|
for (int port=0; port<VIS_PORTS; port++) {
|
|
if (portShouldDraw(port)) {
|
|
nt = &allGUINotes[port*128 + programState.pitchMarkerValue];
|
|
Rectangle rec = (Rectangle){nt->x, nt->y, NOTE_SMALL_SIDE-NOTE_BORDER, NOTE_SMALL_SIDE-NOTE_BORDER};
|
|
DrawRectangleRounded(rec, 0.5, 8, programState.colors[backgroundLighter]);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int port=0; port<VIS_PORTS; port++) {
|
|
for (int midiPitch=0; midiPitch<128; midiPitch++) { //128 is a fixed midi value, no need to dynamically get the size
|
|
nt = &allGUINotes[port*128 + midiPitch];
|
|
if (nt->active) {
|
|
reduceCountdown(nt, ft); //handles 0.0 and 1.0 as special cases
|
|
drawNoteRect(nt, 0, 1); //note, rotated, square. Will not draw if not active/countdown == 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|