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.
181 lines
6.4 KiB
181 lines
6.4 KiB
//Standard lib
|
|
#include <string.h> //strchr
|
|
#include <stdio.h> //print error messages
|
|
|
|
//Third party
|
|
#include "raylib.h"
|
|
|
|
//Our own files
|
|
#include "constants.h"
|
|
#include "programstate.h"
|
|
#include "drawhelper.h"
|
|
|
|
extern ProgramState programState;
|
|
|
|
|
|
float intToHue(int number, int maxnumber) {
|
|
//previously used to auto-color ports this is now only used for the default port colors.
|
|
|
|
//portnum is 0-VIS_PORTS
|
|
//hue is 0-360
|
|
//return (input-inputLowest) / (inputHighest-inputLowest) * (outputHighest-outputLowest) + outputLowest
|
|
return (float)number / (float)maxnumber * 360.0f;
|
|
}
|
|
|
|
Color intToColor(int number, int maxnumber) {
|
|
Color result;
|
|
Vector3 hsv; // 3 floats: hue/color, saturation, value/brightness
|
|
|
|
hsv = (Vector3){intToHue(number, VIS_PORTS), 1.0f, (float)(127+40)/(float)167}; //Saturation is always 1, we tweak Value to never go into the black range.
|
|
result = ColorFromHSV(hsv);
|
|
return result;
|
|
}
|
|
|
|
Color midiToColor(Note * note) {
|
|
Color result;
|
|
Vector3 hsv; // 3 floats: hue/color, saturation, value/brightness
|
|
|
|
//hsv = (Vector3){intToHue(note->port, VIS_PORTS), 1.0f, (float)(note->velocity+40)/(float)167}; //Saturation is always 1, we tweak Value to never go into the black range.
|
|
float hue=ColorToHSV(programState.colors[note->port]).x;
|
|
hsv = (Vector3){hue, 1.0f, (float)(note->velocity+40)/(float)167}; //Saturation is always 1, we tweak Value to never go into the black range.
|
|
result = ColorFromHSV(hsv);
|
|
return result;
|
|
}
|
|
|
|
void drawNoteRect(Note * note, int rotated, int square) {
|
|
if (note->active) {
|
|
//opacity is between 0.0f and 1.0f
|
|
int w,h;
|
|
|
|
if (square==1) {
|
|
w = NOTE_SMALL_SIDE - NOTE_BORDER;
|
|
h = NOTE_SMALL_SIDE - NOTE_BORDER;
|
|
}
|
|
else { //Not Square
|
|
if (rotated==0) {
|
|
w = NOTE_SMALL_SIDE - NOTE_BORDER;
|
|
h = NOTE_LONG_SIDE - NOTE_BORDER;
|
|
}
|
|
else {
|
|
h = NOTE_SMALL_SIDE - NOTE_BORDER;
|
|
w = NOTE_LONG_SIDE - NOTE_BORDER;
|
|
}
|
|
}
|
|
|
|
const Rectangle rec = (Rectangle){note->x, note->y, w,h};
|
|
const Rectangle outer = (Rectangle){note->x-NOTE_BORDER/2, note->y-NOTE_BORDER/2, w+NOTE_BORDER, h+NOTE_BORDER};
|
|
|
|
Color bordercolor = Fade(BLACK, note->countdown);
|
|
Color color = Fade(programState.colors[note->port], note->countdown);
|
|
|
|
//Drawing order is reverse Z-Order
|
|
DrawRectangleRounded(outer, 0.5, 8, bordercolor); //float roundness, int segments/smoothness, Color
|
|
DrawRectangleRounded(rec, 0.5, 8, color);
|
|
}
|
|
}
|
|
|
|
bool portShouldDraw(int port) {
|
|
//Check various conditions if a port background, port name and pitch marker should be drawn
|
|
if ( programState.showPortBackgroundForUnconnected || ( programState.connectedPortNames[port] && programState.connectedPortNames[port][0] != '\0' )) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
void drawJackPortName(const char * portname, int x, int y, int fontsize, Color color, bool vertical) {
|
|
|
|
if (portname && portname[0] != '\0') {
|
|
|
|
const char * finalPortName;
|
|
if (programState.includeClientInPortNameDisplay) {
|
|
finalPortName = portname; //TODO: Pretty Names don't contain the client name. Add it ourselves?
|
|
}
|
|
else {
|
|
if (strchr(portname, ':') == NULL ) //Pretty Names don't contain the client name.
|
|
{
|
|
finalPortName = portname;
|
|
}
|
|
else {
|
|
finalPortName = strchr(portname, ':')+1;
|
|
}
|
|
} //final port name is ready.
|
|
|
|
|
|
//Vertical Mode
|
|
//void DrawTextCodepoint(Font font, int codepoint, Vector2 position, float scale, Color tint); // Draw one character (codepoint)
|
|
if (vertical) {
|
|
//TODO: Wow, that is ugly!
|
|
int counter = 0;
|
|
char ch = finalPortName[counter];
|
|
Font defaultFont = GetFontDefault();
|
|
while (ch != '\0') {
|
|
DrawTextCodepoint(defaultFont, ch, (Vector2){ x, y+counter*(fontsize/1.5) }, 1.8f, color);
|
|
counter++;
|
|
ch = finalPortName[counter];
|
|
}
|
|
}
|
|
else {
|
|
// Horizontal Mode
|
|
DrawText(finalPortName, x, y, fontsize, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
float calculateCountdown(float countdown, float ft) {
|
|
float bpmFactor;
|
|
|
|
switch (programState.fadeOutMode) {
|
|
case 0: // framelegnth * user factor
|
|
if (countdown < 1.0f) { countdown -= (float)programState.fadeOutFactor * ft; } //note off has been triggered. Fade out.
|
|
if (countdown <= 0.0f) { countdown = 0; } // Is it now, or was already, below 0?
|
|
break;
|
|
|
|
case 1: // bpm
|
|
bpmFactor = (float)(programState.bpm/40);
|
|
if (countdown < 1.0f) { countdown -= bpmFactor * ft; } //note off has been triggered. Fade out.
|
|
if (countdown <= 0.0f) { countdown = 0.0f; } // Is it now, or was already, below 0?
|
|
break;
|
|
|
|
case 2: // no fadeout
|
|
if (countdown < 1.0f) { countdown = 0.0f; } // As soon as note off arrives
|
|
break;
|
|
|
|
default: //just in case
|
|
countdown = 0.0f;
|
|
break;
|
|
}
|
|
|
|
return countdown;
|
|
}
|
|
|
|
void reduceCountdown(Note * nt, float ft) {
|
|
//Notes countdown is set to 0 (note-off), 1 (note-on) or 0.999 (note-off) by our jack midi client.
|
|
|
|
float bpmFactor;
|
|
|
|
if (nt->active == 1) {
|
|
switch (programState.fadeOutMode) {
|
|
case 0: // framelegnth * user factor
|
|
if (nt->countdown < 1.0f) { nt->countdown -= (float)programState.fadeOutFactor * ft; } //note off has been triggered. Fade out.
|
|
if (nt->countdown <= 0.0f) { nt->active = false; } // Is it now, or was already, below 0?
|
|
break;
|
|
|
|
case 1: // bpm
|
|
bpmFactor = (float)(programState.bpm/40);
|
|
if (nt->countdown < 1.0f) { nt->countdown -= bpmFactor * ft; } //note off has been triggered. Fade out.
|
|
if (nt->countdown <= 0.0f) { nt->active = false; } // Is it now, or was already, below 0?
|
|
break;
|
|
|
|
case 2: // no fadeout
|
|
if (nt->countdown < 1.0f) { nt->active = false; } // As soon as note off arrives
|
|
break;
|
|
|
|
default: //just in case
|
|
nt->active = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|