Rework to weak_ptr from lots of shared_ptr.

This commit is contained in:
Sebastian
2024-12-03 01:25:49 +01:00
parent 722848d46b
commit 0040956801
10 changed files with 171 additions and 191 deletions
+21 -19
View File
@@ -16,7 +16,6 @@
#include "ui.h"
#include <memory>
#include <ranges>
using json = nlohmann::json;
@@ -91,8 +90,11 @@ namespace VISEQ::APP {
int start_id = e.at("start").get<int>();
int end_id = e.at("end").get<int>();
VEC_SPTR_Node start = gm.nodes | RANGE_FILTER([start_id](SPTR_Node n){return n->id == start_id;}) | std::ranges::to<VEC_SPTR_Node>();
VEC_SPTR_Node end = gm.nodes | RANGE_FILTER([end_id](SPTR_Node n){return n->id == end_id;}) | std::ranges::to<VEC_SPTR_Node>();
VEC_WPTR_Node start = gm.getNodesByID(start_id);
VEC_WPTR_Node end = gm.getNodesByID(end_id);
// VEC_SPTR_Node start = gm.nodes | RANGE_FILTER([start_id](SPTR_Node n){return n->id == start_id;}) | std::ranges::to<VEC_SPTR_Node>();
// VEC_SPTR_Node end = gm.nodes | RANGE_FILTER([end_id](SPTR_Node n){return n->id == end_id;}) | std::ranges::to<VEC_SPTR_Node>();
if(!start.empty() && !end.empty()) {
std::cout << std::format("connection {} to {}", start_id, end_id) << std::endl;
@@ -100,18 +102,17 @@ namespace VISEQ::APP {
}
}
gm.edges.back()->newId(highest_id); // set static id counter in base class to highest value from json file
gm.lastEdge().lock()->newId(highest_id);
for(auto s : graph.at("signalmanager").at("signals")){
int start_id = s.at("start").get<int>();
int next_id = s.at("next").get<int>();
int last_id = s.at("last").get<int>();
std::shared_ptr<VISEQ::SIGNAL::Signal> ms = s;
VEC_WPTR_Node start = gm.getNodesByID(start_id);
VEC_WPTR_Node last = gm.getNodesByID(last_id);
VEC_WPTR_Node next = gm.getNodesByID(next_id);
VEC_SPTR_Node start = gm.nodes | RANGE_FILTER([start_id](SPTR_Node n){return n->id == start_id;}) | std::ranges::to<VEC_SPTR_Node>();
VEC_SPTR_Node last = gm.nodes | RANGE_FILTER([last_id](SPTR_Node n){return n->id == last_id;}) | std::ranges::to<VEC_SPTR_Node>();
VEC_SPTR_Node next = gm.nodes | RANGE_FILTER([next_id](SPTR_Node n){return n->id == next_id;}) | std::ranges::to<VEC_SPTR_Node>();
ms->start = start.front();
ms->next = next.front();
ms->last = last.front();
@@ -129,16 +130,16 @@ namespace VISEQ::APP {
}
for(int i = 0; i < 8; ++i){
gm.addConnection(gm.nodes[i], gm.nodes[(i+1) % 8]);
gm.addConnection(gm.getNode(i), gm.getNode((i+1) % 8));
}
sm.addSignalAtNode(gm.nodes.front());
sm.addSignalAtNode(gm.getFirstNode());
}
}
void updateMidiPorts(){
for(auto&n : gm.nodes | RANGE_FILTER([](VISEQ::GRAPH::NODES::SPTR_Node n){return n->getNodeType() == NodeType::MIDINODE;})){
auto nc = std::dynamic_pointer_cast<MidiNode>(n);
for(auto&n : gm.getMidiNodes()){
auto nc = std::dynamic_pointer_cast<MidiNode>(n.lock());
for(auto& mo : sm.midi.midi_out_ports){
if(!nc->midi_outs.contains(mo.number) && mo.enabled){
nc->midi_outs[mo.number] = {mo.number, mo.port.port_name, false};
@@ -186,13 +187,14 @@ namespace VISEQ::APP {
ui.draw(SCREEN_MOUSE, canvas->camera);
mutex.unlock();
}
/*inline void to_json(json& j, const AppManager& A){*/
/* j = json{{"graphmanager", A.gm}, {"signalmanager", A.sm}};*/
/*}*/
/**/
/*inline void from_json(const json& j, AppManager& A){*/
/* j.at("graphmanager").get_to(A.gm); // = json{{"graphmanager", A.gm}, {"signalmanager", A.sm}};*/
/*}*/
};
inline void to_json(json& j, const AppManager& A){
j = json{{"graphmanager", A.gm}, {"signalmanager", A.sm}};
}
inline void from_json(const json& j, AppManager& A){
j.at("graphmanager").get_to(A.gm); // = json{{"graphmanager", A.gm}, {"signalmanager", A.sm}};
}
}
+2 -32
View File
@@ -3,35 +3,19 @@
#include "draggable.h"
#include "vmath.h"
#include <memory>
#include <vector>
namespace VISEQ::BASE {
class Connectable : public Draggable, public std::enable_shared_from_this<Connectable> {
class Connectable : public Draggable {
public:
Connectable() {}
Connectable(Vec2Df position) : Draggable(position) {}
virtual ~Connectable() {remove();}
inline static std::vector<std::shared_ptr<Connectable>> connectables;
std::weak_ptr<Connectable> partner;
std::shared_ptr<Connectable> partner;
bool new_partner = false;
bool connecting = false;
Vec2Df connecting_position;
std::shared_ptr<Connectable> getPtr(){
return shared_from_this();
}
virtual void init() {
VISEQ::BASE::Connectable::connectables.emplace_back(this);
}
virtual void remove() {
std::cout << "delete Connectable: " << getPtr() << std::endl;
// std::erase(VISEQ::BASE::Connectable::connectables, getPtr());
}
virtual void drag(Vec2Df new_position) override {
connecting = true;
connecting_position = new_position;
@@ -44,22 +28,8 @@ namespace VISEQ::BASE {
virtual void connect() {
if(picked_up){
std::cout << getPtr() << std::endl;
std::cout << "connect use count: " << getPtr().use_count() << std::endl;
for(auto c : connectables){
if(c != getPtr() && c->hovering()) {
partner = c;
c->partner = getPtr();
new_partner = true;
partner->new_partner = true;
std::cout << "connect use count: " << getPtr().use_count() << std::endl;
std::cout << connectables.size() << std::endl;
break;
}
}
connecting = false;
}
}
virtual void draw(){
+6 -7
View File
@@ -13,7 +13,6 @@ namespace VISEQ::GRAPH {
class Connector : public BASE::Connectable, public GraphItem{
public:
Connector() {}
//~Connector() {BASE::Connectable::remove();}
Connector(std::shared_ptr<GraphItem> parent, Vec2Df center_position, float orbit) : orbit(orbit) {
setPosition(center_position);
@@ -33,11 +32,11 @@ namespace VISEQ::GRAPH {
}
std::shared_ptr<Connectable> getPtr(){
return std::static_pointer_cast<Connector>(BASE::Connectable::shared_from_this());
return std::static_pointer_cast<Connector>(shared_from_this());
}
virtual bool hovering() override {
return !partner && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius);
return !partner.expired() && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius);
}
void setParent(std::shared_ptr<GraphItem> _parent){
@@ -54,8 +53,8 @@ namespace VISEQ::GRAPH {
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
if(!partner) position = center_position - ((center_position - SCREEN_MOUSE)).norm() * (radius + orbit);
if(partner) position = center_position - ((center_position - partner->position)).norm() * (radius + orbit);
if(partner.expired()) position = center_position - ((center_position - SCREEN_MOUSE)).norm() * (radius + orbit);
if(!partner.expired()) position = center_position - ((center_position - partner.lock()->position)).norm() * (radius + orbit);
if(new_partner) {
new_partner = false;
state->pushEvent({getPtr(), APP::Interaction::CONNECT});
@@ -66,8 +65,8 @@ namespace VISEQ::GRAPH {
BASE::Connectable::draw();
float opacity = 150.0f - Clamp(position.dist(SCREEN_MOUSE), 0.0f, 150.0f);
if(partner){
DrawLineV(position, partner->position, VS_COLOR_RED);
if(!partner.expired()){
DrawLineV(position, partner.lock()->position, VS_COLOR_RED);
}
if(hovering()){
+7 -5
View File
@@ -12,10 +12,10 @@ namespace VISEQ::GRAPH::EDGES {
public:
Edge() {}
Edge(std::shared_ptr<NODES::Node> start, std::shared_ptr<NODES::Node> end) : start(start), end(end) {}
Edge(std::weak_ptr<NODES::Node> start, std::weak_ptr<NODES::Node> end) : start(start), end(end) {}
std::shared_ptr<NODES::Node> start;
std::shared_ptr<NODES::Node> end;
std::weak_ptr<NODES::Node> start;
std::weak_ptr<NODES::Node> end;
std::weak_ptr<Connector> start_conn;
std::weak_ptr<Connector> end_conn;
@@ -39,13 +39,15 @@ namespace VISEQ::GRAPH::EDGES {
virtual EdgeType getEdgeType() const {return edgeType;}
std::shared_ptr<NODES::Node> getNextNode(std::shared_ptr<NODES::Node> origin){
return start == origin ? end : start;
std::weak_ptr<NODES::Node> getNextNode(std::weak_ptr<NODES::Node> origin){
return start.lock() == origin.lock() ? end : start;
}
void draw(Vec2Df mouse_pos, Camera2D cam) {}
};
typedef std::shared_ptr<Edge> SPTR_Edge;
typedef std::weak_ptr<Edge> WPTR_Edge;
typedef std::vector<SPTR_Edge> VEC_SPTR_Edge;
typedef std::vector<WPTR_Edge> VEC_WPTR_Edge;
}
+92 -83
View File
@@ -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:
@@ -44,38 +57,23 @@ namespace VISEQ::GRAPH {
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?
}
/*SPTR_Node next_node(SPTR_Node current, SPTR_Node last){*/
/* std::vector<std::shared_ptr<Connector>> active_connectors;*/
/**/
/*}*/
WPTR_Edge lastEdge(){
return edges.back();
}
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); // = json{{"nodes", G.nodes}, {"edges", G.edges}};
j.at("nodes").template get_to<VEC_SPTR_Node>(G.nodes);
}
};
}
+3 -1
View File
@@ -7,10 +7,12 @@
#include "graph-item.h"
#include "graph-manager.h"
#include "interaction-event.h"
#include "node.h"
#include "raylib.h"
#include "signal-manager.h"
#include "state.h"
#include "canvas.h"
#include <algorithm>
#include <memory>
namespace VISEQ::INTERACTION{
@@ -64,7 +66,7 @@ namespace VISEQ::INTERACTION{
void update(){
if(KEYS_DOWN.ctrl && IsKeyPressed(KEY_C)){
VEC_SPTR_Node selected_nodes = gm->getSelection();
VEC_WPTR_Node selected_nodes = gm->getSelection();
if(!selected_nodes.empty()) cb.pushNodes(selected_nodes);
}
+6 -19
View File
@@ -1,5 +1,6 @@
#pragma once
#include <algorithm>
#include <fcntl.h>
#include <memory>
#include <raylib.h>
@@ -26,16 +27,6 @@ namespace VISEQ::GRAPH::NODES {
Node(float x, float y) : Draggable(Vec2Df(x, y)) {}
Node(Vec2Df p) : Draggable(p) {}
/*Node(const Node& n){*/
/* distributionMode = n.distributionMode;*/
/* radius = n.radius;*/
/* config = n.config;*/
/* position = n.position;*/
/* for(auto c : n.connectors){*/
/* connectors.emplace_back(std::make_shared<Connector>(*c));*/
/* }*/
/*}*/
NodeType nodeType;
std::vector<std::shared_ptr<Node>> neighbors;
@@ -54,15 +45,10 @@ namespace VISEQ::GRAPH::NODES {
void addConnector() {
connectors.emplace_back(std::make_shared<Connector>(GraphItem::getptr(), position, radius + 5.0f));
connectors.back()->init();
}
void removeConnector(std::shared_ptr<Connector> connector){
std::erase(connectors, connector);
}
void init() {
addConnector();
void removeConnector(std::weak_ptr<Connector> connector){
std::erase(connectors, connector.lock());
}
virtual NodeType getNodeType() const {return nodeType;}
@@ -87,7 +73,7 @@ namespace VISEQ::GRAPH::NODES {
int free_connectors = 0;
for(auto c : connectors){
if(!c->partner) free_connectors++;
if(c->partner.expired()) free_connectors++;
c->setPosition(position);
c->update();
}
@@ -105,6 +91,7 @@ namespace VISEQ::GRAPH::NODES {
};
typedef std::shared_ptr<VISEQ::GRAPH::NODES::Node> SPTR_Node;
typedef std::weak_ptr<VISEQ::GRAPH::NODES::Node> WPTR_Node;
typedef std::vector<SPTR_Node> VEC_SPTR_Node;
typedef std::vector<WPTR_Node> VEC_WPTR_Node;
}
+11 -11
View File
@@ -55,7 +55,7 @@ namespace VISEQ::SIGNAL {
void reset(){
for(auto &s : signals){
s->position = s->start->position + Vec2Df{0.1, 0.1};
s->position = s->start.lock()->position + Vec2Df{0.1, 0.1};
s->next = s->start;
s->last = s->start;
}
@@ -71,16 +71,16 @@ namespace VISEQ::SIGNAL {
loop = false;
}
void addSignalAtNode(SPTR_Node node){
void addSignalAtNode(WPTR_Node node){
Color c = {(unsigned char)(20 + (rand() % 200)), 100, (unsigned char)(20 + (int)(rand() % 200)), 200};
signals.emplace_back(std::make_shared<Signal>(node->position + Vec2Df{0.5f, 0.5f}, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea!
signals.emplace_back(std::make_shared<Signal>(node.lock()->position + Vec2Df{0.5f, 0.5f}, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea!
signals.back()->next = node;
signals.back()->last = node;
signals.back()->start = node;
}
void rerouteSignal(VEC_SPTR_Node nodes, VEC_SPTR_Node adjacent_nodes){
auto reroute_signals = signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->next);});
auto reroute_signals = signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->next.lock());});
for(auto s : reroute_signals){
float dist = 10000000;
@@ -98,7 +98,7 @@ namespace VISEQ::SIGNAL {
}
void rebaseSignal(VEC_SPTR_Node nodes){
auto rebase_signals = signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->start);});
auto rebase_signals = signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->start.lock());});
for(auto s : rebase_signals){
s->start = s->next;
@@ -117,14 +117,14 @@ namespace VISEQ::SIGNAL {
mutex->lock();
if(play){
for(auto& s : signals){
s->direction = (s->next->position - s->position).norm();
s->direction = (s->next.lock()->position - s->position).norm();
s->update(diff.count());
if(s->position.dist(s->next->position) < 0.6f) {
SPTR_Node next_node = gm->next(s->next, s->last);
s->next->trigger();
if(s->position.dist(s->next.lock()->position) < 0.6f) {
WPTR_Node next_node = gm->next(s->next, s->last);
s->next.lock()->trigger();
if(next_node != s->next && next_node != SPTR_Node(nullptr) && s->next->getNodeType() == NodeType::MIDINODE) {
auto midinode = std::dynamic_pointer_cast<MidiNode>(s->next);
if(next_node.lock() != s->next.lock() && !next_node.expired() && s->next.lock()->getNodeType() == NodeType::MIDINODE) {
auto midinode = std::dynamic_pointer_cast<MidiNode>(s->next.lock());
for(auto &m : midinode->midi_outs){
if(m.second.enabled) {
if(midinode->send_note) midi.note(m.second.i, midinode->midi_note_channel, (int)Clamp(midinode->midi_note + s->midi_note_offset, 0, 127), midinode->midi_velocity, midinode->midi_gate);
+13 -4
View File
@@ -1,6 +1,7 @@
#pragma once
#include <raylib.h>
#include <string>
#include "moveable.h"
#include "node.h"
@@ -15,11 +16,11 @@ namespace VISEQ::SIGNAL {
Signal() {}
Signal(Vec2Df position, float r, float _speed, Color color) : Movable(position, Vec2Df(0,0), _speed), radius(r), color(color) {}
NODES::SPTR_Node next;
NODES::SPTR_Node last;
EDGES::SPTR_Edge edge;
NODES::WPTR_Node next;
NODES::WPTR_Node last;
EDGES::WPTR_Edge edge;
NODES::SPTR_Node start;
NODES::WPTR_Node start;
bool at_target = false;
bool run = true;
@@ -35,6 +36,14 @@ namespace VISEQ::SIGNAL {
int midi_note_offset = 0;
int midi_cc_offset = 0;
void reset(){
toStart();
}
void toStart(){
position = start.lock()->position;
}
void update(double t_delta){
// 120px / 16th = 1920px / whole note
// whole note = 2s at 120bpm
+2 -2
View File
@@ -24,7 +24,7 @@ namespace VISEQ::GRAPH::EDGES {
using namespace VISEQ::GRAPH::NODES;
inline void to_json(json& j, const VISEQ::GRAPH::EDGES::Edge& E){
j = json{{"id",E.id}, {"start", E.start->id}, {"end",E.end->id}, {"pass_forward",E.pass_forward}, {"pass_backward", E.pass_backward}};
j = json{{"id",E.id}, {"start", E.start.lock()->id}, {"end",E.end.lock()->id}, {"pass_forward",E.pass_forward}, {"pass_backward", E.pass_backward}};
}
inline void from_json(const json& j, Edge& E){
@@ -167,7 +167,7 @@ namespace VISEQ::BASE{
namespace VISEQ::SIGNAL{
inline void to_json(json& j, const Signal& G){
std::map<std::string, int> fc = {{"r",G.color.r},{"g",G.color.g},{"b",G.color.b},{"a",G.color.a}};
j = json{{"color",fc},{"position", G.position},{"radius",G.radius},{"start",G.start->id},{"next",G.next->id},{"last",G.last->id},{"speed",G.speed},{"midi_note_offset",G.midi_note_offset},{"midi_cc_offset",G.midi_cc_offset},{"multiplier",G.multiplier}};
j = json{{"color",fc},{"position", G.position},{"radius",G.radius},{"start",G.start.lock()->id},{"next",G.next.lock()->id},{"last",G.last.lock()->id},{"speed",G.speed},{"midi_note_offset",G.midi_note_offset},{"midi_cc_offset",G.midi_cc_offset},{"multiplier",G.multiplier}};
}
inline void from_json(const json& j, Signal& S){