refactored main a bit
This commit is contained in:
+4
-6
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
//#include "connection-manager.h"
|
||||||
|
//#include "signal-manager.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#endif
|
#endif
|
||||||
@@ -133,11 +135,8 @@ Vec2D<T> operator*(const Vec2D<T>& left, T scalar){
|
|||||||
return Vec2D<T>(left.x * scalar, left.y * scalar);
|
return Vec2D<T>(left.x * scalar, left.y * scalar);
|
||||||
};
|
};
|
||||||
|
|
||||||
// State
|
// App Settings
|
||||||
|
struct AppSettings{
|
||||||
enum States {IDLE, CONFIG};
|
|
||||||
|
|
||||||
struct AppState{
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
float grid;
|
float grid;
|
||||||
@@ -145,7 +144,6 @@ struct AppState{
|
|||||||
float fps;
|
float fps;
|
||||||
float speed = 16.0f;
|
float speed = 16.0f;
|
||||||
int gui_selected_midi_out;
|
int gui_selected_midi_out;
|
||||||
States state;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// MIDI
|
// MIDI
|
||||||
|
|||||||
+180
-215
@@ -16,48 +16,31 @@
|
|||||||
/*Pink: (176, 82, 121); #b05279*/
|
/*Pink: (176, 82, 121); #b05279*/
|
||||||
/*Blue: (108, 153, 187); #6c99bb*/
|
/*Blue: (108, 153, 187); #6c99bb*/
|
||||||
|
|
||||||
|
#define RAYGUI_IMPLEMENTATION
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "signal-manager.h"
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
#include <raymath.h>
|
#include <raymath.h>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define RAYGUI_IMPLEMENTATION
|
|
||||||
#include "raygui/raygui.h"
|
|
||||||
#include "raygui/dark/style_dark.h"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "state-manager.h"
|
||||||
#include "midi.h"
|
|
||||||
#include "node.h"
|
|
||||||
|
|
||||||
#include "connection-manager.h"
|
|
||||||
#include "signal-manager.h"
|
|
||||||
|
|
||||||
AppState app;
|
AppState app;
|
||||||
|
|
||||||
std::vector<Node> nodes;
|
|
||||||
|
|
||||||
ConnectionManager cm;
|
|
||||||
|
|
||||||
Midi midi;
|
|
||||||
|
|
||||||
SignalManager sm(&app, &cm, &midi);
|
|
||||||
|
|
||||||
Vec2D<float> mouse_pos;
|
Vec2D<float> mouse_pos;
|
||||||
Vec2D<float> drag_start;
|
Vec2D<float> drag_start;
|
||||||
|
|
||||||
|
Camera2D camera = { {0} };
|
||||||
|
|
||||||
bool mouse_clicked = false;
|
bool mouse_clicked = false;
|
||||||
bool mouse_touched = false;
|
bool mouse_touched = false;
|
||||||
bool mouse_dragging = false;
|
bool mouse_dragging = false;
|
||||||
|
|
||||||
|
//#include "ui.h"
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
|
|
||||||
@@ -65,64 +48,47 @@ int main(){
|
|||||||
|
|
||||||
InitWindow(2560, 1440, "VISEQ");
|
InitWindow(2560, 1440, "VISEQ");
|
||||||
|
|
||||||
GuiLoadStyleDark();
|
app.ui.init();
|
||||||
|
|
||||||
int monitor = 0; //GetCurrentMonitor();
|
int monitor = 0; //GetCurrentMonitor();
|
||||||
|
|
||||||
SetWindowMonitor(monitor);
|
SetWindowMonitor(monitor);
|
||||||
|
|
||||||
app.fps = 1.0f;
|
app.settings.fps = 1.0f;
|
||||||
app.bpm = 120.0f;
|
app.settings.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.settings.grid = 120.0f; //round(((app.settings.fps / (app.settings.bpm / 60.0f)) * app.settings.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.settings.speed = round((((app.settings.fps / (app.settings.bpm / 60.0f)) / app.settings.grid) / 4.0f) / 10.0f) * 10.0f;
|
||||||
|
|
||||||
// 16th note = 120px (festgelegt)
|
// 16th note = 120px (festgelegt)
|
||||||
// ganze note = 1920px
|
// ganze note = 1920px
|
||||||
// ganze note bei 120bpm = 2s
|
// ganze note bei 120bpm = 2s
|
||||||
// 120bpm = 960px/s
|
// 120bpm = 960px/s
|
||||||
app.speed = (app.grid * 8.0f) * (120.0f / app.bpm);
|
app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f);
|
||||||
|
|
||||||
// 120 fps
|
app.settings.width = GetMonitorWidth(monitor);
|
||||||
// 120bpm = 120 1/4 Noten pro Minute = 2 1/4 Noten / s
|
app.settings.height = GetMonitorHeight(monitor);
|
||||||
// 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
|
|
||||||
|
|
||||||
app.width = GetMonitorWidth(monitor);
|
|
||||||
app.height = GetMonitorHeight(monitor);
|
|
||||||
|
|
||||||
SetTargetFPS(60.0f);
|
SetTargetFPS(60.0f);
|
||||||
|
|
||||||
Camera2D camera = { {0} };
|
camera.target = (Vector2){ app.settings.width/2.0f, app.settings.height/2.0f };
|
||||||
camera.target = (Vector2){ app.width/2.0f, app.height/2.0f };
|
camera.offset = (Vector2){ app.settings.width/2.0f, app.settings.height/2.0f };
|
||||||
camera.offset = (Vector2){ app.width/2.0f, app.height/2.0f };
|
|
||||||
camera.rotation = 0.0f;
|
camera.rotation = 0.0f;
|
||||||
camera.zoom = 1.0f;
|
camera.zoom = 1.0f;
|
||||||
|
|
||||||
nodes.reserve(1000);
|
|
||||||
|
|
||||||
for(int i = 0; i < 4; ++i){
|
for(int i = 0; i < 4; ++i){
|
||||||
nodes.emplace_back((float)i * app.grid + 10 * app.grid, 5 * app.grid, 15.0f);
|
app.nm.addNode((float)i * app.settings.grid + 10 * app.settings.grid, 5 * app.settings.grid);
|
||||||
}
|
}
|
||||||
for(int i = 3; i >= 0; --i){
|
for(int i = 3; i >= 0; --i){
|
||||||
nodes.emplace_back((float)i * app.grid + 10 * app.grid, 6 * app.grid, 15.0f);
|
app.nm.addNode((float)i * app.settings.grid + 10 * app.settings.grid, 6 * app.settings.grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 8; ++i){
|
for(int i = 0; i < 8; ++i){
|
||||||
cm.addConnection(&nodes[i], &nodes[(i+1) % 8]);
|
app.cm.addConnection(&app.nm.nodes[i], &app.nm.nodes[(i+1) % 8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sm.addSignalAtNode(&nodes.front());
|
app.sm.addSignalAtNode(&app.nm.nodes.front());
|
||||||
|
|
||||||
sm.startSignalThread();
|
app.sm.startSignalThread();
|
||||||
|
|
||||||
Vec2D<float> drag_offset;
|
Vec2D<float> drag_offset;
|
||||||
|
|
||||||
@@ -144,9 +110,8 @@ int main(){
|
|||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground((Color){46,46,46});
|
ClearBackground((Color){46,46,46});
|
||||||
BeginMode2D(camera);
|
BeginMode2D(camera);
|
||||||
|
//app.settings.mutex.lock();
|
||||||
//app.grid = round(((app.fps / (app.bpm / 60.0f)) * app.speed) / 4.0f); // from quarter notes to 16th notes = div by 4
|
app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f);
|
||||||
app.speed = (app.grid * 8.0f) * (120.0f / app.bpm);
|
|
||||||
|
|
||||||
Vector2 mp = GetScreenToWorld2D(GetMousePosition(), camera);
|
Vector2 mp = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||||
Vec2D<float> mouse_pos = {(float)mp.x, (float)mp.y};
|
Vec2D<float> mouse_pos = {(float)mp.x, (float)mp.y};
|
||||||
@@ -163,11 +128,11 @@ int main(){
|
|||||||
Vec2D<float> mouse_delta = {GetMouseDelta().x, GetMouseDelta().y};
|
Vec2D<float> mouse_delta = {GetMouseDelta().x, GetMouseDelta().y};
|
||||||
Vec2D<float> delta = mouse_delta * (-1.0f/camera.zoom);
|
Vec2D<float> delta = mouse_delta * (-1.0f/camera.zoom);
|
||||||
|
|
||||||
auto dragging_nodes = nodes | std::ranges::views::filter([](Node n) { return n.dragging;});
|
auto dragging_nodes = app.nm.nodes | std::ranges::views::filter([](Node n) { return n.dragging;});
|
||||||
auto connecting_nodes = nodes | std::ranges::views::filter([](Node n) { return n.connecting;});
|
auto connecting_nodes = app.nm.nodes | std::ranges::views::filter([](Node n) { return n.connecting;});
|
||||||
auto selected_nodes = nodes | std::ranges::views::filter([](Node n) { return n.selected && !n.dragging;});
|
auto selected_nodes = app.nm.nodes | std::ranges::views::filter([](Node n) { return n.selected && !n.dragging;});
|
||||||
auto hovering_nodes = nodes | std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, n.position, n.radius);});
|
auto hovering_nodes = app.nm.nodes | std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, n.position, n.radius);});
|
||||||
auto hovering_connectors = nodes | std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, (n.position - ((n.position - mouse_pos)).norm() * (n.radius + 14.0f)), 8.0f);});
|
auto hovering_connectors = app.nm.nodes | std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, (n.position - ((n.position - mouse_pos)).norm() * (n.radius + 14.0f)), 8.0f);});
|
||||||
|
|
||||||
if(!mouse_down && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::HOVER_CANVAS;
|
if(!mouse_down && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::HOVER_CANVAS;
|
||||||
if((mouse_clicked || mouse_down || mouse_released) && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::DRAW_SELECTION;
|
if((mouse_clicked || mouse_down || mouse_released) && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::DRAW_SELECTION;
|
||||||
@@ -193,7 +158,7 @@ int main(){
|
|||||||
DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150});
|
DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150});
|
||||||
selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};
|
selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};
|
||||||
|
|
||||||
for(auto& n : nodes){
|
for(auto& n : app.nm.nodes){
|
||||||
if(CheckCollisionPointRec(n.position, selection)) {
|
if(CheckCollisionPointRec(n.position, selection)) {
|
||||||
n.in_rect = true;
|
n.in_rect = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -203,7 +168,7 @@ int main(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mouse_released){
|
if(mouse_released){
|
||||||
for(auto& n : nodes){
|
for(auto& n : app.nm.nodes){
|
||||||
if(CheckCollisionPointRec(n.position, selection)) {
|
if(CheckCollisionPointRec(n.position, selection)) {
|
||||||
n.selected = true;
|
n.selected = true;
|
||||||
n.in_rect = false;
|
n.in_rect = false;
|
||||||
@@ -227,7 +192,7 @@ int main(){
|
|||||||
break;
|
break;
|
||||||
case InteractionState::DRAG_NODE:
|
case InteractionState::DRAG_NODE:
|
||||||
if(IsKeyDown(KEY_LEFT_CONTROL)) {
|
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};
|
dragging_nodes.front().position = (Vec2D<float>){round((mouse_pos.x+dragging_nodes.front().drag_offset.x)/app.settings.grid)*app.settings.grid, round((mouse_pos.y+dragging_nodes.front().drag_offset.y)/app.settings.grid)*app.settings.grid};
|
||||||
} else {
|
} else {
|
||||||
dragging_nodes.front().position = mouse_pos + dragging_nodes.front().drag_offset;
|
dragging_nodes.front().position = mouse_pos + dragging_nodes.front().drag_offset;
|
||||||
}
|
}
|
||||||
@@ -256,13 +221,15 @@ int main(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mouse_released) {
|
if(mouse_released) {
|
||||||
|
if(&hovering_nodes.front() != &connecting_nodes.front() && &connecting_nodes.front() != &hovering_connectors.front()){
|
||||||
if(!hovering_nodes.empty()){
|
if(!hovering_nodes.empty()){
|
||||||
cm.addConnection(&connecting_nodes.front(), &hovering_nodes.front());
|
app.cm.addConnection(&connecting_nodes.front(), &hovering_nodes.front());
|
||||||
} else if(!hovering_connectors.empty()){
|
} else if(!hovering_connectors.empty()){
|
||||||
cm.addConnection(&connecting_nodes.front(), &hovering_connectors.front());
|
app.cm.addConnection(&connecting_nodes.front(), &hovering_connectors.front());
|
||||||
} else {
|
} else {
|
||||||
nodes.emplace_back(mouse_pos.x, mouse_pos.y, 15.0f);
|
app.nm.addNode(mouse_pos.x, mouse_pos.y);
|
||||||
cm.addConnection(&connecting_nodes.front(), &nodes.back());
|
app.cm.addConnection(&connecting_nodes.front(), &app.nm.nodes.back());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
connecting_nodes.front().connecting = false;
|
connecting_nodes.front().connecting = false;
|
||||||
}
|
}
|
||||||
@@ -273,8 +240,8 @@ int main(){
|
|||||||
if(wheel != 0){
|
if(wheel != 0){
|
||||||
if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL)){
|
if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL)){
|
||||||
hovering_nodes.front().midi_note += wheel;
|
hovering_nodes.front().midi_note += wheel;
|
||||||
if(hovering_nodes.front().midi_note < 0 ) hovering_nodes.front().midi_note = midi.midiNotes.size()-1;
|
if(hovering_nodes.front().midi_note < 0 ) hovering_nodes.front().midi_note = app.sm.midi.midiNotes.size()-1;
|
||||||
if(hovering_nodes.front().midi_note >= midi.midiNotes.size() ) hovering_nodes.front().midi_note = 0;
|
if(hovering_nodes.front().midi_note >= app.sm.midi.midiNotes.size() ) hovering_nodes.front().midi_note = 0;
|
||||||
} else {
|
} else {
|
||||||
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
|
||||||
camera.offset = GetMousePosition();
|
camera.offset = GetMousePosition();
|
||||||
@@ -285,154 +252,18 @@ int main(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int x = -app.grid*100; x < app.grid*100; x+=app.grid){
|
for(int x = -app.settings.grid*100; x < app.settings.grid*100; x+=app.settings.grid){
|
||||||
for(int y = -app.grid*100; y < app.grid*100; y+=app.grid){
|
for(int y = -app.settings.grid*100; y < app.settings.grid*100; y+=app.settings.grid){
|
||||||
DrawPixel(x, y, (Color){130,130,130,200});
|
DrawPixel(x, y, (Color){130,130,130,200});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& n : nodes){
|
|
||||||
n.draw(&mouse_pos, &camera);
|
|
||||||
}
|
|
||||||
|
|
||||||
cm.drawConnections(&mouse_pos, &camera);
|
app.draw(&mouse_pos, &camera);
|
||||||
sm.drawSignals(&mouse_pos, &camera);
|
|
||||||
|
|
||||||
midi.update();
|
|
||||||
|
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
|
|
||||||
// Main Config Window
|
app.drawUI(&mouse_pos, &camera);
|
||||||
GuiWindowBox((Rectangle){0,0,280,(float)app.height}, "config");
|
|
||||||
{
|
|
||||||
const int s_controls = 55;
|
|
||||||
if(GuiButton((Rectangle){20, (float)s_controls, 60, 30}, "PLAY")) sm.play ? sm.pause() : sm.start();
|
|
||||||
if(GuiButton((Rectangle){100, (float)s_controls, 60, 30}, "STOP")) sm.stop();
|
|
||||||
if(GuiButton((Rectangle){180, (float)s_controls, 60, 30}, "RESET")) sm.reset();
|
|
||||||
|
|
||||||
const int s_bpm = s_controls + 35;
|
|
||||||
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 = s_bpm + 55;
|
|
||||||
GuiLabel((Rectangle){20, (float)s_midi, 240, 20}, "MIDI OUT");
|
|
||||||
int i = 0;
|
|
||||||
for(auto& mo : midi.midi_out_ports){
|
|
||||||
GuiCheckBox((Rectangle){20, (float)s_midi + 25 + i*20.0f, 20, 20}, mo.port.port_name.c_str(), &mo.enabled);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) {
|
|
||||||
for(auto &midis : midi.midi_out_ports){
|
|
||||||
if(midis.enabled){
|
|
||||||
for(auto &n : nodes){
|
|
||||||
n.midi_outs[midis.number].enabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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")){
|
|
||||||
int ni = rand() % nodes.size();
|
|
||||||
sm.addSignalAtNode(&nodes[ni]);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_multiplier = round(s.multiplier*10.0f)/10.0f;
|
|
||||||
float signal_bpm = app.bpm * s.multiplier;
|
|
||||||
GuiSlider((Rectangle){70, (float)s_signal+70 + signal_configs*20, 160, 20}, "", std::format("{:.1f}",signal_bpm).c_str(), &s_multiplier, 0.1, 2);
|
|
||||||
s.multiplier = s_multiplier;
|
|
||||||
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")){
|
|
||||||
nodes.emplace_back(200.0f, 200.0f, 15.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawFPS(20, app.height - 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per Node Config Windows
|
|
||||||
for(auto& n : nodes){
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(n.config){
|
|
||||||
n.config = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config");
|
|
||||||
|
|
||||||
int option = n.mode;
|
|
||||||
GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 110, 20 }, "Round Robin;Random", &option);
|
|
||||||
n.mode = (Distribution)option;
|
|
||||||
|
|
||||||
GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS");
|
|
||||||
if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){
|
|
||||||
sm.addSignalAtNode(&n);
|
|
||||||
}
|
|
||||||
|
|
||||||
int y_midi = 120;
|
|
||||||
GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT");
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for(auto& mo : n.midi_outs){
|
|
||||||
GuiCheckBox((Rectangle){np.x + 20, np.y + y_midi + 20 + i*20.0f, 20, 20}, mo.second.name.c_str(), &mo.second.enabled);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 90, 100, 20}, "NOTE");
|
|
||||||
float v = n.midi_note;
|
|
||||||
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);
|
|
||||||
n.midi_note = round(v);
|
|
||||||
|
|
||||||
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 150, 100, 20}, "VELOCITY");
|
|
||||||
v = n.midi_velocity;
|
|
||||||
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);
|
|
||||||
n.midi_velocity = round(v);
|
|
||||||
|
|
||||||
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 210, 100, 20}, "GATE");
|
|
||||||
v = n.midi_gate;
|
|
||||||
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);
|
|
||||||
n.midi_gate = round(v);
|
|
||||||
|
|
||||||
//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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
@@ -442,6 +273,140 @@ int main(){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*void drawGUI(){*/
|
||||||
|
/**/
|
||||||
|
/* // Main Config Window*/
|
||||||
|
/* GuiWindowBox((Rectangle){0,0,280,(float)app.settings.height}, "config");*/
|
||||||
|
/* {*/
|
||||||
|
/* const int s_controls = 55;*/
|
||||||
|
/* if(GuiButton((Rectangle){20, (float)s_controls, 60, 30}, "PLAY")) sm.play ? sm.pause() : sm.start();*/
|
||||||
|
/* if(GuiButton((Rectangle){100, (float)s_controls, 60, 30}, "STOP")) sm.stop();*/
|
||||||
|
/* if(GuiButton((Rectangle){180, (float)s_controls, 60, 30}, "RESET")) sm.reset();*/
|
||||||
|
/**/
|
||||||
|
/* const int s_bpm = s_controls + 35;*/
|
||||||
|
/* GuiLabel((Rectangle){20, (float)s_bpm, 120, 20}, "TIMING");*/
|
||||||
|
/* GuiLabel((Rectangle){200, (float)s_bpm, 40, 20}, std::format("{}",app.settings.bpm).c_str());*/
|
||||||
|
/* float _bpm = (float)app.settings.bpm;*/
|
||||||
|
/* GuiSlider((Rectangle){20, (float)s_bpm + 25, 240, 20}, "", "", &_bpm, 1, 300);*/
|
||||||
|
/* app.settings.bpm = _bpm;*/
|
||||||
|
/**/
|
||||||
|
/* int s_midi = s_bpm + 55;*/
|
||||||
|
/* GuiLabel((Rectangle){20, (float)s_midi, 240, 20}, "MIDI OUT");*/
|
||||||
|
/* int i = 0;*/
|
||||||
|
/* for(auto& mo : midi.midi_out_ports){*/
|
||||||
|
/* GuiCheckBox((Rectangle){20, (float)s_midi + 25 + i*20.0f, 20, 20}, mo.port.port_name.c_str(), &mo.enabled);*/
|
||||||
|
/* i++;*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) {*/
|
||||||
|
/* for(auto &midis : midi.midi_out_ports){*/
|
||||||
|
/* if(midis.enabled){*/
|
||||||
|
/* for(auto &n : nodes){*/
|
||||||
|
/* n.midi_outs[midis.number].enabled = true;*/
|
||||||
|
/* }*/
|
||||||
|
/* }*/
|
||||||
|
/* }*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* 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")){*/
|
||||||
|
/* int ni = rand() % nodes.size();*/
|
||||||
|
/* sm.addSignalAtNode(&nodes[ni]);*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* 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_multiplier = round(s.multiplier*10.0f)/10.0f;*/
|
||||||
|
/* float signal_bpm = app.settings.bpm * s.multiplier;*/
|
||||||
|
/* GuiSlider((Rectangle){70, (float)s_signal+70 + signal_configs*20, 160, 20}, "", std::format("{:.1f}",signal_bpm).c_str(), &s_multiplier, 0.1, 2);*/
|
||||||
|
/* s.multiplier = s_multiplier;*/
|
||||||
|
/* s.speed = app.settings.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")){*/
|
||||||
|
/* nodes.emplace_back(200.0f, 200.0f, 15.0f);*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* DrawFPS(20, app.settings.height - 30);*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* // Per Node Config Windows*/
|
||||||
|
/* for(auto& n : nodes){*/
|
||||||
|
/* 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);*/
|
||||||
|
/* }*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* if(n.config){*/
|
||||||
|
/* n.config = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config");*/
|
||||||
|
/**/
|
||||||
|
/* int option = n.mode;*/
|
||||||
|
/* GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 110, 20 }, "Round Robin;Random", &option);*/
|
||||||
|
/* n.mode = (Distribution)option;*/
|
||||||
|
/**/
|
||||||
|
/* GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS");*/
|
||||||
|
/* if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){*/
|
||||||
|
/* sm.addSignalAtNode(&n);*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* int y_midi = 120;*/
|
||||||
|
/* GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT");*/
|
||||||
|
/**/
|
||||||
|
/* int i = 0;*/
|
||||||
|
/* for(auto& mo : n.midi_outs){*/
|
||||||
|
/* GuiCheckBox((Rectangle){np.x + 20, np.y + y_midi + 20 + i*20.0f, 20, 20}, mo.second.name.c_str(), &mo.second.enabled);*/
|
||||||
|
/* i++;*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* 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);*/
|
||||||
|
/**/
|
||||||
|
/* GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 90, 100, 20}, "NOTE");*/
|
||||||
|
/* float v = n.midi_note;*/
|
||||||
|
/* 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);*/
|
||||||
|
/* n.midi_note = round(v);*/
|
||||||
|
/**/
|
||||||
|
/* GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 150, 100, 20}, "VELOCITY");*/
|
||||||
|
/* v = n.midi_velocity;*/
|
||||||
|
/* 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);*/
|
||||||
|
/* n.midi_velocity = round(v);*/
|
||||||
|
/**/
|
||||||
|
/* GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 210, 100, 20}, "GATE");*/
|
||||||
|
/* v = n.midi_gate;*/
|
||||||
|
/* 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);*/
|
||||||
|
/* n.midi_gate = round(v);*/
|
||||||
|
/**/
|
||||||
|
/* //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;*/
|
||||||
|
/* }*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/* 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);*/
|
||||||
|
/**/
|
||||||
|
/* }*/
|
||||||
|
/* }*/
|
||||||
|
/**/
|
||||||
|
/**/
|
||||||
|
/*}*/
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class NodeManager{
|
||||||
|
|
||||||
|
public:
|
||||||
|
NodeManager() {
|
||||||
|
nodes.reserve(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Node> nodes;
|
||||||
|
|
||||||
|
void addNode(float x, float y){
|
||||||
|
addNode(Vec2D<float>(x,y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addNode(Vec2D<float> position){
|
||||||
|
nodes.emplace_back(position, 15.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawNodes(Vec2D<float> *mouse_pos, Camera2D *camera){
|
||||||
|
for(auto& n : nodes){
|
||||||
|
n.draw(mouse_pos, camera);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
@@ -20,6 +20,7 @@ class Node : public Movable{
|
|||||||
public:
|
public:
|
||||||
Node() {}
|
Node() {}
|
||||||
Node(float x, float y, float r) : Movable(Vec2D<float>(x, y), 0.0f), radius(r) {}
|
Node(float x, float y, float r) : Movable(Vec2D<float>(x, y), 0.0f), radius(r) {}
|
||||||
|
Node(Vec2D<float> p, float r) : Movable(p, 0.0f), radius(r) {}
|
||||||
|
|
||||||
float radius;
|
float radius;
|
||||||
|
|
||||||
@@ -52,6 +53,10 @@ class Node : public Movable{
|
|||||||
|
|
||||||
Distribution mode = Distribution::ROUNDROBIN;
|
Distribution mode = Distribution::ROUNDROBIN;
|
||||||
|
|
||||||
|
void setMidiPort(int midi_port, bool state){
|
||||||
|
midi_outs[midi_port].enabled = state;
|
||||||
|
}
|
||||||
|
|
||||||
void draw(Vec2D<float> *mouse, Camera2D *cam) {
|
void draw(Vec2D<float> *mouse, Camera2D *cam) {
|
||||||
if(!dragging && !selected && !in_rect && !hovering) DrawCircle(position.x, position.y, radius, (Color){180, 210, 115, 255});
|
if(!dragging && !selected && !in_rect && !hovering) DrawCircle(position.x, position.y, radius, (Color){180, 210, 115, 255});
|
||||||
if(dragging || selected || in_rect || hovering) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255});
|
if(dragging || selected || in_rect || hovering) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255});
|
||||||
|
|||||||
+10
-5
@@ -12,11 +12,13 @@
|
|||||||
class SignalManager{
|
class SignalManager{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SignalManager(AppState *app, ConnectionManager *cm, Midi *midi) : app(app), cm(cm), midi(midi) {}
|
SignalManager() {}
|
||||||
|
SignalManager(ConnectionManager *cm, std::mutex *mutex) : mutex(mutex), cm(cm) {}
|
||||||
|
|
||||||
AppState *app;
|
Midi midi;
|
||||||
|
|
||||||
|
std::mutex *mutex;
|
||||||
ConnectionManager *cm;
|
ConnectionManager *cm;
|
||||||
Midi *midi;
|
|
||||||
|
|
||||||
std::vector<Signal> signals;
|
std::vector<Signal> signals;
|
||||||
|
|
||||||
@@ -56,7 +58,7 @@ class SignalManager{
|
|||||||
|
|
||||||
void addSignalAtNode(Node *node){
|
void addSignalAtNode(Node *node){
|
||||||
Color c = {(unsigned char)(232 - (rand() % 120)), (unsigned char)(125 + (int)(rand() % 120)), 62, 255};
|
Color c = {(unsigned char)(232 - (rand() % 120)), (unsigned char)(125 + (int)(rand() % 120)), 62, 255};
|
||||||
signals.emplace(signals.end(), Signal(node->position.x+1, node->position.y+1, 5.0f, app->speed, c)); // position + 1 or else it does not render. why? no idea!
|
signals.emplace(signals.end(), Signal(node->position.x+1, node->position.y+1, 5.0f, 0, c)); // position + 1 or else it does not render. why? no idea!
|
||||||
signals.back().next = node;
|
signals.back().next = node;
|
||||||
signals.back().last = node;
|
signals.back().last = node;
|
||||||
signals.back().start = node;
|
signals.back().start = node;
|
||||||
@@ -71,6 +73,7 @@ class SignalManager{
|
|||||||
while(loop){
|
while(loop){
|
||||||
std::chrono::duration<double, std::micro> diff = std::chrono::steady_clock::now() - last;
|
std::chrono::duration<double, std::micro> diff = std::chrono::steady_clock::now() - last;
|
||||||
if(diff.count() > 500){
|
if(diff.count() > 500){
|
||||||
|
//mutex->lock();
|
||||||
if(play){
|
if(play){
|
||||||
for(auto& s : signals){
|
for(auto& s : signals){
|
||||||
s.direction = (s.next->position - s.position).norm();
|
s.direction = (s.next->position - s.position).norm();
|
||||||
@@ -80,7 +83,7 @@ class SignalManager{
|
|||||||
|
|
||||||
if(n != s.next && n != nullptr) {
|
if(n != s.next && n != nullptr) {
|
||||||
for(auto &m : s.next->midi_outs){
|
for(auto &m : s.next->midi_outs){
|
||||||
if(m.second.enabled) midi->note(m.second.i, s.next->midi_channel, s.next->midi_note, s.next->midi_velocity, s.next->midi_gate);
|
if(m.second.enabled) midi.note(m.second.i, s.next->midi_channel, s.next->midi_note, s.next->midi_velocity, s.next->midi_gate);
|
||||||
}
|
}
|
||||||
s.last = s.next;
|
s.last = s.next;
|
||||||
s.next = n;
|
s.next = n;
|
||||||
@@ -88,7 +91,9 @@ class SignalManager{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//mutex->unlock();
|
||||||
last = std::chrono::steady_clock::now();
|
last = std::chrono::steady_clock::now();
|
||||||
|
midi.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
#include "node-manager.h"
|
||||||
|
#include "connection-manager.h"
|
||||||
|
#include "signal-manager.h"
|
||||||
|
#include "ui.h"
|
||||||
|
|
||||||
|
class AppState{
|
||||||
|
public:
|
||||||
|
|
||||||
|
AppState() : sm(&cm, &mutex), ui(&settings, &nm, &cm, &sm) {}
|
||||||
|
|
||||||
|
enum States {IDLE, CONFIG};
|
||||||
|
|
||||||
|
AppSettings settings;
|
||||||
|
|
||||||
|
States state;
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
|
|
||||||
|
ConnectionManager cm;
|
||||||
|
SignalManager sm;
|
||||||
|
NodeManager nm;
|
||||||
|
|
||||||
|
AppUI ui;
|
||||||
|
|
||||||
|
void updateMidiPorts(){
|
||||||
|
for(auto&n : nm.nodes){
|
||||||
|
for(auto& mo : sm.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(Vec2D<float> *mouse_pos, Camera2D *camera){
|
||||||
|
mutex.lock();
|
||||||
|
updateMidiPorts();
|
||||||
|
nm.drawNodes(mouse_pos, camera);
|
||||||
|
cm.drawConnections(mouse_pos, camera);
|
||||||
|
sm.drawSignals(mouse_pos, camera);
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawUI(Vec2D<float> *mouse_pos, Camera2D *camera){
|
||||||
|
mutex.lock();
|
||||||
|
ui.draw(mouse_pos, camera);
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "raygui/raygui.h"
|
||||||
|
#include "raygui/dark/style_dark.h"
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
|
|
||||||
|
#include "connection-manager.h"
|
||||||
|
#include "node-manager.h"
|
||||||
|
#include "raylib.h"
|
||||||
|
#include "signal-manager.h"
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
|
class AppUI{
|
||||||
|
public:
|
||||||
|
|
||||||
|
AppUI(AppSettings *settings, NodeManager *nm, ConnectionManager *cm, SignalManager *sm) : settings(settings), nm(nm), sm(sm), cm(cm) {}
|
||||||
|
|
||||||
|
AppSettings *settings;
|
||||||
|
NodeManager *nm;
|
||||||
|
SignalManager *sm;
|
||||||
|
ConnectionManager *cm;
|
||||||
|
|
||||||
|
void init(){
|
||||||
|
GuiLoadStyleDark();
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawSideBar(){
|
||||||
|
|
||||||
|
GuiWindowBox((Rectangle){0,0,280,(float)settings->height}, "config");
|
||||||
|
{
|
||||||
|
const int s_controls = 55;
|
||||||
|
if(GuiButton((Rectangle){20, (float)s_controls, 60, 30}, "PLAY")) sm->play ? sm->pause() : sm->start();
|
||||||
|
if(GuiButton((Rectangle){100, (float)s_controls, 60, 30}, "STOP")) sm->stop();
|
||||||
|
if(GuiButton((Rectangle){180, (float)s_controls, 60, 30}, "RESET")) sm->reset();
|
||||||
|
|
||||||
|
const int s_bpm = s_controls + 35;
|
||||||
|
GuiLabel((Rectangle){20, (float)s_bpm, 120, 20}, "TIMING");
|
||||||
|
GuiLabel((Rectangle){200, (float)s_bpm, 40, 20}, std::format("{}",settings->bpm).c_str());
|
||||||
|
float _bpm = (float)settings->bpm;
|
||||||
|
GuiSlider((Rectangle){20, (float)s_bpm + 25, 240, 20}, "", "", &_bpm, 1, 300);
|
||||||
|
settings->bpm = _bpm;
|
||||||
|
|
||||||
|
int s_midi = s_bpm + 55;
|
||||||
|
GuiLabel((Rectangle){20, (float)s_midi, 240, 20}, "MIDI OUT");
|
||||||
|
int i = 0;
|
||||||
|
for(auto& mo : sm->midi.midi_out_ports){
|
||||||
|
GuiCheckBox((Rectangle){20, (float)s_midi + 25 + i*20.0f, 20, 20}, mo.port.port_name.c_str(), &mo.enabled);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) {
|
||||||
|
for(auto &midis : sm->midi.midi_out_ports){
|
||||||
|
if(midis.enabled){
|
||||||
|
for(auto &n : nm->nodes){
|
||||||
|
n.setMidiPort(midis.number, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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")){
|
||||||
|
int ni = rand() % nm->nodes.size();
|
||||||
|
sm->addSignalAtNode(&nm->nodes[ni]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_multiplier = round(s.multiplier*10.0f)/10.0f;
|
||||||
|
float signal_bpm = settings->bpm * s.multiplier;
|
||||||
|
GuiSlider((Rectangle){70, (float)s_signal+70 + signal_configs*20, 160, 20}, "", std::format("{:.1f}",signal_bpm).c_str(), &s_multiplier, 0.1, 2);
|
||||||
|
s.multiplier = s_multiplier;
|
||||||
|
s.speed = settings->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")){
|
||||||
|
nm->nodes.emplace_back(200.0f, 200.0f, 15.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawFPS(20, settings->height - 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawPerNodeConfig(Camera2D *camera){
|
||||||
|
for(auto& n : nm->nodes | std::ranges::views::filter([](Node n){ return n.config; })){
|
||||||
|
Vector2 np = GetWorldToScreen2D((Vector2){n.position.x, n.position.y}, *camera);
|
||||||
|
|
||||||
|
n.config = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config");
|
||||||
|
|
||||||
|
int option = n.mode;
|
||||||
|
GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 110, 20 }, "Round Robin;Random", &option);
|
||||||
|
n.mode = (Distribution)option;
|
||||||
|
|
||||||
|
GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS");
|
||||||
|
if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){
|
||||||
|
sm->addSignalAtNode(&n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int y_midi = 120;
|
||||||
|
GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT");
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for(auto& mo : n.midi_outs){
|
||||||
|
GuiCheckBox((Rectangle){np.x + 20, np.y + y_midi + 20 + i*20.0f, 20, 20}, mo.second.name.c_str(), &mo.second.enabled);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 90, 100, 20}, "NOTE");
|
||||||
|
float v = n.midi_note;
|
||||||
|
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 90, 20, 20}, sm->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);
|
||||||
|
n.midi_note = round(v);
|
||||||
|
|
||||||
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 150, 100, 20}, "VELOCITY");
|
||||||
|
v = n.midi_velocity;
|
||||||
|
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);
|
||||||
|
n.midi_velocity = round(v);
|
||||||
|
|
||||||
|
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 210, 100, 20}, "GATE");
|
||||||
|
v = n.midi_gate;
|
||||||
|
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);
|
||||||
|
n.midi_gate = round(v);
|
||||||
|
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw(Vec2D<float> *mouse_pos, Camera2D *camera){
|
||||||
|
drawSideBar();
|
||||||
|
drawPerNodeConfig(camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user