heavy restructuring with smart pointers, not finished
This commit is contained in:
+107
-67
@@ -1,11 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "graph-item.h"
|
||||
#include "node.h"
|
||||
#include "connection.h"
|
||||
#include "edge.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
|
||||
class GraphManager{
|
||||
|
||||
@@ -13,89 +18,72 @@ class GraphManager{
|
||||
|
||||
GraphManager() {}
|
||||
|
||||
std::map<int, Node> nodes;
|
||||
std::vector<Connection> connections;
|
||||
std::vector<std::shared_ptr<Node>> nodes;
|
||||
std::vector<std::shared_ptr<Edge>> edges;
|
||||
|
||||
std::map<std::shared_ptr<Node>, int> counter;
|
||||
|
||||
std::shared_ptr<Node> getRandomNode(){
|
||||
std::vector<std::shared_ptr<GraphItem>> o;
|
||||
std::ranges::sample(nodes, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
|
||||
return std::dynamic_pointer_cast<Node>(o.front());
|
||||
}
|
||||
|
||||
std::vector<int> keys;
|
||||
int iterator = 0;
|
||||
|
||||
std::map<int, int> counter;
|
||||
|
||||
int getRandomNode(){
|
||||
std::vector<int> o;
|
||||
std::ranges::sample(keys, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
|
||||
return o.front();
|
||||
std::shared_ptr<Edge> getRandomEdge(){
|
||||
std::vector<std::shared_ptr<GraphItem>> o;
|
||||
std::ranges::sample(edges, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
|
||||
return std::dynamic_pointer_cast<Edge>(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++;
|
||||
void copyNodes(std::vector<std::shared_ptr<Node>> nodes, Vec2D<float> position){
|
||||
for(auto n: nodes){
|
||||
auto nc = std::make_shared<Node>(n);
|
||||
nc->position = position + nc->drag_offset;
|
||||
nc->selected = true;
|
||||
nodes.push_back(nc);
|
||||
}
|
||||
}
|
||||
|
||||
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 copyNode(std::shared_ptr<Node> n, Vec2D<float> position){
|
||||
auto nc = std::make_shared<Node>(n);
|
||||
nc->setPosition(position);
|
||||
nodes.push_back(nc);
|
||||
}
|
||||
|
||||
void setNodeMode(int mode){
|
||||
for(auto &n : nodes | std::ranges::views::values){
|
||||
n.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
int addNode(float x, float y){
|
||||
std::shared_ptr<Node> 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;
|
||||
std::shared_ptr<Node> addNode(Vec2D<float> position){
|
||||
nodes.emplace_back(std::make_shared<Node>(position));
|
||||
return nodes.back();
|
||||
}
|
||||
|
||||
void triggerNode(int node){
|
||||
nodes.at(node).trigger();
|
||||
void setNodeMode(int mode){
|
||||
for(auto n: nodes){
|
||||
n->setMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
void reset(){
|
||||
counter.clear();
|
||||
}
|
||||
|
||||
int next(int current, int last){
|
||||
std::vector<Connection*> possible_connections;
|
||||
std::vector<int> next_node_ids;
|
||||
std::shared_ptr<Node> next(std::shared_ptr<Node> current, std::shared_ptr<Node> last){
|
||||
std::vector<std::shared_ptr<Edge>> possible_connections = current->connections | std::ranges::views::filter([current](std::shared_ptr<Edge> c){
|
||||
return (c->start == current && c->pass_forward) || (c->end == current && c->pass_backward);
|
||||
}) | std::ranges::to<std::vector<std::shared_ptr<Edge>>>();
|
||||
|
||||
for(auto& c : connections){
|
||||
if((c.v1 == current && c.v1_v2) || (c.v2 == current && c.v2_v1)) {
|
||||
c.active = false;
|
||||
possible_connections.push_back(&c);
|
||||
next_node_ids.push_back( c.v1 == current ? c.v2 : c.v1 );
|
||||
}
|
||||
}
|
||||
|
||||
if(possible_connections.empty()) return -1;
|
||||
if(possible_connections.empty()) return std::shared_ptr<Node>(nullptr);
|
||||
|
||||
int return_path = 0;
|
||||
float angle = -1;
|
||||
if(nodes.at(current).distributionMode == Distribution::GEOMETRIC){
|
||||
Vec2D<float> coming_from = (nodes.at(current).position - nodes.at(last).position).norm();
|
||||
if(current->distributionMode == Distribution::GEOMETRIC){
|
||||
Vec2D<float> coming_from = (current->position - 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((nodes.at(next_position).position - nodes.at(current).position).norm());
|
||||
std::shared_ptr<Node> next_node = n->getNextNode(current);
|
||||
float angle_v1_v2 = coming_from.norm().dot((next_node->position - current->position).norm());
|
||||
if(angle_v1_v2 > angle) {
|
||||
return_path = i;
|
||||
angle = angle_v1_v2;
|
||||
@@ -104,7 +92,7 @@ class GraphManager{
|
||||
}
|
||||
}
|
||||
|
||||
if(nodes.at(current).distributionMode == Distribution::ROUNDROBIN){
|
||||
if(current->distributionMode == Distribution::ROUNDROBIN){
|
||||
if(counter.find(current) == counter.end()) {
|
||||
counter[current] = 0;
|
||||
} else {
|
||||
@@ -113,24 +101,76 @@ class GraphManager{
|
||||
}
|
||||
}
|
||||
|
||||
if(nodes.at(current).distributionMode == Distribution::RANDOM){
|
||||
if(current->distributionMode == Distribution::RANDOM){
|
||||
return_path = rand() % possible_connections.size();
|
||||
}
|
||||
|
||||
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)->getNextNode(current);
|
||||
}
|
||||
|
||||
void addConnection(int from, int to){
|
||||
connections.emplace_back(&nodes, from, to);
|
||||
void addConnection(std::shared_ptr<Node> from, std::shared_ptr<Node> to){
|
||||
edges.emplace_back(std::make_shared<Edge>(from, to));
|
||||
}
|
||||
|
||||
void drawConnections(Vec2D<float> *mouse_pos, Camera2D *cam){
|
||||
std::erase_if(connections, [](Connection c){ return c.remove == true;});
|
||||
for(auto& c : connections){
|
||||
c.draw(mouse_pos, cam);
|
||||
// std::erase_if(connections, [](Connection c){ return c.remove == true;});
|
||||
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> 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 midi_gate_v1 = Clamp((4.f / 1000.f) * c->start->midi_gate, 1.f, 4.f);
|
||||
float midi_gate_v2 = Clamp((4.f / 1000.f) * c->end->midi_gate, 1.f, 4.f);
|
||||
// Line with small connector circles
|
||||
|
||||
Color col = {229, 181, 103, 255};
|
||||
if(c.active) col = {108, 153, 187, 255};
|
||||
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col);
|
||||
|
||||
if(midi_gate_v1 == 4.0f) col = VS_COLOR_RED;
|
||||
DrawCircle(v1_position.x, v1_position.y, midi_gate_v1, col);
|
||||
|
||||
col = {229, 181, 103, 255};
|
||||
if(midi_gate_v2 == 4.0f) col = VS_COLOR_RED;
|
||||
DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col);
|
||||
|
||||
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> 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_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_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
|
||||
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, 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
|
||||
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, 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(!c->start_end){
|
||||
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;
|
||||
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_from});
|
||||
}
|
||||
|
||||
if(!c.end_start){
|
||||
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;
|
||||
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_2.x, flip_handle_2.y, 8.0f, (Color){232, 50, 32, opacity} )) c.split = true;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user