Rework to weak_ptr from lots of shared_ptr.
This commit is contained in:
+97
-88
@@ -15,7 +15,6 @@
|
||||
#include "node.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
@@ -35,6 +34,20 @@ using namespace VISEQ::GRAPH::EDGES;
|
||||
namespace VISEQ::GRAPH {
|
||||
|
||||
class GraphManager : public std::enable_shared_from_this<GraphManager>{
|
||||
private:
|
||||
NODES::VEC_SPTR_Node nodes;
|
||||
EDGES::VEC_SPTR_Edge edges;
|
||||
|
||||
std::map<WPTR_Node, VEC_WPTR_Edge> connections;
|
||||
|
||||
EDGES::VEC_WPTR_Edge remove_edges;
|
||||
EDGES::VEC_WPTR_Edge split_edges;
|
||||
|
||||
VEC_WPTR_Node selected_nodes;
|
||||
|
||||
std::map<NODES::WPTR_Node, int> counter;
|
||||
|
||||
std::shared_ptr<APP::State> state = APP::State::get();
|
||||
|
||||
public:
|
||||
|
||||
@@ -43,39 +56,24 @@ namespace VISEQ::GRAPH {
|
||||
std::shared_ptr<GraphManager> getPtr(){
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
NODES::VEC_SPTR_Node nodes;
|
||||
EDGES::VEC_SPTR_Edge edges;
|
||||
std::map<SPTR_Node, VEC_SPTR_Edge> connections;
|
||||
|
||||
EDGES::VEC_SPTR_Edge remove_edges;
|
||||
EDGES::VEC_SPTR_Edge split_edges;
|
||||
|
||||
VEC_SPTR_Node selected_nodes;
|
||||
|
||||
std::map<NODES::SPTR_Node, int> counter;
|
||||
|
||||
std::shared_ptr<APP::State> state = APP::State::get();
|
||||
|
||||
SPTR_Node addMidiNode(Vec2Df position){
|
||||
void addMidiNode(Vec2Df position){
|
||||
nodes.emplace_back(std::make_shared<MidiNode>(position));
|
||||
return nodes.back();
|
||||
}
|
||||
|
||||
void addNode(SPTR_Node node){
|
||||
nodes.insert(nodes.end(), node);
|
||||
nodes.back()->init();
|
||||
}
|
||||
|
||||
void addConnection(SPTR_Node from, SPTR_Node to){
|
||||
if(from != to) {
|
||||
void addConnection(WPTR_Node from, WPTR_Node to){
|
||||
if(from.lock() != to.lock()) {
|
||||
edges.emplace_back(std::make_shared<Edge>());
|
||||
edges.back()->start = from;
|
||||
edges.back()->end = to;
|
||||
edges.back()->start_conn = from->connectors.back();
|
||||
edges.back()->end_conn = to->connectors.back();
|
||||
from->connections.push_back(edges.back());
|
||||
to->connections.push_back(edges.back());
|
||||
edges.back()->start_conn = from.lock()->connectors.back();
|
||||
edges.back()->end_conn = to.lock()->connectors.back();
|
||||
from.lock()->connections.push_back(edges.back());
|
||||
to.lock()->connections.push_back(edges.back());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,20 +82,19 @@ namespace VISEQ::GRAPH {
|
||||
auto temp_nodes = nodes | RANGE_FILTER([](SPTR_Node n){return n->select();}) | std::ranges::to<VEC_SPTR_Node>();
|
||||
if(!KEYS_DOWN.shift) selected_nodes.clear();
|
||||
selected_nodes.insert(selected_nodes.end(), temp_nodes.begin(), temp_nodes.end());
|
||||
std::for_each(selected_nodes.begin(), selected_nodes.end(), [](SPTR_Node n){n->selected = true;});
|
||||
std::for_each(selected_nodes.begin(), selected_nodes.end(), [](WPTR_Node n){n.lock()->selected = true;});
|
||||
}
|
||||
|
||||
void deselect(){
|
||||
std::cout << "deselect" << std::endl;
|
||||
for(auto s : selected_nodes){
|
||||
s->selected = false;
|
||||
s.lock()->selected = false;
|
||||
}
|
||||
selected_nodes.clear();
|
||||
}
|
||||
|
||||
VEC_SPTR_Node getSelection(){
|
||||
VEC_WPTR_Node getSelection(){
|
||||
return selected_nodes;
|
||||
//return nodes | RANGE_FILTER([](SPTR_Node n){return n->selected;}) | std::ranges::to<VEC_SPTR_Node>();
|
||||
}
|
||||
|
||||
void copyNodes(VEC_SPTR_Node _nodes, Vec2Df position){
|
||||
@@ -139,6 +136,17 @@ namespace VISEQ::GRAPH {
|
||||
void reset(){
|
||||
counter.clear();
|
||||
}
|
||||
WPTR_Node getNode(int i){
|
||||
return nodes.at(i);
|
||||
}
|
||||
|
||||
WPTR_Node getFirstNode(){
|
||||
return nodes.front();
|
||||
}
|
||||
|
||||
VEC_WPTR_Node getMidiNodes(){
|
||||
return nodes | RANGE_FILTER([](VISEQ::GRAPH::NODES::SPTR_Node n){return n->getNodeType() == NodeType::MIDINODE;}) | std::ranges::to<VEC_WPTR_Node>();
|
||||
}
|
||||
|
||||
NODES::SPTR_Node getRandomNode(){
|
||||
VEC_SPTR_GraphItem o;
|
||||
@@ -157,27 +165,29 @@ namespace VISEQ::GRAPH {
|
||||
std::sort(neighbors.begin(), neighbors.end(), [position](SPTR_Node na, SPTR_Node nb){ return na->position.dist(position) < nb->position.dist(position);});
|
||||
return neighbors.front();
|
||||
}
|
||||
VEC_WPTR_Node getNodesByID(int _id){
|
||||
return nodes | RANGE_FILTER([_id](SPTR_Node n){return n->id == _id;}) | std::ranges::to<VEC_WPTR_Node>(); // TODO: Multiple nodes with the same ID? Why not return only one node?
|
||||
}
|
||||
|
||||
WPTR_Edge lastEdge(){
|
||||
return edges.back();
|
||||
}
|
||||
|
||||
/*SPTR_Node next_node(SPTR_Node current, SPTR_Node last){*/
|
||||
/* std::vector<std::shared_ptr<Connector>> active_connectors;*/
|
||||
/**/
|
||||
/*}*/
|
||||
|
||||
SPTR_Node next(SPTR_Node current, SPTR_Node last){
|
||||
VEC_SPTR_Edge possible_connections = current->connections | RANGE_FILTER([current](SPTR_Edge c){
|
||||
return (c->start == current && c->pass_forward) || (c->end == current && c->pass_backward);
|
||||
}) | std::ranges::to<VEC_SPTR_Edge>();
|
||||
WPTR_Node next(WPTR_Node current, WPTR_Node last){
|
||||
VEC_WPTR_Edge possible_connections = current.lock()->connections | RANGE_FILTER([current](WPTR_Edge c){
|
||||
return (c.lock()->start.lock() == current.lock() && c.lock()->pass_forward) || (c.lock()->end.lock() == current.lock() && c.lock()->pass_backward);
|
||||
}) | std::ranges::to<VEC_WPTR_Edge>();
|
||||
|
||||
if(possible_connections.empty()) return SPTR_Node(nullptr);
|
||||
|
||||
int return_path = 0;
|
||||
float angle = -1;
|
||||
if(current->distributionMode == Distribution::GEOMETRIC){
|
||||
Vec2Df coming_from = (current->position - last->position).norm();
|
||||
if(current.lock()->distributionMode == Distribution::GEOMETRIC){
|
||||
Vec2Df coming_from = (current.lock()->position - last.lock()->position).norm();
|
||||
int i = 0;
|
||||
for(auto n : possible_connections){
|
||||
SPTR_Node next_node = n->getNextNode(current);
|
||||
float angle_v1_v2 = coming_from.norm().dot((next_node->position - current->position).norm());
|
||||
WPTR_Node next_node = n.lock()->getNextNode(current);
|
||||
float angle_v1_v2 = coming_from.norm().dot((next_node.lock()->position - current.lock()->position).norm());
|
||||
if(angle_v1_v2 > angle) {
|
||||
return_path = i;
|
||||
angle = angle_v1_v2;
|
||||
@@ -186,7 +196,7 @@ namespace VISEQ::GRAPH {
|
||||
}
|
||||
}
|
||||
|
||||
if(current->distributionMode == Distribution::ROUNDROBIN){
|
||||
if(current.lock()->distributionMode == Distribution::ROUNDROBIN){
|
||||
if(counter.find(current) == counter.end()) {
|
||||
counter[current] = 0;
|
||||
} else {
|
||||
@@ -195,12 +205,11 @@ namespace VISEQ::GRAPH {
|
||||
}
|
||||
}
|
||||
|
||||
if(current->distributionMode == Distribution::RANDOM){
|
||||
if(current.lock()->distributionMode == Distribution::RANDOM){
|
||||
return_path = rand() % possible_connections.size();
|
||||
}
|
||||
|
||||
//possible_connections.at(return_path)->active = true;
|
||||
return possible_connections.at(return_path)->getNextNode(current);
|
||||
return possible_connections.at(return_path).lock()->getNextNode(current);
|
||||
}
|
||||
|
||||
void splitEdge(SPTR_Edge edge){
|
||||
@@ -209,10 +218,10 @@ namespace VISEQ::GRAPH {
|
||||
|
||||
void splitEdges(){
|
||||
for(auto s : split_edges){
|
||||
Vec2Df center = s->end->position.center(s->start->position);
|
||||
SPTR_Node cn = copyNode(std::dynamic_pointer_cast<MidiNode>(s->start), center);
|
||||
addConnection(s->start, cn);
|
||||
addConnection(cn, s->end);
|
||||
Vec2Df center = s.lock()->end.lock()->position.center(s.lock()->start.lock()->position);
|
||||
SPTR_Node cn = copyNode(std::dynamic_pointer_cast<MidiNode>(s.lock()->start.lock()), center);
|
||||
addConnection(s.lock()->start.lock(), cn);
|
||||
addConnection(cn, s.lock()->end.lock());
|
||||
remove_edges.push_back(s);
|
||||
}
|
||||
split_edges.clear();
|
||||
@@ -224,40 +233,40 @@ namespace VISEQ::GRAPH {
|
||||
|
||||
void removeEdges(){
|
||||
for(auto edge : remove_edges){
|
||||
// edge->start->removeConnector(edge->start_conn);
|
||||
// edge->end->removeConnector(edge->end_conn);
|
||||
std::erase(edge->start->connections, edge);
|
||||
std::erase(edge->end->connections, edge);
|
||||
std::erase(edges, edge);
|
||||
edge.lock()->start.lock()->removeConnector(edge.lock()->start_conn);
|
||||
edge.lock()->end.lock()->removeConnector(edge.lock()->end_conn);
|
||||
std::erase(edge.lock()->start.lock()->connections, edge.lock());
|
||||
std::erase(edge.lock()->end.lock()->connections, edge.lock());
|
||||
std::erase(edges, edge.lock());
|
||||
}
|
||||
remove_edges.clear();
|
||||
}
|
||||
|
||||
VEC_SPTR_Node getAdjacentNodes(VEC_SPTR_Node selected_nodes){
|
||||
VEC_WPTR_Node getAdjacentNodes(VEC_SPTR_Node selected_nodes){
|
||||
for(auto n : nodes){
|
||||
n->highlighted = false;
|
||||
}
|
||||
|
||||
auto erase_connections = edges | RANGE_FILTER([selected_nodes](SPTR_Edge c){ return std::ranges::contains(selected_nodes, c->start) || std::ranges::contains(selected_nodes, c->end);});
|
||||
auto erase_connections = edges | RANGE_FILTER([selected_nodes](SPTR_Edge c){ return std::ranges::contains(selected_nodes, c->start.lock()) || std::ranges::contains(selected_nodes, c->end.lock());});
|
||||
|
||||
VEC_SPTR_Node adjacent_nodes;
|
||||
VEC_WPTR_Node adjacent_nodes;
|
||||
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);
|
||||
if(!c->start.lock()->selected) adjacent_nodes.push_back(c->start);
|
||||
if(!c->end.lock()->selected) adjacent_nodes.push_back(c->end);
|
||||
}
|
||||
|
||||
return adjacent_nodes;
|
||||
}
|
||||
|
||||
void removeNodesAndEdges(VEC_SPTR_Node selected_nodes){
|
||||
VEC_SPTR_Node adjacent_nodes = getAdjacentNodes(selected_nodes);
|
||||
VEC_WPTR_Node adjacent_nodes = getAdjacentNodes(selected_nodes);
|
||||
|
||||
for(auto n : adjacent_nodes){
|
||||
std::erase_if(n->connections, [n, selected_nodes](VISEQ::GRAPH::EDGES::SPTR_Edge c){ return std::ranges::contains(selected_nodes, c->start) || std::ranges::contains(selected_nodes, c->end);});
|
||||
std::erase_if(n.lock()->connections, [n, selected_nodes](VISEQ::GRAPH::EDGES::WPTR_Edge c){ return std::ranges::contains(selected_nodes, c.lock()->start.lock()) || std::ranges::contains(selected_nodes, c.lock()->end.lock());});
|
||||
}
|
||||
|
||||
for(auto n : selected_nodes){
|
||||
std::erase_if(this->edges, [n](SPTR_Edge c){ return c->start == n || c->end == n;});
|
||||
std::erase_if(this->edges, [n](WPTR_Edge c){ return c.lock()->start.lock() == n || c.lock()->end.lock() == n;});
|
||||
}
|
||||
|
||||
std::erase_if(this->nodes, [selected_nodes](SPTR_Node n){ return std::ranges::contains(selected_nodes, n);});
|
||||
@@ -267,7 +276,7 @@ namespace VISEQ::GRAPH {
|
||||
|
||||
VEC_SPTR_Edge copy_connections;
|
||||
for(auto c : edges){
|
||||
if(std::ranges::contains(nodes, c->start) && std::ranges::contains(nodes, c->end)) {
|
||||
if(std::ranges::contains(nodes, c->start.lock()) && std::ranges::contains(nodes, c->end.lock())) {
|
||||
copy_connections.push_back(std::make_shared<Edge>(*c));
|
||||
}
|
||||
}
|
||||
@@ -288,13 +297,13 @@ namespace VISEQ::GRAPH {
|
||||
//TODO copy connectors
|
||||
|
||||
for(auto c : copy_connections){
|
||||
if(c->start == old_node) {
|
||||
if(c->start.lock() == old_node) {
|
||||
c->start = new_node;
|
||||
c->start->connections.push_back(c);
|
||||
c->start.lock()->connections.push_back(c);
|
||||
}
|
||||
if(c->end == old_node) {
|
||||
if(c->end.lock() == old_node) {
|
||||
c->end = new_node;
|
||||
c->end->connections.push_back(c);
|
||||
c->end.lock()->connections.push_back(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,29 +317,29 @@ namespace VISEQ::GRAPH {
|
||||
|
||||
void drawEdges(Vec2Df mouse_pos, Camera2D cam){
|
||||
for(auto c : edges){
|
||||
Vec2Df v1_position = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->connector_offset);
|
||||
Vec2Df v2_position = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->connector_offset);
|
||||
Vec2Df v1_position = c->start.lock()->position - ((c->start.lock()->position - c->end.lock()->position)).norm() * (c->start.lock()->radius + c->connector_offset);
|
||||
Vec2Df v2_position = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position)).norm() * (c->end.lock()->radius + c->connector_offset);
|
||||
float v1_v2_distance = v1_position.dist(&v2_position);
|
||||
|
||||
float midi_gate_v1 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast<MidiNode>(c->start)->GGate(), 1.f, 4.f);
|
||||
float midi_gate_v2 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast<MidiNode>(c->end)->GGate(), 1.f, 4.f);
|
||||
float midi_gate_v1 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast<MidiNode>(c->start.lock())->GGate(), 1.f, 4.f);
|
||||
float midi_gate_v2 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast<MidiNode>(c->end.lock())->GGate(), 1.f, 4.f);
|
||||
// Line with small connector circles
|
||||
|
||||
Color col = {229, 181, 103, 255};
|
||||
if(c->GActive()) col = {108, 153, 187, 255};
|
||||
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col);
|
||||
{
|
||||
float d = c->start->position.dist(c->end->position);
|
||||
float d = c->start.lock()->position.dist(c->end.lock()->position);
|
||||
std::string frac = MIDI::Fractions.at(std::clamp<int>(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);
|
||||
|
||||
Vec2Df middle_handle = c->start->position + (c->end->position - c->start->position) * ((d - text_length.x)*0.5f)/d;
|
||||
Vec2Df middle_handle_frac = c->start->position + (c->end->position - c->start->position) * ((d - text_length_frac.x)*0.5f)/d;
|
||||
Vec2Df text_position = middle_handle + (c->start->position - c->end->position).norm().orth() * 12.0f;
|
||||
Vec2Df text_position_frac = middle_handle_frac - (c->start->position - c->end->position).norm().orth() * 4.0f;
|
||||
Vec2Df middle_handle = c->start.lock()->position + (c->end.lock()->position - c->start.lock()->position) * ((d - text_length.x)*0.5f)/d;
|
||||
Vec2Df middle_handle_frac = c->start.lock()->position + (c->end.lock()->position - c->start.lock()->position) * ((d - text_length_frac.x)*0.5f)/d;
|
||||
Vec2Df text_position = middle_handle + (c->start.lock()->position - c->end.lock()->position).norm().orth() * 12.0f;
|
||||
Vec2Df text_position_frac = middle_handle_frac - (c->start.lock()->position - c->end.lock()->position).norm().orth() * 4.0f;
|
||||
|
||||
float rotation = Vector2Angle((Vector2){1,0}, (c->end->position - c->start->position)) * RAD2DEG;
|
||||
float rotation = Vector2Angle((Vector2){1,0}, (c->end.lock()->position - c->start.lock()->position)) * RAD2DEG;
|
||||
DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
||||
if( (int)d % 60 == 0) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
||||
}
|
||||
@@ -342,10 +351,10 @@ namespace VISEQ::GRAPH {
|
||||
DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col);
|
||||
|
||||
if(v1_v2_distance < 100) c->switches_offset = v1_v2_distance/2.3f;
|
||||
Vec2Df from_to_handle = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->switches_offset);
|
||||
Vec2Df to_from_handle = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->switches_offset);
|
||||
Vec2Df middle_handle = c->end->position - ((c->end->position - c->start->position))*0.4f;
|
||||
Vec2Df middle_handle_2 = c->end->position - ((c->end->position - c->start->position))*0.6f;
|
||||
Vec2Df from_to_handle = c->start.lock()->position - ((c->start.lock()->position - c->end.lock()->position)).norm() * (c->start.lock()->radius + c->switches_offset);
|
||||
Vec2Df to_from_handle = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position)).norm() * (c->end.lock()->radius + c->switches_offset);
|
||||
Vec2Df middle_handle = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position))*0.4f;
|
||||
Vec2Df middle_handle_2 = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position))*0.6f;
|
||||
Vec2Df 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);
|
||||
Vec2Df 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);
|
||||
|
||||
@@ -354,7 +363,7 @@ namespace VISEQ::GRAPH {
|
||||
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);
|
||||
|
||||
if(!c->start->picked_up && !c->end->picked_up){
|
||||
if(!c->start.lock()->picked_up && !c->end.lock()->picked_up){
|
||||
// On/Off switches on both sides
|
||||
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->pass_backward ? (Color){120, 210, 115, opacity_to} : (Color){232, 50, 32, opacity_to} )) c->pass_backward = !c->pass_backward;
|
||||
@@ -422,13 +431,13 @@ namespace VISEQ::GRAPH {
|
||||
}
|
||||
}
|
||||
|
||||
inline void to_json(json& j, const GraphManager& G){
|
||||
j = json{{"nodes", G.nodes}, {"edges", G.edges}};
|
||||
}
|
||||
|
||||
inline void from_json(const json& j, GraphManager& G){
|
||||
j.at("nodes").template get_to<VEC_SPTR_Node>(G.nodes);
|
||||
}
|
||||
};
|
||||
|
||||
inline void to_json(json& j, const GraphManager& G){
|
||||
j = json{{"nodes", G.nodes}, {"edges", G.edges}};
|
||||
}
|
||||
|
||||
inline void from_json(const json& j, GraphManager& G){
|
||||
j.at("nodes").template get_to<VEC_SPTR_Node>(G.nodes); // = json{{"nodes", G.nodes}, {"edges", G.edges}};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user