GEO mode for signals takes direction of next connection into account

This commit is contained in:
Sebastian
2024-10-30 02:00:40 +01:00
parent c63eeed1b4
commit ad7b0e4524
9 changed files with 251 additions and 73 deletions
+38 -21
View File
@@ -3,6 +3,7 @@
#include "connection.h" #include "connection.h"
#include "node-manager.h" #include "node-manager.h"
#include "raylib.h" #include "raylib.h"
#include "raymath.h"
#include <map> #include <map>
#include <vector> #include <vector>
@@ -23,41 +24,57 @@ class ConnectionManager{
} }
int next(int current, int last){ int next(int current, int last){
std::vector<Connection*> paths; std::vector<Connection*> possible_connections;
std::vector<int> node_ids; std::vector<int> next_node_ids;
for(auto& p : connections){ for(auto& c : connections){
if((p.v1 == current && p.v1_v2) || (p.v2 == current && p.v2_v1)) { if((c.v1 == current && c.v1_v2) || (c.v2 == current && c.v2_v1)) {
p.active = false; c.active = false;
paths.push_back(&p); possible_connections.push_back(&c);
node_ids.push_back( p.v1 == current ? p.v2 : p.v1 ); next_node_ids.push_back( c.v1 == current ? c.v2 : c.v1 );
} }
} }
if(paths.size() == 2) { /*if(possible_connections.size() == 2) {*/
int next = node_ids[0] == last ? node_ids[1] : node_ids[0]; /* int next = next_node_ids[0] == last ? next_node_ids[1] : next_node_ids[0];*/
if(paths[0]->v1 == next || paths[0]->v2 == next) paths[0]->active = true; /* if(possible_connections[0]->v1 == next || possible_connections[0]->v2 == next) possible_connections[0]->active = true;*/
if(paths[1]->v1 == next || paths[1]->v2 == next) paths[1]->active = true; /* if(possible_connections[1]->v1 == next || possible_connections[1]->v2 == next) possible_connections[1]->active = true;*/
return next; /* return next;*/
} /*}*/
if(paths.empty()) return -1; if(possible_connections.empty()) return -1;
int return_path = 0; int return_path = 0;
float angle = -1;
if(nm->nodes.at(current).mode == Distribution::ROUNDROBIN){ if(nm->nodes.at(current).distributionMode == Distribution::GEOMETRIC){
Vec2D<float> coming_from = (nm->nodes.at(current).position - nm->nodes.at(last).position).norm();
int i = 0;
for(auto n : possible_connections){
int next_position = n->v1 == current ? n->v2 : n->v1;
float angle_v1_v2 = coming_from.norm().dot((nm->nodes.at(next_position).position - nm->nodes.at(current).position).norm());
if(angle_v1_v2 > angle) {
return_path = i;
angle = angle_v1_v2;
}
++i;
}
}
if(nm->nodes.at(current).distributionMode == Distribution::ROUNDROBIN){
if(counter.find(current) == counter.end()) { if(counter.find(current) == counter.end()) {
counter[current] = 0; counter[current] = 0;
} else { } else {
counter[current] = (counter[current] + 1) % paths.size(); counter[current] = (counter[current] + 1) % possible_connections.size();
return_path = counter[current]; return_path = counter[current];
} }
} }
if(nm->nodes.at(current).mode == Distribution::RANDOM){
return_path = rand() % paths.size(); if(nm->nodes.at(current).distributionMode == Distribution::RANDOM){
return_path = rand() % possible_connections.size();
} }
paths.at(return_path)->active = true;
return paths.at(return_path)->v1 == current ? paths.at(return_path)->v2 : paths.at(return_path)->v1; possible_connections.at(return_path)->active = true;
return possible_connections.at(return_path)->v1 == current ? possible_connections.at(return_path)->v2 : possible_connections.at(return_path)->v1;
} }
void addConnection(int from, int to){ void addConnection(int from, int to){
+2 -2
View File
@@ -60,8 +60,8 @@ class Connection{
// Dynamic opacity by distance to mouse // Dynamic opacity by distance to mouse
unsigned char opacity = 150.0f - Clamp(middle_handle.dist(mouse_pos), 0.0f, 150.0f); unsigned char opacity = 150.0f - Clamp(middle_handle.dist(mouse_pos), 0.0f, 150.0f);
unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 120.0f); unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 220.0f);
unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 120.0f); unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.0f);
// On/Off switches on both sides // On/Off switches on both sides
if(ViButton(mouse_pos, from_to_handle.x, from_to_handle.y, 8.0f, v1_v2 ? (Color){120, 210, 115, opacity_from} : (Color){232, 50, 32, opacity_from} )) v1_v2 = !v1_v2; if(ViButton(mouse_pos, from_to_handle.x, from_to_handle.y, 8.0f, v1_v2 ? (Color){120, 210, 115, opacity_from} : (Color){232, 50, 32, opacity_from} )) v1_v2 = !v1_v2;
+6 -1
View File
@@ -25,7 +25,7 @@
#include "libremidi/libremidi.hpp" #include "libremidi/libremidi.hpp"
#include "raylib.h" #include "raylib.h"
enum Distribution {ROUNDROBIN, RANDOM}; enum Distribution {GEOMETRIC, ROUNDROBIN, RANDOM};
// 2D Vectors // 2D Vectors
@@ -57,6 +57,10 @@ class Vec2D{
T dot(Vec2D &v){ T dot(Vec2D &v){
return (x*v.x) + (y*v.y); return (x*v.x) + (y*v.y);
}; };
T dot(Vec2D v){
return (x*v.x) + (y*v.y);
};
operator Vector2() const { operator Vector2() const {
return (Vector2){x,y}; return (Vector2){x,y};
@@ -152,6 +156,7 @@ Vec2D<T> operator*(const Vec2D<T>& left, T scalar){
// App Settings // App Settings
struct AppSettings{ struct AppSettings{
int mode = 0;
int width; int width;
int height; int height;
float grid; float grid;
+48 -11
View File
@@ -63,9 +63,9 @@ int main(){
app.settings.fps = 60.0f; app.settings.fps = 60.0f;
app.settings.bpm = 120.0f; app.settings.bpm = 120.0f;
app.settings.grid = 120.0f; // 120px for a 16th note app.settings.grid = 60.0f; // 120px for a 16th note
app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f); app.settings.speed = (app.settings.grid * 16.0f) * (app.settings.bpm / 120.f);
app.settings.width = monitor_width - 300; app.settings.width = monitor_width - 300;
app.settings.height = monitor_height - 300; app.settings.height = monitor_height - 300;
@@ -78,10 +78,10 @@ int main(){
camera.zoom = 1.0f; camera.zoom = 1.0f;
for(int i = 0; i < 4; ++i){ for(int i = 0; i < 4; ++i){
app.nm.addNode((float)i * app.settings.grid + 10 * app.settings.grid, 5 * app.settings.grid); app.nm.addNode((float)i * app.settings.grid*4 + 10 * app.settings.grid, 5 * app.settings.grid*4);
} }
for(int i = 3; i >= 0; --i){ for(int i = 3; i >= 0; --i){
app.nm.addNode((float)i * app.settings.grid + 10 * app.settings.grid, 6 * app.settings.grid); app.nm.addNode((float)i * app.settings.grid*4 + 10 * app.settings.grid, 6 * app.settings.grid*4);
} }
for(int i = 0; i < 8; ++i){ for(int i = 0; i < 8; ++i){
@@ -104,7 +104,7 @@ int main(){
ClearBackground((Color){46,46,46}); ClearBackground((Color){46,46,46});
BeginMode2D(camera); BeginMode2D(camera);
app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f); app.settings.speed = (app.settings.grid * 16.0f) * (app.settings.bpm / 120.f);
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};
@@ -146,6 +146,11 @@ int main(){
if(!copied_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) istate = InteractionState::PASTE_SELECTED_NODES; if(!copied_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) istate = InteractionState::PASTE_SELECTED_NODES;
if(IsKeyPressed(KEY_TAB)) {
app.settings.mode = (app.settings.mode + 1) % 3;
app.nm.setNodeMode(app.settings.mode);
}
switch(istate){ switch(istate){
case InteractionState::HOVER_CANVAS: case InteractionState::HOVER_CANVAS:
{ {
@@ -214,7 +219,7 @@ int main(){
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.settings.grid)*app.settings.grid, round((mouse_pos.y+dragging_nodes.front().drag_offset.y)/app.settings.grid)*app.settings.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 if(IsKeyDown(KEY_LEFT_SHIFT)){ } else if(IsKeyDown(KEY_LEFT_SHIFT)){
float steps = round(dragging_nodes.front().neighbor->position.dist(mouse_pos) / 60.0f) * 60.0f; float steps = round(dragging_nodes.front().neighbor->position.dist(mouse_pos) / app.settings.grid) * app.settings.grid;
Vec2D<float> polar = dragging_nodes.front().neighbor->position - (dragging_nodes.front().neighbor->position - (mouse_pos + dragging_nodes.front().drag_offset)).norm() * steps; Vec2D<float> polar = dragging_nodes.front().neighbor->position - (dragging_nodes.front().neighbor->position - (mouse_pos + dragging_nodes.front().drag_offset)).norm() * steps;
dragging_nodes.front().position = polar; dragging_nodes.front().position = polar;
} else { } else {
@@ -311,17 +316,49 @@ int main(){
float wheel = GetMouseWheelMove(); float wheel = GetMouseWheelMove();
if(wheel != 0){ if(wheel != 0){
if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL) && !IsKeyDown(KEY_LEFT_ALT)){ if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL) && !IsKeyDown(KEY_LEFT_ALT)){
hovering_nodes.front().midi_note += wheel; switch(app.settings.mode){
case 0:{
hovering_nodes.front().midi_note += wheel;
break;}
case 1:{
hovering_nodes.front().midi_cc += wheel;
break;}
case 2:{
hovering_nodes.front().midi_pitch_bend += wheel;
break;}
};
if(hovering_nodes.front().midi_note < 0 ) hovering_nodes.front().midi_note = app.sm.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 >= app.sm.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;
if(hovering_nodes.front().midi_cc < 0 ) hovering_nodes.front().midi_cc = 127;
if(hovering_nodes.front().midi_cc > 127 ) hovering_nodes.front().midi_cc = 0;
if(hovering_nodes.front().midi_pitch_bend < 0 ) hovering_nodes.front().midi_pitch_bend = 0;
if(hovering_nodes.front().midi_pitch_bend > 16383 ) hovering_nodes.front().midi_pitch_bend = 16383;
} else if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_SHIFT) && !IsKeyDown(KEY_LEFT_ALT)) { } else if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_SHIFT) && !IsKeyDown(KEY_LEFT_ALT)) {
hovering_nodes.front().midi_velocity += wheel; hovering_nodes.front().midi_velocity += wheel;
if(hovering_nodes.front().midi_velocity < 0 ) hovering_nodes.front().midi_velocity = 127; if(hovering_nodes.front().midi_velocity < 0 ) hovering_nodes.front().midi_velocity = 127;
if(hovering_nodes.front().midi_velocity > 127 ) hovering_nodes.front().midi_velocity = 0; if(hovering_nodes.front().midi_velocity > 127 ) hovering_nodes.front().midi_velocity = 0;
} else if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_ALT)) { } else if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_ALT)) {
float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f); switch(app.settings.mode){
hovering_nodes.front().midi_gate += incr; case 0:{
if(hovering_nodes.front().midi_gate < 0 ) hovering_nodes.front().midi_gate = 0; float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f);
hovering_nodes.front().midi_gate += incr;
if(hovering_nodes.front().midi_gate < 0 ) hovering_nodes.front().midi_gate = 0;
break;}
case 1:{
hovering_nodes.front().midi_cc_value += wheel;
if(hovering_nodes.front().midi_cc_value < 0 ) hovering_nodes.front().midi_cc_value = 0;
if(hovering_nodes.front().midi_cc_value > 127 ) hovering_nodes.front().midi_cc_value = 127;
break;}
case 2:{
float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f);
hovering_nodes.front().midi_pitch_bend += incr;
if(hovering_nodes.front().midi_pitch_bend < 0 ) hovering_nodes.front().midi_pitch_bend = 0;
if(hovering_nodes.front().midi_pitch_bend > 16383 ) hovering_nodes.front().midi_pitch_bend = 16383;
break;}
};
} else { } else {
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
camera.offset = GetMousePosition(); camera.offset = GetMousePosition();
+17
View File
@@ -8,6 +8,7 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <memory> #include <memory>
#include <numbers>
#include "datatypes.h" #include "datatypes.h"
struct NoteTimer{ struct NoteTimer{
@@ -90,6 +91,22 @@ class Midi {
} }
} }
} }
void cc(int midi_out, int channel, int cc, int value){
if(midi_outs.contains(midi_out)){
if(midi_outs[midi_out]->is_port_open()){
midi_outs[midi_out]->send_message(libremidi::channel_events::control_change(channel, cc, value));
}
}
}
void pitch_bend(int midi_out, int channel, int pitch_value){
if(midi_outs.contains(midi_out)){
if(midi_outs[midi_out]->is_port_open()){
midi_outs[midi_out]->send_message(libremidi::channel_events::pitch_bend(channel, pitch_value));
}
}
}
void update(){ void update(){
float time = GetTime(); float time = GetTime();
+6
View File
@@ -50,6 +50,12 @@ class NodeManager{
return iterator - 1; return iterator - 1;
} }
void setNodeMode(int mode){
for(auto &n : nodes | std::ranges::views::values){
n.mode = mode;
}
}
int addNode(float x, float y){ int addNode(float x, float y){
return addNode(Vec2D<float>(x,y)); return addNode(Vec2D<float>(x,y));
} }
+69 -10
View File
@@ -22,7 +22,6 @@ class Node : public Movable{
Node(int id, float x, float y, float r) : Movable(Vec2D<float>(x, y), 0.0f), radius(r), id(id) {} Node(int id, float x, float y, float r) : Movable(Vec2D<float>(x, y), 0.0f), radius(r), id(id) {}
Node(int id, Vec2D<float> p, float r) : Movable(p, 0.0f), radius(r), id(id) {} Node(int id, Vec2D<float> p, float r) : Movable(p, 0.0f), radius(r), id(id) {}
Node *neighbor = nullptr; Node *neighbor = nullptr;
float radius; float radius;
@@ -42,6 +41,11 @@ class Node : public Movable{
bool copied = false; bool copied = false;
bool triggered = false; bool triggered = false;
bool send_note = true;
bool send_cc = false;
bool send_pc = false;
bool send_pitch_bend = false;
int midi_out = -1; int midi_out = -1;
Vec2D<float> drag_offset; Vec2D<float> drag_offset;
@@ -53,18 +57,30 @@ class Node : public Movable{
bool gui_midi_velocity_edit = false; bool gui_midi_velocity_edit = false;
bool gui_midi_gate_edit = false; bool gui_midi_gate_edit = false;
int midi_channel = 1; int mode = 0;
int midi_note_channel = 1;
int midi_note = 48; int midi_note = 48;
int midi_velocity = 60; int midi_velocity = 60;
int midi_gate = 100; int midi_gate = 25; // gate time in milliseconds
int midi_cc_channel = 0;
int midi_cc = 0; int midi_cc = 0;
int midi_cc_value = 0;
int midi_pc_channel = 0;
int midi_pc = 0;
int midi_pc_value = 0;
int midi_pitch_bend_channel = 0;
int midi_pitch_bend = 8192;
float start = 0; float start = 0;
float fade = 0; float fade = 0;
float time = 0; float time = 0;
float last = 0; float last = 0;
Distribution mode = Distribution::ROUNDROBIN; Distribution distributionMode = Distribution::GEOMETRIC;
void setMidiPort(int midi_port, bool state){ void setMidiPort(int midi_port, bool state){
midi_outs[midi_port].enabled = state; midi_outs[midi_port].enabled = state;
@@ -89,22 +105,65 @@ class Node : public Movable{
DrawRing(position, radius, radius+4, 0, 360, 24, (Color){60, 60, 60, 255}); DrawRing(position, radius, radius+4, 0, 360, 24, (Color){60, 60, 60, 255});
DrawRing(position, radius, radius+4, 0.0f - 90.0f, (360.0f/127.0f) * midi_velocity - 90.0f, 24, (Color){158, 134, 200, 255}); DrawRing(position, radius, radius+4, 0.0f - 90.0f, (360.0f/127.0f) * midi_velocity - 90.0f, 24, (Color){158, 134, 200, 255});
DrawCircleLinesV(position, radius + 4, (Color){100, 100, 100, 255}); DrawCircleLinesV(position, radius + 4, (Color){100, 100, 100, 255});
if(mode == Distribution::RANDOM) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_PINK);
float midi_gate_map = round((255.f / midi_gate) * fade); float midi_gate_map = round((255.f / midi_gate) * fade);
Color gate_color = ColorAlphaBlend(VS_COLOR_RED, (Color){180, 210, 115, (unsigned char)Clamp(255 - midi_gate_map, 0, 255)}, WHITE);
Color gate_color = VS_COLOR_GREEN;
switch(mode){
case 0:{
gate_color = ColorAlphaBlend(VS_COLOR_RED, (Color){180, 210, 115, (unsigned char)Clamp(255 - midi_gate_map, 0, 255)}, WHITE);
break;}
case 1:{
gate_color = ColorAlphaBlend(VS_COLOR_RED, (Color){229, 181, 103, (unsigned char)Clamp(255 - midi_gate_map, 0, 255)}, WHITE);
break;}
case 2:{
gate_color = ColorAlphaBlend(VS_COLOR_RED, (Color){232, 125, 62, (unsigned char)Clamp(255 - midi_gate_map, 0, 255)}, WHITE);
break;}
}
if(!dragging && !selected && !in_rect && !hovering) DrawCircle(position.x, position.y, radius, gate_color); if(!dragging && !selected && !in_rect && !hovering) DrawCircle(position.x, position.y, radius, gate_color);
if(selected || dragging || in_rect || hovering) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255}); if(selected || dragging || in_rect || hovering) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255});
if(distributionMode == Distribution::RANDOM) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_PINK);
if(distributionMode == Distribution::ROUNDROBIN) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_YELLOW);
if(selected) DrawCircleLinesV(position, radius+8, (Color){158, 255, 210, 255}); if(selected) DrawCircleLinesV(position, radius+8, (Color){158, 255, 210, 255});
if(IsKeyDown(KEY_LEFT_ALT)){ if(IsKeyDown(KEY_LEFT_ALT)){
int offset_gate = MeasureText(std::format("{:.2f}", (float)midi_gate/1000.0f).c_str(), 12); float value = 0;
DrawText(std::format("{:.2f}",(float)midi_gate/1000.0f).c_str(), position.x-offset_gate/2.0f, position.y-5, 12, WHITE ); int offset_gate = 0;
switch(mode){
case 0:
value = (float)midi_gate/1000.0f;
offset_gate = MeasureText(std::format("{:.2f}", value).c_str(), 12);
DrawText(std::format("{:.2f}",value).c_str(), position.x-offset_gate/2.0f, position.y-5, 12, WHITE );
break;
case 1:
value = (float)midi_cc_value;
offset_gate = MeasureText(std::format("{}", value).c_str(), 12);
DrawText(std::format("{}",value).c_str(), position.x-offset_gate/2.0f, position.y-5, 12, WHITE );
break;
case 2:
value = (float)midi_pitch_bend;
offset_gate = MeasureText(std::format("{}", value).c_str(), 12);
DrawText(std::format("{}",value).c_str(), position.x-offset_gate/2.0f, position.y-5, 12, WHITE );
break;
}
} else { } else {
int offset = MeasureText(MIDI::Notes[midi_note].c_str(), 12); switch(mode){
DrawText(MIDI::Notes[midi_note].c_str(), position.x-offset/2.0f, position.y-5, 12, WHITE ); case 0:{
int offset = MeasureText(MIDI::Notes[(int)midi_note].c_str(), 12);
DrawText(MIDI::Notes[midi_note].c_str(), position.x-offset/2.0f, position.y-5, 12, WHITE );
break;}
case 1:{
int offset = MeasureText(std::format("{}", midi_cc).c_str(), 12);
DrawText(std::format("{}", midi_cc).c_str(), position.x-offset/2.0f, position.y-5, 12, WHITE );
break;}
case 2:{
int offset = MeasureText(std::format("{}", midi_pitch_bend).c_str(), 12);
DrawText(std::format("{}", midi_pitch_bend).c_str(), position.x-offset/2.0f, position.y-5, 12, WHITE );
break;}
}
} }
Vec2D<float> connector = position - ((position - *mouse)).norm() * (radius + R); Vec2D<float> connector = position - ((position - *mouse)).norm() * (radius + R);
+4 -2
View File
@@ -60,7 +60,7 @@ class SignalManager{
void addSignalAtNode(int node_id){ void addSignalAtNode(int node_id){
Color c = {(unsigned char)(20 + (rand() % 200)), 100, (unsigned char)(20 + (int)(rand() % 200)), 200}; Color c = {(unsigned char)(20 + (rand() % 200)), 100, (unsigned char)(20 + (int)(rand() % 200)), 200};
signals.emplace(signals.end(), Signal(nm->nodes[node_id].position.x+1, nm->nodes[node_id].position.y+1, 5.0f, 0, c)); // position + 1 or else it does not render. why? no idea! signals.emplace(signals.end(), Signal(nm->nodes[node_id].position.x+1, nm->nodes[node_id].position.y+1, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea!
signals.back().next = node_id; signals.back().next = node_id;
signals.back().last = node_id; signals.back().last = node_id;
signals.back().start = node_id; signals.back().start = node_id;
@@ -87,7 +87,9 @@ class SignalManager{
if(n != s.next && n != -1) { if(n != s.next && n != -1) {
for(auto &m : nm->nodes[s.next].midi_outs){ for(auto &m : nm->nodes[s.next].midi_outs){
if(m.second.enabled) { if(m.second.enabled) {
midi.note(m.second.i, nm->nodes[s.next].midi_channel, nm->nodes[s.next].midi_note, nm->nodes[s.next].midi_velocity, nm->nodes[s.next].midi_gate); if(nm->nodes[s.next].send_note) midi.note(m.second.i, nm->nodes[s.next].midi_note_channel, nm->nodes[s.next].midi_note, nm->nodes[s.next].midi_velocity, nm->nodes[s.next].midi_gate);
if(nm->nodes[s.next].send_cc) midi.cc(m.second.i, nm->nodes[s.next].midi_cc_channel, nm->nodes[s.next].midi_cc, nm->nodes[s.next].midi_cc_value);
if(nm->nodes[s.next].send_pitch_bend) midi.pitch_bend(m.second.i, nm->nodes[s.next].midi_pitch_bend_channel, nm->nodes[s.next].midi_pitch_bend);
} }
} }
s.last = s.next; s.last = s.next;
+61 -26
View File
@@ -95,9 +95,9 @@ class AppUI{
n.config = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config"); n.config = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config");
int option = n.mode; int option = n.distributionMode;
GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 110, 20 }, "Round Robin;Random", &option); GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 73, 20 }, "GEO;RR;RAND", &option);
n.mode = (Distribution)option; n.distributionMode = (Distribution)option;
GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS"); GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS");
if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){ if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){
@@ -114,30 +114,65 @@ class AppUI{
} }
int y_channel = y_midi + 30 + i*20; int y_channel = y_midi + 30 + i*20;
GuiLabel((Rectangle){np.x + 20, np.y + y_channel, 220, 20}, "CHANNEL"); GuiCheckBox((Rectangle){np.x + 20, np.y + y_channel, 20, 20}, "NOTE", &n.send_note);
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); GuiCheckBox((Rectangle){np.x + 90, np.y + y_channel, 20, 20}, "CC", &n.send_cc);
GuiCheckBox((Rectangle){np.x + 160, np.y + y_channel, 20, 20}, "PITCH", &n.send_pitch_bend);
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 90, 100, 20}, "NOTE"); int y_cc_note = y_channel + 120;
float v = n.midi_note; switch(settings->mode){
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 90, 20, 20}, sm->midi.midiNotes[(int)round(v)].c_str()); case 0:{
GuiLabel((Rectangle){np.x + 160, np.y + y_channel + 90, 40, 20}, std::format("{}",n.midi_note).c_str()); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "NOTE CHANNEL");
GuiSlider((Rectangle){np.x + 20, np.y + y_channel + 120, 220, 20}, "", "", &v, 0, 127); GuiToggleGroup((Rectangle){np.x + 20, np.y + y_cc_note - 50, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &n.midi_note_channel);
n.midi_note = round(v);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "NOTE");
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 150, 100, 20}, "VELOCITY"); float v = n.midi_note;
v = n.midi_velocity; GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note , 20, 20}, sm->midi.midiNotes[(int)round(v)].c_str());
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 150, 20, 20}, std::format("{}",n.midi_velocity).c_str()); GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",n.midi_note).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_channel + 180, 220, 20}, "", "", &v, 0, 127); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127);
n.midi_velocity = round(v); n.midi_note = round(v);
GuiLabel((Rectangle){np.x + 20, np.y + y_channel + 210, 100, 20}, "GATE"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "VELOCITY");
v = n.midi_gate; v = n.midi_velocity;
GuiLabel((Rectangle){np.x + 210, np.y + y_channel + 210, 20, 20}, std::format("{}",(float)n.midi_gate/1000.0f).c_str()); GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",n.midi_velocity).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_channel + 240, 220, 20}, "", "", &v, 0, 30000); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127);
n.midi_gate = round(v); n.midi_velocity = 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; GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 120, 100, 20}, "GATE");
//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; v = n.midi_gate;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 120, 20, 20}, std::format("{}",(float)n.midi_gate/1000.0f).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 150, 220, 20}, "", "", &v, 0, 30000);
n.midi_gate = round(v);
break;}
case 1:
{
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "CC CHANNEL");
GuiToggleGroup((Rectangle){np.x + 20, np.y + y_cc_note - 50, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &n.midi_cc_channel);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC");
float v = n.midi_cc;
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",n.midi_cc).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127);
n.midi_cc = round(v);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "CC VALUE");
v = n.midi_cc_value;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",n.midi_cc_value).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127);
n.midi_cc_value = round(v);
break;}
case 2:
{
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "PITCH BEND CHANNEL");
GuiToggleGroup((Rectangle){np.x + 20, np.y + y_cc_note - 50, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &n.midi_pitch_bend_channel);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC");
float v = n.midi_pitch_bend;
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",n.midi_pitch_bend).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 16383);
n.midi_pitch_bend = round(v);
break;}
}
} }
} }