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.
116 lines
5.6 KiB
116 lines
5.6 KiB
2 years ago
|
//Standard lib
|
||
|
#include <stdio.h>
|
||
|
|
||
|
//Third party
|
||
|
#include "raylib.h"
|
||
|
#include "raygui.h" // Required for GUI controls
|
||
|
|
||
|
//Our own files
|
||
|
#include "constants.h"
|
||
|
#include "programstate.h"
|
||
|
#include "drawhelper.h"
|
||
|
#include "draw_meterbridge.h"
|
||
|
|
||
|
extern ProgramState programState;
|
||
|
static Rectangle backgroundRect;
|
||
|
static bool guiGroupEditMode= false;
|
||
|
static int screenHeight;
|
||
|
static int bottom;
|
||
|
|
||
|
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 xOffset = (int)(screenWidth/2) - (int)(60*(NOTE_LONG_SIDE+NOTE_GAP)); //we want all tracks around the center.
|
||
|
int yOffset = (int)(screenHeight/2) - (int)(NOTE_SMALL_SIDE+NOTE_GAP)*2; //we want all tracks below the center.
|
||
|
|
||
|
programState.modeDescription = "All port are in one horizontal row.\
|
||
|
\nPitches are left to right, low to high.\
|
||
|
\n\
|
||
|
\nVelocity 'shoots' notes upwards, then they fall back\
|
||
|
\ninfluenced by the fade-out setting.\
|
||
|
\n\
|
||
|
\nYou can set the a 'grouping' parameter for this mode\
|
||
|
\nwhich combines several pitches into a single indicator.\
|
||
|
\nGrouping uses the pitch marker pitch as baseline.\
|
||
|
\nThink of it like the tonic or root note.\
|
||
|
\n\
|
||
|
\n\
|
||
|
\nNotes are only lit up when they are played.\
|
||
|
\nThere is no time-dimension.";
|
||
|
|
||
|
int rootNote = programState.pitchMarkerValue % 12; //factor out the octave. used to start groups on the pitchmarker as root note of the scale
|
||
|
int xpos = xOffset;
|
||
|
int pitchToTheCenter = 64 - (128/programState.meterbridge_grouping/2);
|
||
|
for (int port=0; port<VIS_PORTS; port++) {
|
||
|
for (int midiPitch=0; midiPitch<128; midiPitch++) { //We prepare the full range of pitches, but the main loop will only activate the current pitch range.
|
||
|
int adjustedNotePitch = (int)((midiPitch-rootNote)/programState.meterbridge_grouping) + pitchToTheCenter;
|
||
|
xpos = xOffset + adjustedNotePitch*NOTE_LONG_SIDE + adjustedNotePitch*NOTE_GAP/2;
|
||
|
allGUINotes[port*128 + midiPitch].x = xpos;
|
||
|
allGUINotes[port*128 + midiPitch].y = yOffset + NOTE_SMALL_SIDE + NOTE_GAP*2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
backgroundRect.x = allGUINotes[programState.pitchMin].x; //includes offset
|
||
|
backgroundRect.y = (float)(yOffset + NOTE_SMALL_SIDE + NOTE_GAP*2 - NOTE_GAP);
|
||
|
backgroundRect.width = allGUINotes[programState.pitchMax].x - allGUINotes[programState.pitchMin].x;
|
||
|
backgroundRect.height = (float)NOTE_SMALL_SIDE;
|
||
|
}
|
||
|
|
||
|
static void drawBackground() {
|
||
|
if (programState.showPortBackground) {
|
||
|
DrawRectangleRec(backgroundRect, programState.colors[backgroundLight]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void draw_meterbridge(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.showPitchMarker) {
|
||
|
nt = &allGUINotes[programState.pitchMarkerValue];
|
||
|
Rectangle rec = (Rectangle){nt->x, nt->y+NOTE_SMALL_SIDE, NOTE_LONG_SIDE-NOTE_BORDER, NOTE_SMALL_SIDE-NOTE_BORDER}; //TODO: Ha! :) This falls down as well, together with the note.
|
||
|
DrawRectangleRounded(rec, 0.5, 8, programState.colors[backgroundLighter]);
|
||
|
}
|
||
|
|
||
|
//Debug: Show 0 and 127
|
||
|
//DrawLine(allGUINotes[0].x, 0, allGUINotes[0].x, GetScreenHeight(), RAYWHITE); //(int startPosX, int startPosY, int endPosX, int endPosY, Color color);
|
||
|
//DrawLine(allGUINotes[127].x, 0, allGUINotes[127].x, GetScreenHeight(), RAYWHITE); //(int startPosX, int startPosY, int endPosX, int endPosY, Color color);
|
||
|
|
||
|
for (int port=0; port<VIS_PORTS; port++) {
|
||
|
for (int midiPitch=programState.pitchMin; midiPitch<=programState.pitchMax; midiPitch++) {
|
||
|
nt = &allGUINotes[port*128 + midiPitch];
|
||
|
if (nt->active) {
|
||
|
nt->y = backgroundRect.y - 2*(nt->countdown * nt->velocity); //Shift the notes upwards. Don't use -= or +=, that is exponential modifications
|
||
|
reduceCountdown(nt, ft/2); //handles 0.0 and 1.0 as special cases
|
||
|
drawNoteRect(nt, 1, 0); //note, rotated, square. Will not draw if not active/countdown == 0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Our own GUI section
|
||
|
if (programState.guiVisible) {
|
||
|
EndMode2D(); //We are already in camera mode because this is a draw_ function. GUI is not under camera control.
|
||
|
int row = 0;
|
||
|
screenHeight = GetScreenHeight(); //Changes on resize
|
||
|
bottom = screenHeight - 2*SPACING;
|
||
|
int remember = programState.meterbridge_grouping;
|
||
|
GuiLabel((Rectangle){ 34, bottom-row*SPACING, 105, HEIGHT }, "Meterbridge Note Grouping"); // void GuiLabel(Rectangle bounds, const char *text);
|
||
|
if (GuiSpinner((Rectangle){ 250, bottom-row*SPACING, 80, HEIGHT }, "", &programState.meterbridge_grouping, 0, 127, guiGroupEditMode)) guiGroupEditMode = !guiGroupEditMode; // bool GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode)
|
||
|
if (programState.meterbridge_grouping > 128) {programState.meterbridge_grouping=128;}
|
||
|
if (programState.meterbridge_grouping < 1) {programState.meterbridge_grouping=1;}
|
||
|
if (remember != programState.meterbridge_grouping) { reposition(allGUINotes); } //we cannot set guiRedrawNeeded to true here because parent draw() will reset it after we return
|
||
|
|
||
|
row++;
|
||
|
BeginMode2D(programState.camera); //Switch back to previously active camera mode
|
||
|
}
|
||
|
}
|