connection split button added, but no functionality yes

This commit is contained in:
Sebastian
2024-10-30 11:27:37 +01:00
parent c0f5138765
commit ba5874837c
6 changed files with 2982 additions and 46 deletions
+11 -13
View File
@@ -3,7 +3,6 @@
#include "connection.h"
#include "node-manager.h"
#include "raylib.h"
#include "raymath.h"
#include <map>
#include <vector>
@@ -28,19 +27,12 @@ class ConnectionManager{
std::vector<int> next_node_ids;
for(auto& c : connections){
if((c.v1 == current && c.v1_v2) || (c.v2 == current && c.v2_v1)) {
if((c.node_id_start == current && c.v1_v2) || (c.node_id_end == current && c.v2_v1)) {
c.active = false;
possible_connections.push_back(&c);
next_node_ids.push_back( c.v1 == current ? c.v2 : c.v1 );
next_node_ids.push_back( c.node_id_start == current ? c.node_id_end : c.node_id_start );
}
}
/*if(possible_connections.size() == 2) {*/
/* int next = next_node_ids[0] == last ? next_node_ids[1] : next_node_ids[0];*/
/* if(possible_connections[0]->v1 == next || possible_connections[0]->v2 == next) possible_connections[0]->active = true;*/
/* if(possible_connections[1]->v1 == next || possible_connections[1]->v2 == next) possible_connections[1]->active = true;*/
/* return next;*/
/*}*/
if(possible_connections.empty()) return -1;
@@ -50,7 +42,7 @@ class ConnectionManager{
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;
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;
@@ -74,16 +66,22 @@ class ConnectionManager{
}
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;
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->nodes, from, 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);
}
}
+25 -17
View File
@@ -2,41 +2,49 @@
#include "button.h"
#include "datatypes.h"
#include "node-manager.h"
#include "node.h"
#include "raylib.h"
class Connection{
public:
Connection(std::map<int, Node> *nodes, int v1, int v2) : v1(v1), v2(v2), nodes(nodes) {}
Connection(NodeManager *nm, int v1, int v2) : node_id_start(v1), node_id_end(v2), nm(nm) {}
int v1;
int v2;
int node_id_start;
int node_id_end;
std::map<int, Node> *nodes;
Node* node_start;
Node* node_end;
NodeManager *nm;
bool v1_v2 = true;
bool v2_v1 = true;
bool active = false;
bool remove = false;
bool config = false;
bool split = false;
float connector_offset = 8.0f;
float switches_offset = 25.0f;
void flip(){
int vt = v1;
v1 = v2;
v2 = vt;
int vt = node_id_start;
node_id_start = node_id_end;
node_id_end = vt;
Node* nt = node_start;
node_start = node_end;
node_end = nt;
}
void draw(Vec2D<float> *mouse_pos, Camera2D *cam){
Vec2D<float> v1_position = nodes->at(v1).position - ((nodes->at(v1).position - nodes->at(v2).position)).norm() * (nodes->at(v1).radius + connector_offset);
Vec2D<float> v2_position = nodes->at(v2).position - ((nodes->at(v2).position - nodes->at(v1).position)).norm() * (nodes->at(v2).radius + connector_offset);
Vec2D<float> v1_position = nm->node(node_id_start)->position - ((nm->node(node_id_start)->position - nm->node(node_id_end)->position)).norm() * (nm->node(node_id_start)->radius + connector_offset);
Vec2D<float> v2_position = nm->node(node_id_end)->position - ((nm->node(node_id_end)->position - nm->node(node_id_start)->position)).norm() * (nm->node(node_id_end)->radius + connector_offset);
float v1_v2_distance = v1_position.dist(&v2_position);
float midi_gate_v1 = Clamp((4.f / 1000.f) * nodes->at(v1).midi_gate, 1.f, 4.f);
float midi_gate_v2 = Clamp((4.f / 1000.f) * nodes->at(v2).midi_gate, 1.f, 4.f);
float midi_gate_v1 = Clamp((4.f / 1000.f) * nm->node(node_id_start)->midi_gate, 1.f, 4.f);
float midi_gate_v2 = Clamp((4.f / 1000.f) * nm->node(node_id_end)->midi_gate, 1.f, 4.f);
// Line with small connector circles
Color c = {229, 181, 103, 255};
@@ -51,11 +59,12 @@ class Connection{
DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, c);
if(v1_v2_distance < 100) switches_offset = v1_v2_distance/2.3f;
Vec2D<float> from_to_handle = nodes->at(v1).position - ((nodes->at(v1).position - nodes->at(v2).position)).norm() * (nodes->at(v1).radius + switches_offset);
Vec2D<float> to_from_handle = nodes->at(v2).position - ((nodes->at(v2).position - nodes->at(v1).position)).norm() * (nodes->at(v2).radius + switches_offset);
Vec2D<float> middle_handle = nodes->at(v2).position - ((nodes->at(v2).position - nodes->at(v1).position))*0.5f;
// Vec2D<float> config_handle = nodes.at(v2)->position - ((nodes.at(v2)->position - nodes.at(v1)->position))*0.66f;
Vec2D<float> from_to_handle = nm->node(node_id_start)->position - ((nm->node(node_id_start)->position - nm->node(node_id_end)->position)).norm() * (nm->node(node_id_start)->radius + switches_offset);
Vec2D<float> to_from_handle = nm->node(node_id_end)->position - ((nm->node(node_id_end)->position - nm->node(node_id_start)->position)).norm() * (nm->node(node_id_end)->radius + switches_offset);
Vec2D<float> middle_handle = nm->node(node_id_end)->position - ((nm->node(node_id_end)->position - nm->node(node_id_start)->position))*0.4f;
Vec2D<float> middle_handle_2 = nm->node(node_id_end)->position - ((nm->node(node_id_end)->position - nm->node(node_id_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_2 = middle_handle_2 + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*-0.2, -20.f, 0.f) : 1.0f);
// Dynamic opacity by distance to mouse
@@ -81,7 +90,6 @@ class Connection{
if(ViButton(mouse_pos, flip_handle.x, flip_handle.y, 8.0f, (Color){232, 50, 32, opacity} )) remove = true;
//if(ViButton(mouse_pos, config_handle.x, config_handle.y, 8.0f, (Color){158, 134, 200, opacity})) config = !config;
//if(ViButton(mouse_pos, config_handle.x + flip_handle.x, config_handle.y + flip_handle.y, 8.0f, (Color){158, 0, 200, opacity})) flip();
if(ViButton(mouse_pos, flip_handle_2.x, flip_handle_2.y, 8.0f, (Color){232, 50, 32, opacity} )) split = true;
}
};
+11 -7
View File
@@ -75,7 +75,10 @@ class Vec2D{
};
Vec2D norm() { return *this / length();};
Vec2D center(Vec2D v){
return Vec2D<T>{x,y} + (Vec2D<T>{x,y} - v)*0.5f;
}
Vec2D& operator=(const Vec2D& vec){
if (this == &vec){
@@ -125,32 +128,32 @@ class Vec2D{
};
template<typename T>
Vec2D<T> operator+(const Vec2D<T>& left, const Vec2D<T>& right){
Vec2D<T> operator+(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x + right.x, left.y + right.y);
};
template<typename T>
Vec2D<T> operator-(const Vec2D<T>& left, const Vec2D<T>& right){
Vec2D<T> operator-(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x - right.x, left.y - right.y);
};
template<typename T>
Vec2D<T> operator*(const Vec2D<T>& left, const Vec2D<T>& right){
Vec2D<T> operator*(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x * right.x, left.y * right.y);
};
template<typename T>
Vec2D<T> operator/(const Vec2D<T>& left, const Vec2D<T>& right){
Vec2D<T> operator/(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x / right.x, left.y / right.y);
};
template<typename T>
Vec2D<T> operator/(const Vec2D<T>& left, T scalar){
Vec2D<T> operator/(const Vec2D<T> left, T scalar){
return Vec2D<T>(left.x / scalar, left.y / scalar);
};
template<typename T>
Vec2D<T> operator*(const Vec2D<T>& left, T scalar){
Vec2D<T> operator*(const Vec2D<T> left, T scalar){
return Vec2D<T>(left.x * scalar, left.y * scalar);
};
@@ -180,6 +183,7 @@ struct MidiOut{
};
namespace MIDI{
inline std::vector<std::string> Fractions = {"1/32","1/16","3/32","1/8","5/32","3/16","7/32","1/4","9/32","5/16","11/32","3/8","13/32","7/16","15/32","1/2","17/32","9/16","19/32","5/8","21/32","11/16","23/32","3/4","25/32","13/16","27/32","7/8","29/32","15/16","31/32","1/1"};
inline std::vector<std::string> Notes = {
"C-1", "C#-1", "D-1", "D#-1", "E-1", "F-1", "F#-1", "G-1",
"G#-1", "A-1", "A#-1", "B-1", "C0", "C#0", "D0", "D#0",
+4 -2
View File
@@ -20,7 +20,9 @@ class NodeManager{
std::vector<int> keys;
int iterator = 0;
std::vector<std::string> fractions = {"1/32","1/16","3/32","1/8","5/32","3/16","7/32","1/4","9/32","5/16","11/32","3/8","13/32","7/16","15/32","1/2","17/32","9/16","19/32","5/8","21/32","11/16","23/32","3/4","25/32","13/16","27/32","7/8","29/32","15/16","31/32","1/1"};
Node* node(int id){
return &nodes.at(id);
}
int getRandomNode(){
std::vector<int> o;
@@ -80,7 +82,7 @@ class NodeManager{
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 = 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_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f);
+7 -7
View File
@@ -48,7 +48,7 @@ class AppState{
auto copy_nodes_ids = nm.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<Connection> copy_connections;
std::ranges::copy_if(cm.connections, std::back_inserter(copy_connections), [copy_nodes_ids](Connection c){return std::ranges::contains(copy_nodes_ids, c.v1) && std::ranges::contains(copy_nodes_ids, c.v2);});
std::ranges::copy_if(cm.connections, std::back_inserter(copy_connections), [copy_nodes_ids](Connection 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 : copy_nodes_ids){
int old_id = n;
@@ -57,8 +57,8 @@ class AppState{
nm.nodes[new_id].selected = true;
for(auto &c : copy_connections){
if(c.v1 == old_id) c.v1 = new_id;
if(c.v2 == old_id) c.v2 = new_id;
if(c.node_id_start == old_id) c.node_id_start = new_id;
if(c.node_id_end == old_id) c.node_id_end = new_id;
}
}
@@ -78,13 +78,13 @@ class AppState{
erase_nodes_ids.push_back(e.id);
}
auto erase_connections = cm.connections | std::ranges::views::filter([erase_nodes_ids](Connection c){ return std::ranges::contains(erase_nodes_ids, c.v1) || std::ranges::contains(erase_nodes_ids, c.v2);});
auto erase_connections = cm.connections | std::ranges::views::filter([erase_nodes_ids](Connection c){ return std::ranges::contains(erase_nodes_ids, c.node_id_start) || std::ranges::contains(erase_nodes_ids, c.node_id_end);});
std::vector<int> adjacent_nodes_ids;
for(auto &c : erase_connections){
if(!nm.nodes.at(c.v1).selected) adjacent_nodes_ids.push_back(c.v1);
if(!nm.nodes.at(c.v2).selected) adjacent_nodes_ids.push_back(c.v2);
if(!nm.nodes.at(c.node_id_start).selected) adjacent_nodes_ids.push_back(c.node_id_start);
if(!nm.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){
@@ -113,7 +113,7 @@ class AppState{
}
for(auto &n : erase_nodes){
std::erase_if(cm.connections, [n](Connection c){ return c.v1 == n.id || c.v2 == n.id;});
std::erase_if(cm.connections, [n](Connection c){ return c.node_id_start == n.id || c.node_id_end == n.id;});
}
std::erase_if(nm.nodes, [](std::pair<int, Node> n){ return n.second.erase;});
nm.keys.clear();