conversion to smart pointers done but still buggy

This commit is contained in:
Sebastian
2024-11-01 02:38:47 +01:00
parent c0eb7c98ba
commit 19b2c9549f
15 changed files with 389 additions and 524 deletions
+2 -4
View File
@@ -4,14 +4,12 @@
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
inline bool ViButton(Vec2D<float> *mouse_pos, float x, float y, float radius, Color color){ inline bool ViButton(Vec2D<float> mp, float x, float y, float radius, Color color){
Vector2 mp = {mouse_pos->x, mouse_pos->y}; //GetMousePosition(); TODO: Refactor my own vectors to raylib vectors
DrawCircle(x,y,radius, color); DrawCircle(x,y,radius, color);
return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
} }
inline bool ViSegButton(Vec2D<float> *mouse_pos, float x, float y, float start_angle, float end_angle, float radius, Color color){ inline bool ViSegButton(Vec2D<float> mp, float x, float y, float start_angle, float end_angle, float radius, Color color){
Vector2 mp = {mouse_pos->x, mouse_pos->y}; //GetMousePosition(); TODO: Refactor my own vectors to raylib vectors
DrawCircleSector((Vector2){x,y},radius, start_angle, end_angle, 5, color); DrawCircleSector((Vector2){x,y},radius, start_angle, end_angle, 5, color);
return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
} }
-88
View File
@@ -1,88 +0,0 @@
#pragma once
#include "edge.h"
#include "node-manager.h"
#include "raylib.h"
#include <map>
#include <vector>
class ConnectionManager{
public:
ConnectionManager(NodeManager *nm) : nm(nm) {}
NodeManager *nm;
std::vector<Connection> connections;
std::map<int, int> counter;
void reset(){
counter.clear();
}
int next(int current, int last){
std::vector<Connection*> possible_connections;
std::vector<int> next_node_ids;
for(auto& c : connections){
if((c.node_id_start == current && c.start_end) || (c.node_id_end == current && c.end_start)) {
c.active = false;
possible_connections.push_back(&c);
next_node_ids.push_back( c.node_id_start == current ? c.node_id_end : c.node_id_start );
}
}
if(possible_connections.empty()) return -1;
int return_path = 0;
float angle = -1;
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->node_id_start == current ? n->node_id_end : n->node_id_start;
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()) {
counter[current] = 0;
} else {
counter[current] = (counter[current] + 1) % possible_connections.size();
return_path = counter[current];
}
}
if(nm->nodes.at(current).distributionMode == Distribution::RANDOM){
return_path = rand() % possible_connections.size();
}
possible_connections.at(return_path)->active = true;
return possible_connections.at(return_path)->node_id_start == current ? possible_connections.at(return_path)->node_id_end : possible_connections.at(return_path)->node_id_start;
}
void addConnection(int from, int to){
connections.emplace_back(nm, from, to);
}
void splitConnection(Connection *c){
Vec2D<float> center = c->node_start->position.center(c->node_end->position);
}
void drawConnections(Vec2D<float> *mouse_pos, Camera2D *cam){
std::erase_if(connections, [](Connection c){ return c.remove == true;});
for(auto& c : connections){
if(c.split) splitConnection(&c);
c.draw(mouse_pos, cam);
}
}
};
+2 -3
View File
@@ -1,7 +1,5 @@
#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
@@ -172,7 +170,8 @@ struct AppSettings{
// Graph // Graph
inline enum GraphItemType {NODE, EDGE} type; enum GraphItemType {NODE, EDGE};
enum NodeType {OSCNODE, MIDINODE};
// MIDI // MIDI
+7
View File
@@ -8,6 +8,7 @@ class Node;
class Edge : public GraphItem{ class Edge : public GraphItem{
public: public:
Edge() {}
Edge(std::shared_ptr<Node> start, std::shared_ptr<Node> end) : start(start), end(end) {} Edge(std::shared_ptr<Node> start, std::shared_ptr<Node> end) : start(start), end(end) {}
std::shared_ptr<Node> start; std::shared_ptr<Node> start;
@@ -24,7 +25,13 @@ class Edge : public GraphItem{
float connector_offset = 8.0f; float connector_offset = 8.0f;
float switches_offset = 25.0f; float switches_offset = 25.0f;
virtual bool GActive() {return active;}
std::shared_ptr<Node> getNextNode(std::shared_ptr<Node> origin){ std::shared_ptr<Node> getNextNode(std::shared_ptr<Node> origin){
return start == origin ? end : start; return start == origin ? end : start;
} }
void draw(Vec2D<float> mouse_pos, Camera2D cam) {
}
}; };
+3
View File
@@ -10,6 +10,9 @@ class GraphItem{
public: public:
std::vector<std::shared_ptr<GraphItem>> neighbors; std::vector<std::shared_ptr<GraphItem>> neighbors;
GraphItemType graphItemType;
virtual void draw(Vec2D<float> mouse, Camera2D cam) = 0; virtual void draw(Vec2D<float> mouse, Camera2D cam) = 0;
virtual GraphItemType getType() {return graphItemType;}
virtual ~GraphItem() = default; virtual ~GraphItem() = default;
}; };
+70 -40
View File
@@ -1,10 +1,14 @@
#pragma once #pragma once
#include "button.h"
#include "datatypes.h" #include "datatypes.h"
#include "graph-item.h" #include "graph-item.h"
#include "midi-node.h"
#include "node.h" #include "node.h"
#include "edge.h" #include "edge.h"
#include "raymath.h"
#include <algorithm> #include <algorithm>
#include <iostream>
#include <iterator> #include <iterator>
#include <map> #include <map>
#include <memory> #include <memory>
@@ -37,31 +41,53 @@ class GraphManager{
void copyNodes(std::vector<std::shared_ptr<Node>> nodes, Vec2D<float> position){ void copyNodes(std::vector<std::shared_ptr<Node>> nodes, Vec2D<float> position){
for(auto n: nodes){ for(auto n: nodes){
auto nc = std::make_shared<Node>(n); auto nc = std::make_shared<Node>(*n);
nc->position = position + nc->drag_offset; nc->position = position + nc->drag_offset;
nc->selected = true; nc->selected = true;
nodes.push_back(nc); nodes.push_back(nc);
} }
} }
void copyNode(std::shared_ptr<Node> n, Vec2D<float> position){ void copyNodes(std::vector<std::shared_ptr<MidiNode>> nodes, Vec2D<float> position){
auto nc = std::make_shared<Node>(n); for(auto n: nodes){
nc->setPosition(position); std::shared_ptr<MidiNode> nc = std::make_shared<MidiNode>(*n);
nc->position = position + nc->drag_offset;
nc->selected = true;
nodes.push_back(nc); nodes.push_back(nc);
} }
std::shared_ptr<Node> addNode(float x, float y){
return addNode(Vec2D<float>(x,y));
} }
std::shared_ptr<Node> addNode(Vec2D<float> position){ std::shared_ptr<Node> copyNode(std::shared_ptr<Node> n, Vec2D<float> position){
nodes.emplace_back(std::make_shared<Node>(position)); auto nc = std::make_shared<Node>(*n);
nc->setPosition(position);
nodes.push_back(nc);
return nc;
}
std::shared_ptr<MidiNode> copyNode(std::shared_ptr<MidiNode> n, Vec2D<float> position){
auto nc = std::make_shared<MidiNode>(*n);
nc->setPosition(position);
nodes.push_back(nc);
return nc;
}
/*std::shared_ptr<Node> addNode(float x, float y){*/
/* return addNode(Vec2D<float>(x,y));*/
/*}*/
/**/
/*std::shared_ptr<Node> addNode(Vec2D<float> position){*/
/* nodes.emplace_back(std::make_shared<Node>(position));*/
/* return nodes.back();*/
/*}*/
std::shared_ptr<Node> addMidiNode(Vec2D<float> position){
nodes.emplace_back(std::make_shared<MidiNode>(position));
return nodes.back(); return nodes.back();
} }
void setNodeMode(int mode){ void setNodeMode(int mode){
for(auto n: nodes){ for(auto n: nodes){
n->setMode(mode); n->SMode(mode);
} }
} }
@@ -110,22 +136,26 @@ class GraphManager{
} }
void addConnection(std::shared_ptr<Node> from, std::shared_ptr<Node> to){ void addConnection(std::shared_ptr<Node> from, std::shared_ptr<Node> to){
edges.emplace_back(std::make_shared<Edge>(from, to)); edges.emplace_back(std::make_shared<Edge>());
edges.back()->start = from;
edges.back()->end = to;
from->connections.push_back(edges.back());
to->connections.push_back(edges.back());
} }
void drawConnections(Vec2D<float> *mouse_pos, Camera2D *cam){ void drawEdges(Vec2D<float> mouse_pos, Camera2D cam){
// std::erase_if(connections, [](Connection c){ return c.remove == true;}); // std::erase_if(connections, [](Connection c){ return c.remove == true;});
for(auto& c : edges){ for(auto& c : edges){
Vec2D<float> v1_position = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->connector_offset); Vec2D<float> v1_position = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->connector_offset);
Vec2D<float> v2_position = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->connector_offset); Vec2D<float> v2_position = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->connector_offset);
float v1_v2_distance = v1_position.dist(&v2_position); float v1_v2_distance = v1_position.dist(&v2_position);
float midi_gate_v1 = Clamp((4.f / 1000.f) * c->start->midi_gate, 1.f, 4.f); float midi_gate_v1 = Clamp((4.f / 1000.f) * c->start->GGate(), 1.f, 4.f);
float midi_gate_v2 = Clamp((4.f / 1000.f) * c->end->midi_gate, 1.f, 4.f); float midi_gate_v2 = Clamp((4.f / 1000.f) * c->end->GGate(), 1.f, 4.f);
// Line with small connector circles // Line with small connector circles
Color col = {229, 181, 103, 255}; Color col = {229, 181, 103, 255};
if(c.active) col = {108, 153, 187, 255}; if(c->GActive()) col = {108, 153, 187, 255};
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col); DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col);
if(midi_gate_v1 == 4.0f) col = VS_COLOR_RED; if(midi_gate_v1 == 4.0f) col = VS_COLOR_RED;
@@ -135,9 +165,9 @@ class GraphManager{
if(midi_gate_v2 == 4.0f) col = VS_COLOR_RED; if(midi_gate_v2 == 4.0f) col = VS_COLOR_RED;
DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col); DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col);
if(v1_v2_distance < 100) c.switches_offset = v1_v2_distance/2.3f; if(v1_v2_distance < 100) c->switches_offset = v1_v2_distance/2.3f;
Vec2D<float> from_to_handle = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c.switches_offset); Vec2D<float> from_to_handle = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->switches_offset);
Vec2D<float> to_from_handle = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c.switches_offset); Vec2D<float> to_from_handle = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->switches_offset);
Vec2D<float> middle_handle = c->end->position - ((c->end->position - c->start->position))*0.4f; Vec2D<float> middle_handle = c->end->position - ((c->end->position - c->start->position))*0.4f;
Vec2D<float> middle_handle_2 = c->end->position - ((c->end->position - c->start->position))*0.6f; Vec2D<float> middle_handle_2 = c->end->position - ((c->end->position - c->start->position))*0.6f;
Vec2D<float> flip_handle = middle_handle + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*0.2, 0.f, 20.f) : 1.0f); Vec2D<float> flip_handle = middle_handle + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*0.2, 0.f, 20.f) : 1.0f);
@@ -150,58 +180,58 @@ class GraphManager{
unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.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, c->start_end ? (Color){120, 210, 115, opacity_from} : (Color){232, 50, 32, opacity_from} )) c->start_end = !c->start_end; if(ViButton(mouse_pos, from_to_handle.x, from_to_handle.y, 8.0f, c->pass_forward ? (Color){120, 210, 115, opacity_from} : (Color){232, 50, 32, opacity_from} )) c->pass_forward = !c->pass_forward;
if(ViButton(mouse_pos, to_from_handle.x, to_from_handle.y, 8.0f, c.end_start ? (Color){120, 210, 115, opacity_to} : (Color){232, 50, 32, opacity_to} )) c.end_start = !c.end_start; if(ViButton(mouse_pos, to_from_handle.x, to_from_handle.y, 8.0f, c->pass_backward ? (Color){120, 210, 115, opacity_to} : (Color){232, 50, 32, opacity_to} )) c->pass_backward = !c->pass_backward;
if(!c->start_end){ if(!c->pass_forward){
Vec2D<float> block_point1 = (v1_position - v2_position).norm().orth()*4.0f + from_to_handle; Vec2D<float> block_point1 = (v1_position - v2_position).norm().orth()*4.0f + from_to_handle;
Vec2D<float> block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + from_to_handle; Vec2D<float> block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + from_to_handle;
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_from}); DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_from});
} }
if(!c.end_start){ if(!c->pass_backward){
Vec2D<float> block_point1 = (v1_position - v2_position).norm().orth()*4.0f + to_from_handle; Vec2D<float> block_point1 = (v1_position - v2_position).norm().orth()*4.0f + to_from_handle;
Vec2D<float> block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + to_from_handle; Vec2D<float> block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + to_from_handle;
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_to}); DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_to});
} }
if(ViButton(mouse_pos, flip_handle.x, flip_handle.y, 8.0f, (Color){232, 50, 32, opacity} )) c.remove = true; if(ViButton(mouse_pos, flip_handle.x, flip_handle.y, 8.0f, (Color){232, 50, 32, opacity} )) c->remove = true;
if(ViButton(mouse_pos, flip_handle_2.x, flip_handle_2.y, 8.0f, (Color){232, 50, 32, opacity} )) c.split = true; if(ViButton(mouse_pos, flip_handle_2.x, flip_handle_2.y, 8.0f, (Color){232, 50, 32, opacity} )) c->split = true;
} }
} }
void drawNodes(Vec2D<float> *mouse_pos, Camera2D *camera){ void drawNodes(Vec2D<float> mouse_pos, Camera2D camera){
auto neighbors = nodes | std::ranges::views::values | std::ranges::views::filter([](Node n){ return !n.dragging && !n.selected;}) | std::ranges::to<std::vector<Node>>(); auto neighbors = nodes | std::ranges::views::filter([](std::shared_ptr<Node> n){ return !n->dragging && !n->selected;}) | std::ranges::to<std::vector<std::shared_ptr<Node>>>();
float min_d = 480; float min_d = 480;
for(auto& n : nodes | std::ranges::views::values ){ for(auto n : nodes){
if(n.dragging){ if(n->dragging){
std::sort(neighbors.begin(), neighbors.end(), [n](Node na, Node nb){ return na.position.dist(n.position) < nb.position.dist(n.position);}); std::sort(neighbors.begin(), neighbors.end(), [n](std::shared_ptr<Node> na, std::shared_ptr<Node> nb){ return na->position.dist(n->position) < nb->position.dist(n->position);});
if(neighbors.size() > 1){ if(neighbors.size() > 1){
min_d = neighbors.front().position.dist(n.position); min_d = neighbors.front()->position.dist(n->position);
n.neighbor = &nodes.at(neighbors.at(1).id); n->neighbor = neighbors.at(1);
int i = 0; int i = 0;
for(auto it = (neighbors.begin()); it != neighbors.end(); it++, i++){ for(auto nb : neighbors){
float d = it->position.dist(n.position); float d = nb->position.dist(n->position);
if(d > 0 && d < min_d*1.5 && d < 960) { if(d > 0 && d < min_d*1.5 && d < 960) {
std::string frac = MIDI::Fractions.at((int)Clamp(round(d/60) - 1, 0, 31)); std::string frac = MIDI::Fractions.at((int)Clamp(round(d/60) - 1, 0, 31));
Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f); Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f);
Vector2 text_length_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f); Vector2 text_length_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f);
Vec2D<float> middle_handle = it->position + (n.position - it->position) * ((d - text_length.x)*0.5f)/d; Vec2D<float> middle_handle = nb->position + (n->position - nb->position) * ((d - text_length.x)*0.5f)/d;
Vec2D<float> middle_handle_frac = it->position + (n.position - it->position) * ((d - text_length_frac.x)*0.5f)/d; Vec2D<float> middle_handle_frac = nb->position + (n->position - nb->position) * ((d - text_length_frac.x)*0.5f)/d;
Vec2D<float> text_position = middle_handle + (it->position - n.position).norm().orth() * 12.0f; Vec2D<float> text_position = middle_handle + (nb->position - n->position).norm().orth() * 12.0f;
Vec2D<float> text_position_frac = middle_handle_frac - (it->position - n.position).norm().orth() * 4.0f; Vec2D<float> text_position_frac = middle_handle_frac - (nb->position - n->position).norm().orth() * 4.0f;
float rotation = Vector2Angle((Vector2){1,0}, (n.position - it->position)) * RAD2DEG; float rotation = Vector2Angle((Vector2){1,0}, (n->position - nb->position)) * RAD2DEG;
DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
if(i == 0 && IsKeyDown(KEY_LEFT_SHIFT)) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); if(i == 0 && IsKeyDown(KEY_LEFT_SHIFT)) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
DrawLineV(n.position, it->position, VS_COLOR_PINK); DrawLineV(n->position, nb->position, VS_COLOR_PINK);
} }
} }
} }
} }
n.draw(mouse_pos, camera); n->draw(mouse_pos, camera);
} }
} }
+91 -88
View File
@@ -6,7 +6,10 @@
* *
*/ */
#include "midi-node.h"
#include <iterator>
#include <memory> #include <memory>
#include <vector>
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#include "datatypes.h" #include "datatypes.h"
@@ -68,17 +71,19 @@ 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.gm.addNode((float)i * app.settings.grid*4 + 10 * app.settings.grid, 5 * app.settings.grid*4); app.gm.addMidiNode(Vec2D<float>{(float)i * app.settings.grid*4 + 5 * app.settings.grid, 5 * app.settings.grid*4});
} }
for(int i = 3; i >= 0; --i){ for(int i = 3; i >= 0; --i){
app.gm.addNode((float)i * app.settings.grid*4 + 10 * app.settings.grid, 6 * app.settings.grid*4); app.gm.addMidiNode(Vec2D<float>{(float)i * app.settings.grid*4 + 5 * app.settings.grid, 6 * app.settings.grid*4});
} }
for(int i = 0; i < 8; ++i){ for(int i = 0; i < 8; ++i){
app.gm.addConnection(app.gm.nodes[i].id, app.gm.nodes[(i+1) % 8].id); app.gm.addConnection(app.gm.nodes[i], app.gm.nodes[(i+1) % 8]);
} }
app.sm.addSignalAtNode((app.gm.nodes | std::views::values).front().id); std::cout << app.gm.nodes[0]->getNodeType() << std::endl;
app.sm.addSignalAtNode(app.gm.nodes.front());
app.sm.startSignalThread(); app.sm.startSignalThread();
enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES}; enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES};
@@ -87,6 +92,7 @@ int main(){
Vec2D<float> select_start; Vec2D<float> select_start;
Rectangle selection; Rectangle selection;
std::vector<std::shared_ptr<Node>> copied_nodes;
while(!WindowShouldClose()){ while(!WindowShouldClose()){
@@ -111,17 +117,15 @@ 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);
std::vector<std::shared_ptr<Node>> copied_nodes; auto dragging_nodes = app.gm.nodes | std::ranges::views::filter([](std::shared_ptr<Node> n) { return n->dragging;});
auto connecting_nodes = app.gm.nodes | std::ranges::views::filter([](std::shared_ptr<Node> n) { return n->connecting;});
auto selected_nodes = app.gm.nodes | std::ranges::views::filter([](std::shared_ptr<Node> n) { return n->selected && !n->dragging;}) | std::ranges::to<std::vector<std::shared_ptr<Node>>>();
auto hovering_nodes = app.gm.nodes | std::ranges::views::filter([&mouse_pos](std::shared_ptr<Node> n) { return CheckCollisionPointCircle(mouse_pos, n->position, n->radius);});
auto hovering_connectors = app.gm.nodes | std::ranges::views::filter([&mouse_pos](std::shared_ptr<Node> n) { return CheckCollisionPointCircle(mouse_pos, (n->position - ((n->position - mouse_pos)).norm() * (n->radius + 14.0f)), 8.0f);});
auto dragging_nodes = app.gm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n) { return n.dragging;}); for(auto &n : app.gm.nodes ){
auto connecting_nodes = app.gm.nodes | std::ranges::views::values| std::ranges::views::filter([](Node n) { return n.connecting;}); if(hovering_nodes.empty()) n->hovering = false;
auto selected_nodes = app.gm.nodes | std::ranges::views::values| std::ranges::views::filter([](Node n) { return n.selected && !n.dragging;}); if(hovering_connectors.empty()) n->hover_connect = false;
auto hovering_nodes = app.gm.nodes | std::ranges::views::values| std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, n.position, n.radius);});
auto hovering_connectors = app.gm.nodes | std::ranges::views::values| 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);});
for(auto &n : app.gm.nodes | std::ranges::views::values){
if(hovering_nodes.empty()) n.hovering = false;
if(hovering_connectors.empty()) n.hover_connect = false;
} }
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;
@@ -145,8 +149,8 @@ int main(){
switch(istate){ switch(istate){
case InteractionState::HOVER_CANVAS: case InteractionState::HOVER_CANVAS:
{ {
for(auto &n : app.gm.nodes | std::ranges::views::values){ for(auto &n : app.gm.nodes){
n.hover_connect = false; n->hover_connect = false;
} }
if(mouse_right_down) { if(mouse_right_down) {
camera.target = Vector2Add(camera.target, delta); camera.target = Vector2Add(camera.target, delta);
@@ -164,22 +168,22 @@ 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 : app.gm.nodes | std::views::values){ for(auto& n : app.gm.nodes){
if(CheckCollisionPointRec(n.position, selection)) { if(CheckCollisionPointRec(n->position, selection)) {
n.in_rect = true; n->in_rect = true;
} else { } else {
n.in_rect = false; n->in_rect = false;
} }
} }
} }
if(mouse_released){ if(mouse_released){
for(auto& n : app.gm.nodes | std::views::values){ for(auto& n : app.gm.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;
} else { } else {
if(!IsKeyDown(KEY_LEFT_SHIFT)) n.selected = false; if(!IsKeyDown(KEY_LEFT_SHIFT)) n->selected = false;
} }
} }
selection = (Rectangle){0,0,0,0}; selection = (Rectangle){0,0,0,0};
@@ -190,45 +194,45 @@ int main(){
{ {
if(mouse_clicked) { if(mouse_clicked) {
if(IsKeyDown(KEY_LEFT_SHIFT)) { if(IsKeyDown(KEY_LEFT_SHIFT)) {
hovering_nodes.front().selected = true; hovering_nodes.front()->selected = true;
} else { } else {
hovering_nodes.front().dragging = true; hovering_nodes.front()->dragging = true;
hovering_nodes.front().drag_offset = hovering_nodes.front().position - mouse_pos; hovering_nodes.front()->drag_offset = hovering_nodes.front()->position - mouse_pos;
} }
} }
if(mouse_right_clicked) hovering_nodes.front().config = true; if(mouse_right_clicked) hovering_nodes.front()->config = true;
break; break;
} }
case InteractionState::DRAG_NODE: case InteractionState::DRAG_NODE:
{ {
if(!dragging_nodes.empty()){ if(!dragging_nodes.empty()){
for(auto &n : selected_nodes){ for(auto &n : selected_nodes){
if(!n.picked_up) n.drag_offset = n.position - dragging_nodes.front().position; if(!n->picked_up) n->drag_offset = n->position - dragging_nodes.front()->position;
n.picked_up = true; n->picked_up = true;
} }
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) / app.settings.grid) * app.settings.grid; 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 {
dragging_nodes.front().position = mouse_pos + dragging_nodes.front().drag_offset; dragging_nodes.front()->position = mouse_pos + dragging_nodes.front()->drag_offset;
} }
for(auto &n : selected_nodes){ for(auto &n : selected_nodes){
n.position = dragging_nodes.front().position + n.drag_offset; n->position = dragging_nodes.front()->position + n->drag_offset;
} }
if(mouse_released) { if(mouse_released) {
for(auto &n : dragging_nodes){ for(auto &n : dragging_nodes){
n.dragging = false; n->dragging = false;
n.picked_up = false; n->picked_up = false;
} }
for(auto &n : selected_nodes){ for(auto &n : selected_nodes){
n.picked_up = false; n->picked_up = false;
n.dragging = false; n->dragging = false;
} }
} }
} }
@@ -237,116 +241,115 @@ int main(){
case InteractionState::HOVER_CONNECTOR: case InteractionState::HOVER_CONNECTOR:
{ {
if(!hovering_connectors.empty()){ if(!hovering_connectors.empty()){
hovering_connectors.front().hover_connect = true; hovering_connectors.front()->hover_connect = true;
if(mouse_clicked) hovering_connectors.front().connecting = true; if(mouse_clicked) hovering_connectors.front()->connecting = true;
} }
break; break;
} }
case InteractionState::CONNECT_NODE: case InteractionState::CONNECT_NODE:
{ {
Vec2D<float> connector_position = connecting_nodes.front().position - ((connecting_nodes.front().position - mouse_pos)).norm() * (connecting_nodes.front().radius + 14.0f); Vec2D<float> connector_position = connecting_nodes.front()->position - ((connecting_nodes.front()->position - mouse_pos)).norm() * (connecting_nodes.front()->radius + 14.0f);
if(connecting_nodes.front().connecting && mouse_down){ if(connecting_nodes.front()->connecting && mouse_down){
DrawLine(connector_position.x, connector_position.y, mouse_pos.x, mouse_pos.y, (Color){229, 181, 103, 255}); DrawLine(connector_position.x, connector_position.y, mouse_pos.x, mouse_pos.y, (Color){229, 181, 103, 255});
connecting_nodes.front().hovering = true; connecting_nodes.front()->hovering = true;
connecting_nodes.front().hover_connect = true; connecting_nodes.front()->hover_connect = true;
} }
if(!hovering_connectors.empty()) { if(!hovering_connectors.empty()) {
hovering_connectors.front().hovering = true; hovering_connectors.front()->hovering = true;
hovering_connectors.front().hover_connect = true; hovering_connectors.front()->hover_connect = true;
} }
if(!hovering_nodes.empty()) hovering_nodes.front().hovering = true; if(!hovering_nodes.empty()) hovering_nodes.front()->hovering = true;
if(mouse_released) { if(mouse_released) {
if(&hovering_nodes.front() != &connecting_nodes.front() && &connecting_nodes.front() != &hovering_connectors.front()){ if(&hovering_nodes.front() != &connecting_nodes.front() && &connecting_nodes.front() != &hovering_connectors.front()){
if(!hovering_nodes.empty()){ if(!hovering_nodes.empty()){
app.gm.addConnection(connecting_nodes.front().id, hovering_nodes.front().id); app.gm.addConnection(connecting_nodes.front(), hovering_nodes.front());
} else if(!hovering_connectors.empty()){ } else if(!hovering_connectors.empty()){
app.gm.addConnection(connecting_nodes.front().id, hovering_connectors.front().id); app.gm.addConnection(connecting_nodes.front(), hovering_connectors.front());
} else { } else {
int id = app.gm.addNode(mouse_pos.x, mouse_pos.y); std::shared_ptr<Node> new_node = app.gm.addMidiNode(mouse_pos);
app.gm.addConnection(connecting_nodes.front().id, id); app.gm.addConnection(connecting_nodes.front(), new_node);
} }
} }
connecting_nodes.front().connecting = false; connecting_nodes.front()->connecting = false;
istate = InteractionState::HOVER_CANVAS; istate = InteractionState::HOVER_CANVAS;
} }
break; break;
} }
case InteractionState::DELETE_SELECTED_NODES: case InteractionState::DELETE_SELECTED_NODES:
{ {
for(auto &n : selected_nodes){ app.removeNodes(selected_nodes | std::ranges::to<std::vector<std::shared_ptr<Node>>>());
n.erase = true;
}
app.removeNodes();
break; break;
} }
case InteractionState::COPY_SELECTED_NODES: case InteractionState::COPY_SELECTED_NODES:
{ {
std::copy(selected_nodes.begin(), selected_nodes.end(), copied_nodes.begin()); std::ranges::copy(selected_nodes.begin(), selected_nodes.end(), std::back_inserter(copied_nodes));
break; break;
} }
case InteractionState::PASTE_SELECTED_NODES: case InteractionState::PASTE_SELECTED_NODES:
{ {
for(auto &n: copied_nodes){ for(auto &n: copied_nodes){
n.drag_offset = (n.position - copied_nodes.front().position); n->drag_offset = (n->position - copied_nodes.front()->position);
} }
// app.gm.copyNodes(mouse_pos); app.copyNodesAndConnections(copied_nodes, mouse_pos);
//app.gm.copyNodes(selected_nodes, mouse_pos); copied_nodes.clear();
app.copyNodesAndConnections(mouse_pos);
break; break;
} }
}; };
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() && hovering_nodes.front()->getNodeType() == NodeType::MIDINODE) {
std::shared_ptr<MidiNode> midiNode = std::dynamic_pointer_cast<MidiNode>(hovering_nodes.front());
if(IsKeyDown(KEY_LEFT_CONTROL) && !IsKeyDown(KEY_LEFT_ALT)){
switch(app.settings.mode){ switch(app.settings.mode){
case 0:{ case 0:{
hovering_nodes.front().midi_note += wheel; midiNode->midi_note += wheel;
break;} break;}
case 1:{ case 1:{
hovering_nodes.front().midi_cc += wheel; midiNode->midi_cc += wheel;
break;} break;}
case 2:{ case 2:{
hovering_nodes.front().midi_pitch_bend += wheel; midiNode->midi_pitch_bend += wheel;
break;} break;}
}; };
if(hovering_nodes.front().midi_note < 0 ) hovering_nodes.front().midi_note = app.sm.midi.midiNotes.size()-1; if(midiNode->midi_note < 0 ) midiNode->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(midiNode->midi_note >= app.sm.midi.midiNotes.size() ) midiNode->midi_note = 0;
if(hovering_nodes.front().midi_cc < 0 ) hovering_nodes.front().midi_cc = 127; if(midiNode->midi_cc < 0 ) midiNode->midi_cc = 127;
if(hovering_nodes.front().midi_cc > 127 ) hovering_nodes.front().midi_cc = 0; if(midiNode->midi_cc > 127 ) midiNode->midi_cc = 0;
if(hovering_nodes.front().midi_pitch_bend < 0 ) hovering_nodes.front().midi_pitch_bend = 0; if(midiNode->midi_pitch_bend < 0 ) midiNode->midi_pitch_bend = 0;
if(hovering_nodes.front().midi_pitch_bend > 16383 ) hovering_nodes.front().midi_pitch_bend = 16383; if(midiNode->midi_pitch_bend > 16383 ) midiNode->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; midiNode->midi_velocity += wheel;
if(hovering_nodes.front().midi_velocity < 0 ) hovering_nodes.front().midi_velocity = 127; if(midiNode->midi_velocity < 0 ) midiNode->midi_velocity = 127;
if(hovering_nodes.front().midi_velocity > 127 ) hovering_nodes.front().midi_velocity = 0; if(midiNode->midi_velocity > 127 ) midiNode->midi_velocity = 0;
} else if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_ALT)) { } else if(!hovering_nodes.empty() && IsKeyDown(KEY_LEFT_ALT)) {
switch(app.settings.mode){ switch(app.settings.mode){
case 0:{ case 0:{
float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f); float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f);
hovering_nodes.front().midi_gate += incr; midiNode->midi_gate += incr;
if(hovering_nodes.front().midi_gate < 0 ) hovering_nodes.front().midi_gate = 0; if(midiNode->midi_gate < 0 ) midiNode->midi_gate = 0;
break;} break;}
case 1:{ case 1:{
hovering_nodes.front().midi_cc_value += wheel; midiNode->midi_cc_value += wheel;
if(hovering_nodes.front().midi_cc_value < 0 ) hovering_nodes.front().midi_cc_value = 0; if(midiNode->midi_cc_value < 0 ) midiNode->midi_cc_value = 0;
if(hovering_nodes.front().midi_cc_value > 127 ) hovering_nodes.front().midi_cc_value = 127; if(midiNode->midi_cc_value > 127 ) midiNode->midi_cc_value = 127;
break;} break;}
case 2:{ case 2:{
float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f); 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; midiNode->midi_pitch_bend += incr;
if(hovering_nodes.front().midi_pitch_bend < 0 ) hovering_nodes.front().midi_pitch_bend = 0; if(midiNode->midi_pitch_bend < 0 ) midiNode->midi_pitch_bend = 0;
if(hovering_nodes.front().midi_pitch_bend > 16383 ) hovering_nodes.front().midi_pitch_bend = 16383; if(midiNode->midi_pitch_bend > 16383 ) midiNode->midi_pitch_bend = 16383;
break;} break;}
}; };
} else { }
}
if(hovering_nodes.empty()){
Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera); Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);
camera.offset = GetMousePosition(); camera.offset = GetMousePosition();
camera.target = mouseWorldPos; camera.target = mouseWorldPos;
@@ -362,7 +365,7 @@ int main(){
} }
} }
app.draw(&mouse_pos, &camera); app.draw(mouse_pos, camera);
EndMode2D(); EndMode2D();
+14 -2
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "datatypes.h"
#include "node.h" #include "node.h"
#include "raymath.h" #include "raymath.h"
#include <map> #include <map>
@@ -16,6 +17,11 @@ class MidiNode : public Node{
public: public:
MidiNode() {}
MidiNode(Vec2D<float> position) : Node(position) {}
NodeType nodeType = NodeType::MIDINODE;
bool send_note = true; bool send_note = true;
bool send_cc = false; bool send_cc = false;
bool send_pc = false; bool send_pc = false;
@@ -55,20 +61,26 @@ class MidiNode : public Node{
float time = 0; float time = 0;
float last = 0; float last = 0;
virtual NodeType getNodeType() override {return nodeType;}
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;
} }
void trigger(){ void trigger() override {
triggered = true; triggered = true;
start = GetTime(); start = GetTime();
fade = midi_gate; fade = midi_gate;
} }
void setMode(int _mode) override{ void SMode(int _mode) override{
mode = _mode; mode = _mode;
} }
int Ggate(){
return midi_gate;
}
void draw(Vec2D<float> mouse, Camera2D cam) override { void draw(Vec2D<float> mouse, Camera2D cam) override {
last = time; last = time;
time = GetTime(); time = GetTime();
+1
View File
@@ -32,6 +32,7 @@ class Movable{
bool erase = false; bool erase = false;
virtual void setPosition(Vec2D<float> _position) {position = _position;} virtual void setPosition(Vec2D<float> _position) {position = _position;}
virtual Vec2D<float> getPosition() {return position;};
virtual void update(double frametime) {}; virtual void update(double frametime) {};
virtual void update() {}; virtual void update() {};
}; };
-106
View File
@@ -1,106 +0,0 @@
#pragma once
#include "datatypes.h"
#include "node.h"
#include "raylib.h"
#include "raymath.h"
#include <algorithm>
#include <iterator>
#include <random>
#include <ranges>
#include <utility>
#include <vector>
class NodeManager{
public:
NodeManager() {}
std::map<int, Node> nodes;
std::vector<int> keys;
int iterator = 0;
Node* node(int id){
return &nodes.at(id);
}
int getRandomNode(){
std::vector<int> o;
std::ranges::sample(keys, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
return o.front();
}
void copyNodes(Vec2D<float> position){
for(auto n: nodes | std::ranges::views::filter([](std::pair<int, Node> n){ return n.second.copied;})){
n.second.position = position + n.second.drag_offset;
n.second.id = iterator;
n.second.copied = false;
n.second.selected = true;
nodes.insert(std::make_pair(iterator, n.second));
keys.push_back(iterator);
iterator++;
}
}
int copyNode(int id, Vec2D<float> position){
Node n = nodes.at(id);
n.position = position;
n.id = iterator;
nodes.insert(std::make_pair(iterator, n));
keys.push_back(iterator);
iterator++;
return iterator - 1;
}
void setNodeMode(int mode){
for(auto &n : nodes | std::ranges::views::values){
n.mode = mode;
}
}
int addNode(float x, float y){
return addNode(Vec2D<float>(x,y));
}
int addNode(Vec2D<float> position){
nodes.emplace(std::make_pair(iterator, Node(iterator, position, 15.0f)));
keys.push_back(iterator);
iterator++;
return iterator - 1;
}
void drawNodes(Vec2D<float> *mouse_pos, Camera2D *camera){
auto neighbors = nodes | std::ranges::views::values | std::ranges::views::filter([](Node n){ return !n.dragging && !n.selected;}) | std::ranges::to<std::vector<Node>>();
float min_d = 480;
for(auto& n : nodes | std::ranges::views::values ){
if(n.dragging){
std::sort(neighbors.begin(), neighbors.end(), [n](Node na, Node nb){ return na.position.dist(n.position) < nb.position.dist(n.position);});
if(neighbors.size() > 1){
min_d = neighbors.front().position.dist(n.position);
n.neighbor = &nodes.at(neighbors.at(1).id);
int i = 0;
for(auto it = (neighbors.begin()); it != neighbors.end(); it++, i++){
float d = it->position.dist(n.position);
if(d > 0 && d < min_d*1.5 && d < 960) {
std::string frac = MIDI::Fractions.at((int)Clamp(round(d/60) - 1, 0, 31));
Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f);
Vector2 text_length_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f);
Vec2D<float> middle_handle = it->position + (n.position - it->position) * ((d - text_length.x)*0.5f)/d;
Vec2D<float> middle_handle_frac = it->position + (n.position - it->position) * ((d - text_length_frac.x)*0.5f)/d;
Vec2D<float> text_position = middle_handle + (it->position - n.position).norm().orth() * 12.0f;
Vec2D<float> text_position_frac = middle_handle_frac - (it->position - n.position).norm().orth() * 4.0f;
float rotation = Vector2Angle((Vector2){1,0}, (n.position - it->position)) * RAD2DEG;
DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
if(i == 0 && IsKeyDown(KEY_LEFT_SHIFT)) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
DrawLineV(n.position, it->position, VS_COLOR_PINK);
}
}
}
}
n.draw(mouse_pos, camera);
}
}
};
+10 -2
View File
@@ -15,7 +15,9 @@ class Node : public Movable, public GraphItem{
Node(float x, float y) : Movable(Vec2D<float>(x, y), 0.0f) {} Node(float x, float y) : Movable(Vec2D<float>(x, y), 0.0f) {}
Node(Vec2D<float> p) : Movable(p, 0.0f) {} Node(Vec2D<float> p) : Movable(p, 0.0f) {}
Node *neighbor = nullptr; NodeType nodeType;
std::shared_ptr<Node> neighbor;
std::vector<std::shared_ptr<Edge>> connections; std::vector<std::shared_ptr<Edge>> connections;
@@ -24,5 +26,11 @@ class Node : public Movable, public GraphItem{
float radius = 15.0f; float radius = 15.0f;
bool config = false; bool config = false;
virtual void setMode(int mode) = 0; virtual NodeType getNodeType() {return nodeType;}
virtual void SMode(int mode) {};
virtual int GGate() {return 0;};
virtual int GActive() {return 0;};
virtual void trigger() {};
void draw(Vec2D<float> mouse_pos, Camera2D cam) {}
}; };
+27 -24
View File
@@ -2,10 +2,12 @@
#include "datatypes.h" #include "datatypes.h"
#include "graph-manager.h" #include "graph-manager.h"
#include "midi-node.h"
#include "signal.h" #include "signal.h"
#include "midi.h" #include "midi.h"
#include <chrono> #include <chrono>
#include <memory>
#include <thread> #include <thread>
class SignalManager{ class SignalManager{
@@ -19,7 +21,7 @@ class SignalManager{
std::mutex *mutex; std::mutex *mutex;
GraphManager *gm; GraphManager *gm;
std::vector<Signal> signals; std::vector<std::shared_ptr<Signal>> signals;
bool loop = true; bool loop = true;
bool play = false; bool play = false;
@@ -39,9 +41,9 @@ class SignalManager{
void reset(){ void reset(){
for(auto &s : signals){ for(auto &s : signals){
s.position = gm->node(s.start)->position + Vec2D<float>{0.1, 0.1}; s->position = s->start->position + Vec2D<float>{0.1, 0.1};
s.next = s.start; s->next = s->start;
s.last = s.start; s->last = s->start;
} }
gm->reset(); gm->reset();
} }
@@ -55,12 +57,12 @@ class SignalManager{
loop = false; loop = false;
} }
void addSignalAtNode(int node_id){ void addSignalAtNode(std::shared_ptr<Node> node){
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(gm->node(node_id)->position.x+1, gm->node(node_id)->position.y+1, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea! signals.emplace_back(std::make_shared<Signal>(node->position, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea!
signals.back().next = node_id; signals.back()->next = node;
signals.back().last = node_id; signals.back()->last = node;
signals.back().start = node_id; signals.back()->start = node;
} }
void removeSignal(int n){ void removeSignal(int n){
@@ -75,22 +77,23 @@ class SignalManager{
mutex->lock(); mutex->lock();
if(play){ if(play){
for(auto& s : signals){ for(auto& s : signals){
s.direction = (gm->node(s.next)->position - s.position).norm(); s->direction = (s->next->position - s->position).norm();
s.update(diff.count()); s->update(diff.count());
if(s.position.dist(&gm->node(s.next)->position) < 0.6f) { if(s->position.dist(s->next->position) < 0.6f) {
int n = gm->next(s.next, s.last); std::shared_ptr<Node> next_node = gm->next(s->next, s->last);
gm->triggerNode(s.next); s->next->trigger();
if(n != s.next && n != -1) { if(next_node != s->next && next_node != std::shared_ptr<Node>(nullptr) && s->next->getNodeType() == NodeType::MIDINODE) {
for(auto &m : gm->node(s.next)->midi_outs){ auto midinode = std::dynamic_pointer_cast<MidiNode>(s->next);
for(auto &m : midinode->midi_outs){
if(m.second.enabled) { if(m.second.enabled) {
if(gm->node(s.next)->send_note) midi.note(m.second.i, gm->node(s.next)->midi_note_channel, gm->node(s.next)->midi_note, gm->node(s.next)->midi_velocity, gm->node(s.next)->midi_gate); if(midinode->send_note) midi.note(m.second.i, midinode->midi_note_channel, midinode->midi_note, midinode->midi_velocity, midinode->midi_gate);
if(gm->node(s.next)->send_cc) midi.cc(m.second.i, gm->node(s.next)->midi_cc_channel, gm->node(s.next)->midi_cc, gm->node(s.next)->midi_cc_value); if(midinode->send_cc) midi.cc(m.second.i, midinode->midi_cc_channel, midinode->midi_cc, midinode->midi_cc_value);
if(gm->node(s.next)->send_pitch_bend) midi.pitch_bend(m.second.i, gm->node(s.next)->midi_pitch_bend_channel, gm->node(s.next)->midi_pitch_bend); if(midinode->send_pitch_bend) midi.pitch_bend(m.second.i, midinode->midi_pitch_bend_channel, midinode->midi_pitch_bend);
} }
} }
s.last = s.next; s->last = s->next;
s.next = n; s->next = next_node;
} }
} }
} }
@@ -102,10 +105,10 @@ class SignalManager{
} }
} }
void drawSignals(Vec2D<float> *mouse_pos, Camera2D *camera){ void drawSignals(Vec2D<float> mouse_pos, Camera2D camera){
for(auto& s : signals){ for(auto s : signals){
mutex->lock(); mutex->lock();
s.draw(mouse_pos, camera); s->draw(mouse_pos, camera);
mutex->unlock(); mutex->unlock();
} }
} }
+8 -9
View File
@@ -1,26 +1,25 @@
#pragma once #pragma once
#include <memory>
#include <raylib.h> #include <raylib.h>
#include "datatypes.h" #include "datatypes.h"
#include "moveable.h" #include "moveable.h"
#include "node.h"
class Signal : public Movable{ class Signal : public Movable{
public: public:
Signal(); Signal();
Signal(float x, float y, float r, float _speed, Color color) : Movable(Vec2D<float>(x, y), Vec2D<float>(0,0), _speed), radius(r), color(color) {} Signal(Vec2D<float> position, float r, float _speed, Color color) : Movable(position, Vec2D<float>(0,0), _speed), radius(r), color(color) {}
int id = 0; std::shared_ptr<Node> next;
std::shared_ptr<Node> last;
std::shared_ptr<Edge> edge;
int next; std::shared_ptr<Node> start;
int last;
int start;
bool at_target = false; bool at_target = false;
int target_node_id = 1;
int source_node_id = 0;
float radius; float radius;
@@ -35,7 +34,7 @@ class Signal : public Movable{
position += direction.norm() * speed * multiplier * (float)t_delta / 1000000.0f; position += direction.norm() * speed * multiplier * (float)t_delta / 1000000.0f;
} }
void draw(Vec2D<float> *mouse, Camera2D *cam) { void draw(Vec2D<float> mouse, Camera2D cam) {
DrawCircle(position.x, position.y, radius, color); DrawCircle(position.x, position.y, radius, color);
} }
}; };
+47 -56
View File
@@ -3,11 +3,13 @@
#include "edge.h" #include "edge.h"
#include "datatypes.h" #include "datatypes.h"
#include "graph-manager.h" #include "graph-manager.h"
#include "midi-node.h"
#include "signal-manager.h" #include "signal-manager.h"
#include "ui.h" #include "ui.h"
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <memory>
#include <ranges> #include <ranges>
#include <vector> #include <vector>
@@ -30,100 +32,89 @@ class AppState{
AppUI ui; AppUI ui;
void updateMidiPorts(){ void updateMidiPorts(){
for(auto&n : gm.nodes | std::views::values){ for(auto&n : gm.nodes | std::ranges::views::filter([](std::shared_ptr<Node> n){return n->getNodeType() == NodeType::MIDINODE;})){
auto nc = std::dynamic_pointer_cast<MidiNode>(n);
for(auto& mo : sm.midi.midi_out_ports){ for(auto& mo : sm.midi.midi_out_ports){
if(!n.midi_outs.contains(mo.number) && mo.enabled){ if(!nc->midi_outs.contains(mo.number) && mo.enabled){
n.midi_outs[mo.number] = {mo.number, mo.port.port_name, false}; nc->midi_outs[mo.number] = {mo.number, mo.port.port_name, false};
} }
if(n.midi_outs.contains(mo.number) && !mo.enabled){ if(nc->midi_outs.contains(mo.number) && !mo.enabled){
n.midi_outs.erase(mo.number); nc->midi_outs.erase(mo.number);
} }
} }
} }
} }
void copyNodesAndConnections(Vec2D<float> position){ void copyNodesAndConnections(std::vector<std::shared_ptr<Node>> nodes, Vec2D<float> position){
auto copy_nodes_ids = gm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n){return n.copied;}) | std::views::transform([](Node n){return n.id;}) | std::ranges::to<std::vector<int>>();
std::vector<Edge> copy_connections; std::vector<std::shared_ptr<Edge>> copy_connections;
std::ranges::copy_if(gm.connections, std::back_inserter(copy_connections), [copy_nodes_ids](Edge c){return std::ranges::contains(copy_nodes_ids, c.node_id_start) && std::ranges::contains(copy_nodes_ids, c.node_id_end);}); for(auto n : nodes){
std::ranges::copy_if(n->connections.begin(), n->connections.end(), std::back_inserter(copy_connections), [nodes](std::shared_ptr<Edge> e){ return std::ranges::contains(nodes, e->start) && std::ranges::contains(nodes, e->end);});
}
for(auto &n : copy_nodes_ids){ for(auto n : nodes){
int old_id = n; std::shared_ptr<Node> old_node = n;
int new_id = gm.copyNode(n, position + gm.nodes[n].drag_offset); std::shared_ptr<Node> new_node = gm.copyNode(n, position + n->drag_offset);
gm.nodes[new_id].copied = false; new_node->copied = false;
gm.nodes[new_id].selected = true; new_node->selected = true;
for(auto &c : copy_connections){ for(auto &c : copy_connections){
if(c.node_id_start == old_id) c.node_id_start = new_id; if(c->start == old_node) c->start = new_node;
if(c.node_id_end == old_id) c.node_id_end = new_id; if(c->end == old_node) c->end = new_node;
} }
} }
gm.connections.insert(gm.connections.end(), copy_connections.cbegin(), copy_connections.cend()); gm.edges.insert(gm.edges.end(), copy_connections.cbegin(), copy_connections.cend());
} }
void removeNodes(){ void removeNodes(std::vector<std::shared_ptr<Node>> nodes){
for(auto &n : gm.nodes){ for(auto n : gm.nodes){
n.second.highlighted = false; n->highlighted = false;
} }
auto erase_nodes = gm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n){return n.erase;}); auto erase_connections = gm.edges | std::ranges::views::filter([nodes](std::shared_ptr<Edge> c){ return std::ranges::contains(nodes, c->start) || std::ranges::contains(nodes, c->end);});
std::vector<int> erase_nodes_ids; std::vector<std::shared_ptr<Node>> adjacent_nodes;
for(auto &e : erase_nodes){
erase_nodes_ids.push_back(e.id); for(auto c : erase_connections){
if(!c->start->selected) adjacent_nodes.push_back(c->start);
if(!c->end->selected) adjacent_nodes.push_back(c->end);
} }
auto erase_connections = gm.connections | std::ranges::views::filter([erase_nodes_ids](Edge c){ return std::ranges::contains(erase_nodes_ids, c.node_id_start) || std::ranges::contains(erase_nodes_ids, c.node_id_end);}); auto reroute_signals = sm.signals | std::ranges::views::filter([nodes](std::shared_ptr<Signal> s){return std::ranges::contains(nodes, s->next);});
std::vector<int> adjacent_nodes_ids; for(auto s : reroute_signals){
for(auto &c : erase_connections){
if(!gm.nodes.at(c.node_id_start).selected) adjacent_nodes_ids.push_back(c.node_id_start);
if(!gm.nodes.at(c.node_id_end).selected) adjacent_nodes_ids.push_back(c.node_id_end);
}
auto reroute_signals = sm.signals | std::ranges::views::filter([erase_nodes_ids](Signal s){
return std::ranges::contains(erase_nodes_ids, s.next);
});
for(auto &s : reroute_signals){
float dist = 10000000; float dist = 10000000;
int next_id = -1; std::shared_ptr<Node> next_node;
for(int i : adjacent_nodes_ids){ for(auto n : adjacent_nodes){
if(gm.nodes.at(i).position.dist(&s.position) < dist) { if(n->position.dist(s->position) < dist) {
dist = gm.nodes.at(i).position.dist(&s.position); dist = n->position.dist(s->position);
next_id = i; next_node = n;
} }
} }
s.next = next_id; s->next = next_node;
s.last = next_id; s->last = next_node;
} }
auto rebase_signals = sm.signals | std::ranges::views::filter([erase_nodes_ids](Signal s){ auto rebase_signals = sm.signals | std::ranges::views::filter([nodes](std::shared_ptr<Signal> s){return std::ranges::contains(nodes, s->start);});
return std::ranges::contains(erase_nodes_ids, s.start);
});
for(auto &s : rebase_signals){ for(auto s : rebase_signals){
s.start = s.next; s->start = s->next;
} }
for(auto &n : erase_nodes){ for(auto n : nodes){
std::erase_if(gm.connections, [n](Edge c){ return c.node_id_start == n.id || c.node_id_end == n.id;}); std::erase_if(gm.edges, [n](std::shared_ptr<Edge> c){ return c->start == n || c->end == n;});
} }
std::erase_if(gm.nodes, [](std::pair<int, Node> n){ return n.second.erase;}); std::erase_if(gm.nodes, [nodes](std::shared_ptr<Node> n){ return std::ranges::contains(nodes, n);});
gm.keys.clear();
std::ranges::copy(gm.nodes | std::ranges::views::keys, std::back_inserter(gm.keys));
} }
void draw(Vec2D<float> *mouse_pos, Camera2D *camera){ void draw(Vec2D<float> mouse_pos, Camera2D camera){
mutex.lock(); mutex.lock();
updateMidiPorts(); updateMidiPorts();
mutex.unlock(); mutex.unlock();
gm.drawNodes(mouse_pos, camera); gm.drawNodes(mouse_pos, camera);
gm.drawConnections(mouse_pos, camera); gm.drawEdges(mouse_pos, camera);
sm.drawSignals(mouse_pos, camera); sm.drawSignals(mouse_pos, camera);
} }
+45 -40
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "midi-node.h"
#include "raylib.h" #include "raylib.h"
#include "raygui/raygui.h" #include "raygui/raygui.h"
#include "raygui/dark/style_dark.h" #include "raygui/dark/style_dark.h"
@@ -8,6 +9,7 @@
#include "graph-manager.h" #include "graph-manager.h"
#include "signal-manager.h" #include "signal-manager.h"
#include <memory>
#include <ranges> #include <ranges>
class AppUI{ class AppUI{
@@ -52,8 +54,8 @@ class AppUI{
if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) { if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) {
for(auto &midis : sm->midi.midi_out_ports){ for(auto &midis : sm->midi.midi_out_ports){
if(midis.enabled){ if(midis.enabled){
for(auto &n : gm->nodes){ for(auto n : gm->nodes){
n.second.setMidiPort(midis.number, true); if(n->getNodeType() == NodeType::MIDINODE) std::dynamic_pointer_cast<MidiNode>(n)->setMidiPort(midis.number, true);
} }
} }
} }
@@ -62,117 +64,120 @@ class AppUI{
int s_signal = s_midi + 100 + i*20; int s_signal = s_midi + 100 + i*20;
GuiLabel((Rectangle){20, (float)s_signal, 240, 20}, "SIGNALS"); GuiLabel((Rectangle){20, (float)s_signal, 240, 20}, "SIGNALS");
if(GuiButton((Rectangle){20, (float)s_signal + 35, 240, 20}, "ADD RANDOM SIGNAL")){ if(GuiButton((Rectangle){20, (float)s_signal + 35, 240, 20}, "ADD RANDOM SIGNAL")){
int ni = gm->getRandomNode(); std::shared_ptr<Node> ni = gm->getRandomNode();
sm->addSignalAtNode(ni); sm->addSignalAtNode(ni);
} }
int signal_configs = 0; int signal_configs = 0;
for(auto &s : sm->signals){ for(auto &s : sm->signals){
if(GuiButton((Rectangle){20,(float)s_signal+70 + signal_configs*20, 20, 20},"X")) sm->removeSignal(signal_configs); 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); DrawCircle(55, s_signal+80 + signal_configs*20, 6.0F, s->color);
float s_multiplier = round(s.multiplier*10.0f)/10.0f; float s_multiplier = round(s->multiplier*10.0f)/10.0f;
float signal_bpm = settings->bpm * s.multiplier; 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, 10); GuiSlider((Rectangle){70, (float)s_signal+70 + signal_configs*20, 160, 20}, "", std::format("{:.1f}",signal_bpm).c_str(), &s_multiplier, 0.1, 10);
s.multiplier = s_multiplier; s->multiplier = s_multiplier;
s.speed = settings->speed; s->speed = settings->speed;
signal_configs++; signal_configs++;
} }
int s_nodes = s_signal + 70 + signal_configs*20; int s_nodes = s_signal + 70 + signal_configs*20;
GuiLabel((Rectangle){20, (float)s_nodes + 30, 240, 20}, "NODES"); GuiLabel((Rectangle){20, (float)s_nodes + 30, 240, 20}, "NODES");
if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){ if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){
gm->addNode(200.0f, 200.0f); gm->addMidiNode(Vec2D<float>{200.0f, 200.0f});
} }
DrawText(std::format("{}", gm->nodes.size()).c_str(), 20, settings->height - 70, 15, VS_COLOR_WHITE); DrawText(std::format("{}", gm->nodes.size()).c_str(), 20, settings->height - 70, 15, VS_COLOR_WHITE);
DrawFPS(20, settings->height - 30); DrawFPS(20, settings->height - 30);
} }
void drawPerNodeConfig(Camera2D *camera){ void drawPerNodeConfig(Camera2D *camera){
for(auto& n : gm->nodes | std::ranges::views::values | std::views::filter([](Node n){ return n.config; })){ for(auto& n : gm->nodes | std::views::filter([](std::shared_ptr<Node> n){ return n->config; })){
Vector2 np = GetWorldToScreen2D((Vector2){n.position.x, n.position.y}, *camera); Vector2 np = GetWorldToScreen2D((Vector2){n->position.x, n->position.y}, *camera);
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.distributionMode; int option = n->distributionMode;
GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 73, 20 }, "GEO;RR;RAND", &option); GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 73, 20 }, "GEO;RR;RAND", &option);
n.distributionMode = (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")){
sm->addSignalAtNode(n.id); sm->addSignalAtNode(n);
} }
int y_midi = 120; int y_midi = 120;
GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT"); GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT");
int i = 0; int i = 0;
for(auto& mo : n.midi_outs){ if(n->getNodeType() == NodeType::MIDINODE){
std::shared_ptr<MidiNode> mn = std::dynamic_pointer_cast<MidiNode>(n);
for(auto& mo : mn->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); GuiCheckBox((Rectangle){np.x + 20, np.y + y_midi + 20 + i*20.0f, 20, 20}, mo.second.name.c_str(), &mo.second.enabled);
i++; i++;
} }
int y_channel = y_midi + 30 + i*20; int y_channel = y_midi + 30 + i*20;
GuiCheckBox((Rectangle){np.x + 20, np.y + y_channel, 20, 20}, "NOTE", &n.send_note); GuiCheckBox((Rectangle){np.x + 20, np.y + y_channel, 20, 20}, "NOTE", &mn->send_note);
GuiCheckBox((Rectangle){np.x + 90, np.y + y_channel, 20, 20}, "CC", &n.send_cc); GuiCheckBox((Rectangle){np.x + 90, np.y + y_channel, 20, 20}, "CC", &mn->send_cc);
GuiCheckBox((Rectangle){np.x + 160, np.y + y_channel, 20, 20}, "PITCH", &n.send_pitch_bend); GuiCheckBox((Rectangle){np.x + 160, np.y + y_channel, 20, 20}, "PITCH", &mn->send_pitch_bend);
int y_cc_note = y_channel + 120; int y_cc_note = y_channel + 120;
switch(settings->mode){ switch(settings->mode){
case 0:{ case 0:{
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "NOTE CHANNEL"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "NOTE 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_note_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", &mn->midi_note_channel);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "NOTE"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "NOTE");
float v = n.midi_note; float v = mn->midi_note;
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_cc_note , 20, 20}, sm->midi.midiNotes[(int)round(v)].c_str());
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",n.midi_note).c_str()); GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",mn->midi_note).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127);
n.midi_note = round(v); mn->midi_note = round(v);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "VELOCITY"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "VELOCITY");
v = n.midi_velocity; v = mn->midi_velocity;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",n.midi_velocity).c_str()); GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",mn->midi_velocity).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127);
n.midi_velocity = round(v); mn->midi_velocity = round(v);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 120, 100, 20}, "GATE"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 120, 100, 20}, "GATE");
v = n.midi_gate; v = mn->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()); GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 120, 20, 20}, std::format("{}",(float)mn->midi_gate/1000.0f).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 150, 220, 20}, "", "", &v, 0, 30000); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 150, 220, 20}, "", "", &v, 0, 30000);
n.midi_gate = round(v); mn->midi_gate = round(v);
break;} break;}
case 1: case 1:
{ {
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "CC CHANNEL"); 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); 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", &mn->midi_cc_channel);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC");
float v = n.midi_cc; float v = mn->midi_cc;
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",n.midi_cc).c_str()); GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",mn->midi_cc).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127);
n.midi_cc = round(v); mn->midi_cc = round(v);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "CC VALUE"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "CC VALUE");
v = n.midi_cc_value; v = mn->midi_cc_value;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",n.midi_cc_value).c_str()); GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",mn->midi_cc_value).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127);
n.midi_cc_value = round(v); mn->midi_cc_value = round(v);
break;} break;}
case 2: case 2:
{ {
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "PITCH BEND CHANNEL"); 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); 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", &mn->midi_pitch_bend_channel);
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC"); GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC");
float v = n.midi_pitch_bend; float v = mn->midi_pitch_bend;
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",n.midi_pitch_bend).c_str()); GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",mn->midi_pitch_bend).c_str());
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 16383); GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 16383);
n.midi_pitch_bend = round(v); mn->midi_pitch_bend = round(v);
break;} break;}
} }
} }
} }
}
void draw(Vec2D<float> *mouse_pos, Camera2D *camera){ void draw(Vec2D<float> *mouse_pos, Camera2D *camera){
drawSideBar(); drawSideBar();