2024-10-09 02:01:23 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* VISEQ - Visual Sequencer
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
/*Background: (46, 46, 46); #2e2e2e*/
|
|
|
|
|
/*Comments: (121, 121, 121); #797979*/
|
|
|
|
|
/*White: (214, 214, 214); #d6d6d6*/
|
|
|
|
|
/*Yellow: (229, 181, 103); #e5b567*/
|
|
|
|
|
/*Green: (180, 210, 115); #b4d273*/
|
|
|
|
|
/*Orange: (232, 125, 62); #e87d3e*/
|
|
|
|
|
/*Purple: (158, 134, 200); #9e86c8*/
|
|
|
|
|
/*Pink: (176, 82, 121); #b05279*/
|
|
|
|
|
/*Blue: (108, 153, 187); #6c99bb*/
|
|
|
|
|
|
2024-10-16 02:26:02 +02:00
|
|
|
#include "datatypes.h"
|
2024-10-22 01:55:31 +02:00
|
|
|
#include "signal-manager.h"
|
2024-10-20 01:17:18 +02:00
|
|
|
#include <format>
|
2024-10-23 03:25:57 +02:00
|
|
|
#include <ranges>
|
2024-10-13 04:22:09 +02:00
|
|
|
#include <raylib.h>
|
|
|
|
|
#include <raymath.h>
|
2024-10-22 03:07:11 +02:00
|
|
|
#include <string>
|
2024-10-13 04:22:09 +02:00
|
|
|
|
|
|
|
|
#define RAYGUI_IMPLEMENTATION
|
|
|
|
|
#include "raygui/raygui.h"
|
|
|
|
|
#include "raygui/dark/style_dark.h"
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
#include "midi.h"
|
2024-10-09 02:01:23 +02:00
|
|
|
#include "node.h"
|
2024-10-15 02:59:26 +02:00
|
|
|
|
|
|
|
|
#include "connection-manager.h"
|
2024-10-22 01:55:31 +02:00
|
|
|
#include "signal-manager.h"
|
|
|
|
|
|
|
|
|
|
AppState app;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
|
|
|
|
std::vector<Node> nodes;
|
2024-10-22 01:55:31 +02:00
|
|
|
|
2024-10-15 02:59:26 +02:00
|
|
|
ConnectionManager cm;
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-19 04:08:46 +02:00
|
|
|
Midi midi;
|
|
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
SignalManager sm(&app, &cm, &midi);
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
Vec2D<float> mouse_pos;
|
|
|
|
|
Vec2D<float> drag_start;
|
|
|
|
|
|
|
|
|
|
bool mouse_clicked = false;
|
|
|
|
|
bool mouse_touched = false;
|
2024-10-13 04:22:09 +02:00
|
|
|
bool mouse_dragging = false;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
int main(){
|
|
|
|
|
|
|
|
|
|
srand(time(NULL));
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
InitWindow(2560, 1440, "VISEQ");
|
|
|
|
|
|
|
|
|
|
GuiLoadStyleDark();
|
|
|
|
|
|
|
|
|
|
int monitor = 0; //GetCurrentMonitor();
|
|
|
|
|
|
|
|
|
|
SetWindowMonitor(monitor);
|
|
|
|
|
|
2024-10-23 03:25:57 +02:00
|
|
|
app.fps = 60.0f;
|
|
|
|
|
app.bpm = 120.0f;
|
|
|
|
|
app.grid = 120.0f; //round(((app.fps / (app.bpm / 60.0f)) * app.speed) / 4.0f); // from quarter notes to 16th notes = div by 4
|
|
|
|
|
// app.speed = round((((app.fps / (app.bpm / 60.0f)) / app.grid) / 4.0f) / 10.0f) * 10.0f;
|
|
|
|
|
|
|
|
|
|
app.speed = (app.grid * 4.0f) / (app.fps / (app.bpm / 60.0f));
|
2024-10-22 01:55:31 +02:00
|
|
|
|
|
|
|
|
// 120 fps
|
|
|
|
|
// 120bpm = 120 1/4 Noten pro Minute = 2 1/4 Noten / s
|
|
|
|
|
// 2px / frame bei 120fps = 240px / s = 14400 px / minute
|
|
|
|
|
// 1/4 Note / 120 pixel
|
|
|
|
|
// 1/16 Note alle 30 pixel
|
|
|
|
|
|
|
|
|
|
// 60 fps bei 120 bpm
|
|
|
|
|
// 2px / frame bei 60fps = 120px / s = 7200 px / minute
|
|
|
|
|
// 1/16 Note alle 15 pixel
|
|
|
|
|
// 1/8 Note alle 30 pixel
|
|
|
|
|
// 1/4 Note alle 60 pixel
|
|
|
|
|
// 1/2 Note alle 120 pixel
|
|
|
|
|
// 1/1 Note alle 240 pixel
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
app.width = GetMonitorWidth(monitor);
|
|
|
|
|
app.height = GetMonitorHeight(monitor);
|
|
|
|
|
|
2024-10-19 04:08:46 +02:00
|
|
|
Camera2D camera = { {0} };
|
2024-10-13 04:22:09 +02:00
|
|
|
camera.target = (Vector2){ app.width/2.0f, app.height/2.0f };
|
|
|
|
|
camera.offset = (Vector2){ app.width/2.0f, app.height/2.0f };
|
|
|
|
|
camera.rotation = 0.0f;
|
|
|
|
|
camera.zoom = 1.0f;
|
|
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
SetTargetFPS(app.fps);
|
2024-10-13 04:22:09 +02:00
|
|
|
|
|
|
|
|
ToggleFullscreen();
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
for(int i = 0; i < 4; ++i){
|
|
|
|
|
nodes.emplace(nodes.end(), Node((float)i * app.grid + 10 * app.grid, 5 * app.grid, 15.0f));
|
|
|
|
|
}
|
|
|
|
|
for(int i = 3; i >= 0; --i){
|
|
|
|
|
nodes.emplace(nodes.end(), Node((float)i * app.grid + 10 * app.grid, 6 * app.grid, 15.0f));
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
2024-10-22 01:55:31 +02:00
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
for(int i = 0; i < 8; ++i){
|
|
|
|
|
cm.addConnection(&nodes[i], &nodes[(i+1) % 8]);
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
sm.addSignalAtNode(&nodes.front());
|
2024-10-18 01:27:14 +02:00
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
sm.startSignalThread();
|
|
|
|
|
|
2024-10-13 15:07:19 +02:00
|
|
|
Vec2D<float> drag_offset;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-10-20 23:42:38 +02:00
|
|
|
Vec2D<float> cam_drag_offset;
|
|
|
|
|
Vec2D<float> cam_mouse_drag_offset;
|
|
|
|
|
|
2024-10-16 02:26:02 +02:00
|
|
|
Node* connecting_from = nullptr;
|
|
|
|
|
|
|
|
|
|
double drag_timer = GetTime();
|
|
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
Vec2D<float> select_start;
|
|
|
|
|
Rectangle selection;
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
while(!WindowShouldClose()){
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-10-23 03:25:57 +02:00
|
|
|
//app.grid = round(((app.fps / (app.bpm / 60.0f)) * app.speed) / 4.0f); // from quarter notes to 16th notes = div by 4
|
|
|
|
|
app.speed = (app.grid * 4.0f) / (app.fps / (app.bpm / 60.0f));
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
Vector2 mp = GetScreenToWorld2D(GetMousePosition(), camera);
|
2024-10-10 02:59:27 +02:00
|
|
|
Vec2D<float> mouse_pos = {(float)mp.x, (float)mp.y};
|
2024-10-20 23:42:38 +02:00
|
|
|
Vec2D<float> cam_pos = {camera.offset.x, camera.offset.y};
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
bool mouse_down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
|
|
|
|
|
bool mouse_clicked = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
|
|
|
|
bool mouse_released = IsMouseButtonReleased(MOUSE_BUTTON_LEFT);
|
2024-10-10 02:59:27 +02:00
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
if(IsMouseButtonDown(MOUSE_BUTTON_RIGHT)){
|
2024-10-20 23:42:38 +02:00
|
|
|
Vector2 delta = GetMouseDelta();
|
|
|
|
|
delta = Vector2Scale(delta, -1.0f/camera.zoom);
|
|
|
|
|
camera.target = Vector2Add(camera.target, delta);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float wheel = GetMouseWheelMove();
|
2024-10-23 00:23:24 +02:00
|
|
|
if(wheel != 0){
|
2024-10-20 23:42:38 +02:00
|
|
|
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
|
|
|
|
camera.offset = GetMousePosition();
|
|
|
|
|
camera.target = mouseWorldPos;
|
|
|
|
|
float scaleFactor = 1.0f + (0.25f*fabsf(wheel));
|
|
|
|
|
if (wheel < 0) scaleFactor = 1.0f/scaleFactor;
|
|
|
|
|
camera.zoom = Clamp(camera.zoom*scaleFactor, 0.125f, 64.0f);
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
if(mouse_clicked){
|
2024-10-10 02:59:27 +02:00
|
|
|
drag_start = mouse_pos;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
BeginDrawing();
|
2024-10-22 01:55:31 +02:00
|
|
|
DrawFPS(app.width - 300, 50);
|
2024-10-13 04:22:09 +02:00
|
|
|
ClearBackground((Color){46,46,46});
|
|
|
|
|
|
|
|
|
|
BeginMode2D(camera);
|
2024-10-16 02:26:02 +02:00
|
|
|
bool connecting = false;
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
for(int x = -app.grid*100; x < app.grid*100; x+=app.grid){
|
|
|
|
|
for(int y = -app.grid*100; y < app.grid*100; y+=app.grid){
|
2024-10-23 00:23:24 +02:00
|
|
|
DrawPixel(x, y, (Color){130,130,130,200});
|
2024-10-20 23:42:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 03:25:57 +02:00
|
|
|
for(auto &n : nodes){
|
|
|
|
|
n.hovering = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto dragging_nodes = nodes | std::ranges::views::filter([](Node n) { return n.dragging;});
|
|
|
|
|
|
|
|
|
|
if(dragging_nodes.empty()) {
|
|
|
|
|
auto hovering_nodes = nodes | std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, n.position, n.radius);});
|
|
|
|
|
|
|
|
|
|
if(hovering_nodes.empty() || selection.width > 0){
|
|
|
|
|
if(mouse_clicked){
|
|
|
|
|
select_start = mouse_pos;
|
|
|
|
|
for(auto &n : nodes){
|
|
|
|
|
n.selected = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(mouse_down){
|
|
|
|
|
Vec2D<float> select1 = {mouse_pos.x > select_start.x ? select_start.x : mouse_pos.x, mouse_pos.y > select_start.y ? select_start.y : mouse_pos.y};
|
|
|
|
|
Vec2D<float> select2 = {mouse_pos.x > select_start.x ? mouse_pos.x - select_start.x : select_start.x - mouse_pos.x, mouse_pos.y > select_start.y ? mouse_pos.y - select_start.y : select_start.y - mouse_pos.y};
|
|
|
|
|
DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150});
|
|
|
|
|
selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};
|
|
|
|
|
|
|
|
|
|
for(auto& n : nodes){
|
|
|
|
|
if(CheckCollisionPointRec(n.position, selection)) {
|
|
|
|
|
n.in_rect = true;
|
|
|
|
|
} else {
|
|
|
|
|
n.in_rect = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(mouse_released){
|
|
|
|
|
for(auto& n : nodes){
|
|
|
|
|
if(CheckCollisionPointRec(n.position, selection)) {
|
|
|
|
|
n.selected = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
selection = (Rectangle){0,0,0,0};
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
hovering_nodes.front().hovering = true;
|
|
|
|
|
if(selection.width == 0.0f){
|
|
|
|
|
if(mouse_clicked){
|
|
|
|
|
drag_timer = GetTime();
|
|
|
|
|
}
|
|
|
|
|
if(mouse_down && GetTime() - drag_timer > 0.07){
|
|
|
|
|
hovering_nodes.front().drag_offset = hovering_nodes.front().position - mouse_pos;
|
|
|
|
|
hovering_nodes.front().dragging = true;
|
|
|
|
|
}
|
|
|
|
|
if(mouse_released && GetTime() - drag_timer <= 0.07){
|
|
|
|
|
hovering_nodes.front().config = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-23 00:23:24 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-23 03:25:57 +02:00
|
|
|
} else {
|
|
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
if(mouse_down){
|
2024-10-23 03:25:57 +02:00
|
|
|
if(IsKeyDown(KEY_LEFT_CONTROL)) {
|
|
|
|
|
dragging_nodes.front().position = (Vec2D<float>){round((mouse_pos.x+dragging_nodes.front().drag_offset.x)/app.grid)*app.grid, round((mouse_pos.y+dragging_nodes.front().drag_offset.y)/app.grid)*app.grid};
|
|
|
|
|
} else {
|
|
|
|
|
dragging_nodes.front().position = mouse_pos + dragging_nodes.front().drag_offset;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(mouse_released) {
|
|
|
|
|
dragging_nodes.front().dragging = false;
|
2024-10-23 00:23:24 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-23 03:25:57 +02:00
|
|
|
auto selected_nodes = nodes | std::ranges::views::filter([](Node n) { return n.selected && !n.dragging;});
|
|
|
|
|
if(!selected_nodes.empty() && mouse_down){
|
|
|
|
|
for(auto &n : selected_nodes){
|
|
|
|
|
if(!n.picked_up) n.drag_offset = n.position - dragging_nodes.front().position;
|
|
|
|
|
n.picked_up = true;
|
|
|
|
|
n.position = dragging_nodes.front().position + n.drag_offset;
|
2024-10-23 00:23:24 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-23 03:25:57 +02:00
|
|
|
if(mouse_released) {
|
|
|
|
|
dragging_nodes.front().dragging = false;
|
|
|
|
|
for(auto &n : selected_nodes){
|
|
|
|
|
n.picked_up = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-23 00:23:24 +02:00
|
|
|
}
|
2024-10-23 03:25:57 +02:00
|
|
|
|
2024-10-13 15:07:19 +02:00
|
|
|
for(auto& n : nodes){
|
2024-10-18 01:27:14 +02:00
|
|
|
Vec2D<float> connector_position = n.position - ((n.position - mouse_pos)).norm() * (n.radius + 14.0f);
|
2024-10-13 04:22:09 +02:00
|
|
|
float dist_connector = (connector_position - mouse_pos).length();
|
|
|
|
|
|
|
|
|
|
float dist = (n.position - mouse_pos).length();
|
2024-10-13 15:07:19 +02:00
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
// connect nodes
|
|
|
|
|
if( (dist <= n.radius + 25.0f && dist > n.radius) || n.connecting){
|
|
|
|
|
n.hover_connect = true;
|
|
|
|
|
} else {
|
|
|
|
|
n.hover_connect = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-18 01:27:14 +02:00
|
|
|
if(dist_connector <= 8.0f && mouse_clicked && !connecting) {
|
2024-10-13 04:22:09 +02:00
|
|
|
connecting_from = &n;
|
|
|
|
|
n.connecting = true;
|
2024-10-16 02:26:02 +02:00
|
|
|
connecting = true;
|
2024-10-13 04:22:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(n.connecting && mouse_down){
|
|
|
|
|
DrawLine(connector_position.x, connector_position.y, mouse_pos.x, mouse_pos.y, (Color){229, 181, 103, 255});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(mouse_released && n.connecting) {
|
|
|
|
|
n.connecting = false;
|
2024-10-16 02:26:02 +02:00
|
|
|
//connecting_from = nullptr;
|
2024-10-13 04:22:09 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-23 03:25:57 +02:00
|
|
|
if(mouse_released && (n.hover_connect || n.dragging)) {
|
2024-10-15 02:59:26 +02:00
|
|
|
if(&n != connecting_from && connecting_from != nullptr){
|
2024-10-23 00:23:24 +02:00
|
|
|
cm.addConnection(connecting_from, &n);
|
2024-10-15 02:59:26 +02:00
|
|
|
connecting_from = nullptr;
|
2024-10-13 15:07:19 +02:00
|
|
|
}
|
2024-10-13 04:22:09 +02:00
|
|
|
}
|
2024-10-20 23:42:38 +02:00
|
|
|
n.draw(&mouse_pos, &camera);
|
2024-10-13 04:22:09 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-22 01:55:31 +02:00
|
|
|
cm.drawConnections(&mouse_pos, &camera);
|
|
|
|
|
sm.drawSignals(&mouse_pos, &camera);
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-19 17:41:31 +02:00
|
|
|
midi.update();
|
2024-10-13 04:22:09 +02:00
|
|
|
EndMode2D();
|
2024-10-19 17:41:31 +02:00
|
|
|
|
|
|
|
|
// Main Config Window
|
|
|
|
|
GuiWindowBox((Rectangle){0,0,280,(float)app.height}, "config");
|
2024-10-22 03:07:11 +02:00
|
|
|
{
|
|
|
|
|
const int s_bpm = 55;
|
|
|
|
|
GuiLabel((Rectangle){20, (float)s_bpm, 120, 20}, "TIMING");
|
|
|
|
|
GuiLabel((Rectangle){200, (float)s_bpm, 40, 20}, std::format("{}",app.bpm).c_str());
|
|
|
|
|
float _bpm = (float)app.bpm;
|
|
|
|
|
GuiSlider((Rectangle){20, (float)s_bpm + 25, 240, 20}, "", "", &_bpm, 1, 300);
|
|
|
|
|
app.bpm = _bpm;
|
|
|
|
|
|
|
|
|
|
int s_midi = 100;
|
|
|
|
|
GuiLabel((Rectangle){20, (float)s_midi, 240, 20}, "MIDI OUT");
|
2024-10-19 17:41:31 +02:00
|
|
|
int i = 0;
|
|
|
|
|
for(auto& mo : midi.midi_out_ports){
|
2024-10-22 03:07:11 +02:00
|
|
|
GuiCheckBox((Rectangle){20, (float)s_midi + 25 + i*20.0f, 20, 20}, mo.port.port_name.c_str(), &mo.enabled);
|
2024-10-19 17:41:31 +02:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-22 03:07:11 +02:00
|
|
|
if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) {
|
2024-10-20 23:42:38 +02:00
|
|
|
for(auto &midis : midi.midi_out_ports){
|
|
|
|
|
if(midis.enabled){
|
|
|
|
|
for(auto &n : nodes){
|
|
|
|
|
n.midi_outs[midis.number].enabled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-22 03:07:11 +02:00
|
|
|
|
|
|
|
|
int s_signal = s_midi + 90 + i*20;
|
|
|
|
|
GuiLabel((Rectangle){20, (float)s_signal, 240, 20}, "SIGNALS");
|
|
|
|
|
if(GuiButton((Rectangle){20, (float)s_signal + 35, 240, 20}, "ADD RANDOM SIGNAL")){
|
2024-10-20 23:42:38 +02:00
|
|
|
int ni = rand() % nodes.size();
|
2024-10-22 01:55:31 +02:00
|
|
|
sm.addSignalAtNode(&nodes[ni]);
|
2024-10-20 23:42:38 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-22 03:07:11 +02:00
|
|
|
int signal_configs = 0;
|
|
|
|
|
for(auto &s : sm.signals){
|
|
|
|
|
if(GuiButton((Rectangle){20,(float)s_signal+70 + signal_configs*20, 20, 20},"X")) sm.removeSignal(signal_configs);
|
|
|
|
|
DrawCircle(55, s_signal+80 + signal_configs*20, 6.0F, s.color);
|
|
|
|
|
float s_speed = round(s.speed*10.0f)/10.0f;
|
|
|
|
|
float signal_bpm = (app.bpm / app.speed) * s_speed;
|
|
|
|
|
GuiSlider((Rectangle){70, (float)s_signal+70 + signal_configs*20, 160, 20}, "", std::format("{:.1f}",signal_bpm).c_str(), &s_speed, 0.1, 24);
|
|
|
|
|
s.speed = s_speed;
|
|
|
|
|
signal_configs++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int s_nodes = s_signal + 60 + signal_configs*20;
|
|
|
|
|
GuiLabel((Rectangle){20, (float)s_nodes + 30, 240, 20}, "NODES");
|
|
|
|
|
if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){
|
2024-10-23 03:25:57 +02:00
|
|
|
nodes.emplace_back(Node(200.0f, 200.0f, 15.0f));
|
2024-10-19 17:41:31 +02:00
|
|
|
}
|
2024-10-22 03:07:11 +02:00
|
|
|
|
|
|
|
|
|
2024-10-16 02:26:02 +02:00
|
|
|
}
|
2024-10-19 17:41:31 +02:00
|
|
|
|
2024-10-20 23:42:38 +02:00
|
|
|
// Per Node Config Windows
|
2024-10-16 02:26:02 +02:00
|
|
|
for(auto& n : nodes){
|
2024-10-20 23:42:38 +02:00
|
|
|
Vector2 np = GetWorldToScreen2D((Vector2){n.position.x, n.position.y}, camera);
|
|
|
|
|
|
|
|
|
|
for(auto& mo : midi.midi_out_ports){
|
|
|
|
|
if(!n.midi_outs.contains(mo.number) && mo.enabled){
|
|
|
|
|
n.midi_outs[mo.number] = {mo.number, mo.port.port_name, false};
|
|
|
|
|
}
|
|
|
|
|
if(n.midi_outs.contains(mo.number) && !mo.enabled){
|
|
|
|
|
n.midi_outs.erase(mo.number);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-16 02:26:02 +02:00
|
|
|
if(n.config){
|
2024-10-20 23:42:38 +02:00
|
|
|
n.config = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config");
|
|
|
|
|
|
2024-10-16 02:26:02 +02:00
|
|
|
int option = n.mode;
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 110, 20 }, "Round Robin;Random", &option);
|
2024-10-16 02:26:02 +02:00
|
|
|
n.mode = (Distribution)option;
|
2024-10-20 23:42:38 +02:00
|
|
|
|
|
|
|
|
GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS");
|
|
|
|
|
if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){
|
2024-10-22 01:55:31 +02:00
|
|
|
sm.addSignalAtNode(&n);
|
2024-10-19 17:41:31 +02:00
|
|
|
}
|
2024-10-20 23:42:38 +02:00
|
|
|
|
|
|
|
|
int y_midi = 120;
|
|
|
|
|
GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT");
|
|
|
|
|
|
2024-10-20 01:17:18 +02:00
|
|
|
int i = 0;
|
|
|
|
|
for(auto& mo : n.midi_outs){
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiCheckBox((Rectangle){np.x + 20, np.y + y_midi + 20 + i*20.0f, 20, 20}, mo.second.name.c_str(), &mo.second.enabled);
|
2024-10-20 01:17:18 +02:00
|
|
|
i++;
|
2024-10-19 04:08:46 +02:00
|
|
|
}
|
2024-10-20 01:17:18 +02:00
|
|
|
|
2024-10-20 23:42:38 +02:00
|
|
|
int y_channel = y_midi + 30 + i*20;
|
|
|
|
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel, 220, 20}, "CHANNEL");
|
|
|
|
|
GuiToggleGroup((Rectangle){np.x + 20, np.y + y_channel + 30, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &n.midi_channel);
|
2024-10-20 02:01:30 +02:00
|
|
|
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 90, 100, 20}, "NOTE");
|
2024-10-20 02:01:30 +02:00
|
|
|
float v = n.midi_note;
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 90, 20, 20}, midi.midiNotes[(int)round(v)].c_str());
|
|
|
|
|
GuiLabel((Rectangle){np.x + 160, np.y + y_channel + 90, 40, 20}, std::format("{}",n.midi_note).c_str());
|
|
|
|
|
GuiSlider((Rectangle){np.x + 20, np.y + y_channel + 120, 220, 20}, "", "", &v, 0, 127);
|
2024-10-20 02:01:30 +02:00
|
|
|
n.midi_note = round(v);
|
|
|
|
|
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 150, 100, 20}, "VELOCITY");
|
2024-10-20 02:01:30 +02:00
|
|
|
v = n.midi_velocity;
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 150, 20, 20}, std::format("{}",n.midi_velocity).c_str());
|
|
|
|
|
GuiSlider((Rectangle){np.x + 20, np.y + y_channel + 180, 220, 20}, "", "", &v, 0, 127);
|
2024-10-20 02:01:30 +02:00
|
|
|
n.midi_velocity = round(v);
|
2024-10-20 01:17:18 +02:00
|
|
|
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 210, 100, 20}, "GATE");
|
2024-10-20 02:01:30 +02:00
|
|
|
v = n.midi_gate;
|
2024-10-20 23:42:38 +02:00
|
|
|
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 210, 20, 20}, std::format("{}",(float)n.midi_gate/1000.0f).c_str());
|
|
|
|
|
GuiSlider((Rectangle){np.x + 20, np.y + y_channel + 240, 220, 20}, "", "", &v, 0, 5000);
|
2024-10-20 02:01:30 +02:00
|
|
|
n.midi_gate = round(v);
|
2024-10-20 01:17:18 +02:00
|
|
|
|
2024-10-20 02:01:30 +02:00
|
|
|
//if(GuiValueBox((Rectangle){n.position.x + 100, n.position.y + y_channel + 40, 140, 20}, "VELOCITY", &n.midi_velocity, 0, 127, n.gui_midi_velocity_edit)) n.gui_midi_velocity_edit = !n.gui_midi_velocity_edit;
|
|
|
|
|
//if(GuiValueBox((Rectangle){n.position.x + 100, n.position.y + y_channel + 60, 140, 20}, "GATE", &n.midi_gate, 0, 5000, n.gui_midi_gate_edit)) n.gui_midi_gate_edit = !n.gui_midi_gate_edit;
|
2024-10-18 01:27:14 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto& c : cm.connections){
|
|
|
|
|
if(c.config){
|
|
|
|
|
Vec2D<float> config_handle = c.v2->position - ((c.v2->position - c.v1->position))*0.75f;
|
|
|
|
|
c.config = !GuiWindowBox((Rectangle){config_handle.x + 10, config_handle.y + 10, 200, 300}, "connection");
|
|
|
|
|
GuiToggle((Rectangle){config_handle.x + 10, config_handle.y + 50, 80, 20}, "v1v2", &c.v1_v2);
|
|
|
|
|
GuiToggle((Rectangle){config_handle.x + 100, config_handle.y + 50, 80, 20}, "v2v1", &c.v2_v1);
|
|
|
|
|
|
2024-10-16 02:26:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-13 04:22:09 +02:00
|
|
|
|
|
|
|
|
EndDrawing();
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
CloseWindow();
|
|
|
|
|
|
|
|
|
|
return 0;
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-10 02:59:27 +02:00
|
|
|
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
|