From bfc14d5f6ea37c9f1812ee4c9ea4543bc82facc1 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 21 Nov 2024 02:03:32 +0100 Subject: [PATCH] copy/paste partially. z-index experiments, but not working yet. --- src/app-manager.h | 98 +++++++++----------------------------------- src/clipboard.h | 35 ++++------------ src/connectable.h | 4 -- src/connector.h | 9 ++++ src/draggable.h | 21 +++++++--- src/graph-manager.h | 78 +++++++++++++++++++++++++++++++++-- src/interactable.h | 7 +++- src/midi-node.h | 3 +- src/node.h | 28 ++++++------- src/signal-manager.h | 28 ++++++++++++- 10 files changed, 172 insertions(+), 139 deletions(-) diff --git a/src/app-manager.h b/src/app-manager.h index cc0c96f..08f2507 100644 --- a/src/app-manager.h +++ b/src/app-manager.h @@ -4,14 +4,14 @@ #include "datatypes.h" #include "graph-manager.h" #include "midi-node.h" +#include "node.h" +#include "raylib.h" #include "signal-manager.h" +#include "state.h" #include "ui.h" -#include -#include #include #include -#include namespace VISEQ::APP { @@ -26,6 +26,8 @@ namespace VISEQ::APP { VISEQ::SIGNAL::SignalManager sm; VISEQ::APP::Clipboard cb; + std::shared_ptr state = APP::State::get(); + UI::AppUI ui; void updateMidiPorts(){ @@ -42,92 +44,30 @@ namespace VISEQ::APP { } } - void copyNodesAndConnections(VEC_SPTR_Node nodes, Vec2Df position){ - - VEC_SPTR_Edge copy_connections; - for(auto c : gm.edges){ - if(std::ranges::contains(nodes, c->start) && std::ranges::contains(nodes, c->end)) { - copy_connections.push_back(std::make_shared(*c)); - } - } - std::cout << copy_connections.size() << std::endl; - - for(auto old_node : nodes){ - SPTR_Node new_node; - - if(old_node->getNodeType() == NodeType::MIDINODE) { - new_node = gm.copyNode(std::dynamic_pointer_cast(old_node), position + old_node->drag_offset); - } else { - new_node = gm.copyNode(old_node, position + old_node->drag_offset); - } - - new_node->copied = false; - new_node->selected = true; - - for(auto c : copy_connections){ - if(c->start == old_node) { - c->start = new_node; - c->start->connections.push_back(c); - } - if(c->end == old_node) { - c->end = new_node; - c->end->connections.push_back(c); - } - } - } - std::ranges::copy(copy_connections.begin(), copy_connections.end(), std::back_inserter(gm.edges)); - } - void removeNodes(VEC_SPTR_Node nodes){ - for(auto n : gm.nodes){ - n->highlighted = false; - } + VEC_SPTR_Node adjacent_nodes = gm.getAdjacentNodes(nodes); - auto erase_connections = gm.edges | RANGE_FILTER([nodes](SPTR_Edge c){ return std::ranges::contains(nodes, c->start) || std::ranges::contains(nodes, c->end);}); + sm.rerouteSignal(nodes, adjacent_nodes); + sm.rebaseSignal(nodes); - VEC_SPTR_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); - } - - auto reroute_signals = sm.signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->next);}); - - for(auto s : reroute_signals){ - float dist = 10000000; - SPTR_Node next_node; - for(auto n : adjacent_nodes){ - if(n->position.dist(s->position) < dist) { - dist = n->position.dist(s->position); - next_node = n; - } - } - s->next = next_node; - s->last = next_node; - } - - auto rebase_signals = sm.signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->start);}); - - for(auto s : rebase_signals){ - s->start = s->next; - } - - for(auto n : adjacent_nodes){ - std::erase_if(n->connections, [n, nodes](VISEQ::GRAPH::EDGES::SPTR_Edge c){ return std::ranges::contains(nodes, c->start) || std::ranges::contains(nodes, c->end);}); - } - - for(auto n : nodes){ - std::erase_if(gm.edges, [n](SPTR_Edge c){ return c->start == n || c->end == n;}); - } - std::erase_if(gm.nodes, [nodes](SPTR_Node n){ return std::ranges::contains(nodes, n);}); + gm.removeNodesAndEdges(nodes); } void update(){ mutex.lock(); updateMidiPorts(); mutex.unlock(); + + if(KEYS_DOWN.ctrl && IsKeyPressed(KEY_C)){ + VEC_SPTR_Node selected_nodes = gm.getSelection(); + if(!selected_nodes.empty()) cb.pushNodes(selected_nodes); + } + + if(KEYS_DOWN.ctrl && IsKeyPressed(KEY_V)){ + VEC_SPTR_Node paste_nodes = cb.pullNodes(); + if(!paste_nodes.empty()) gm.pasteNodesAndEdges(paste_nodes, MOD_MOUSE); + } } void draw(Vec2Df mouse_pos, Camera2D camera){ diff --git a/src/clipboard.h b/src/clipboard.h index 8fdcce6..6084fb3 100644 --- a/src/clipboard.h +++ b/src/clipboard.h @@ -1,6 +1,5 @@ #pragma once -#include "midi-node.h" #include "node.h" namespace VISEQ::APP { @@ -8,36 +7,16 @@ namespace VISEQ::APP { public: Clipboard() {} - GRAPH::NODES::VEC_SPTR_Node clipboard; + std::vector clipboard; - GRAPH::NODES::VEC_SPTR_Node pasteNodes(){ - return clipboard; - } - - void copyNodes(GRAPH::NODES::VEC_SPTR_Node _nodes, Vec2Df position){ - for(auto n: _nodes){ - copyNode(n, position + n->drag_offset); - } - } - - void copyNodes(std::vector> _nodes, Vec2Df position){ - for(auto n: _nodes){ - copyNode(n, position + n->drag_offset); - } - } - - GRAPH::NODES::SPTR_Node copyNode(GRAPH::NODES::SPTR_Node n, Vec2Df position){ - std::cout << "copy basenode" << std::endl; - clipboard.insert(clipboard.end(), std::make_shared(*n)); - clipboard.back()->setPosition(position); + GRAPH::NODES::VEC_SPTR_Node pullNodes(){ return clipboard.back(); } - - GRAPH::NODES::SPTR_Node copyNode(std::shared_ptr n, Vec2Df position){ - std::cout << "copy midinode" << std::endl; - clipboard.insert(clipboard.end(), std::make_shared(*n)); - clipboard.back()->setPosition(position); - return clipboard.back(); + + void pushNodes(GRAPH::NODES::VEC_SPTR_Node selected_nodes){ + clipboard.emplace_back(); + std::ranges::copy(selected_nodes.begin(), selected_nodes.end(), std::back_inserter(clipboard.back())); + std::ranges::for_each(selected_nodes.begin(), selected_nodes.end(), [](GRAPH::NODES::SPTR_Node n){n->selected = false;}); } }; diff --git a/src/connectable.h b/src/connectable.h index 170d764..d7d8e31 100644 --- a/src/connectable.h +++ b/src/connectable.h @@ -18,10 +18,6 @@ namespace VISEQ::BASE { connectables.emplace_back(this); } - virtual bool hovering() override { - return CheckCollisionPointCircle(SCREEN_MOUSE, position, 5); - } - virtual void drag() override { DrawLineV(position, MOD_MOUSE, (Color){229, 181, 103, 255}); } diff --git a/src/connector.h b/src/connector.h index fa6b2cb..47dd8be 100644 --- a/src/connector.h +++ b/src/connector.h @@ -3,6 +3,7 @@ #include "connectable.h" #include "graph-item.h" #include "raymath.h" +#include "state.h" #include "vmath.h" namespace VISEQ::GRAPH { @@ -24,6 +25,10 @@ namespace VISEQ::GRAPH { float orbit = 14.0f; Vec2Df center_position; + virtual bool hovering() override { + return STATE != IState::DRAW_SELECTION && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); + } + void setParent(std::shared_ptr _parent){ parent = _parent; } @@ -34,6 +39,10 @@ namespace VISEQ::GRAPH { if(partner) position = center_position - ((center_position - partner->position)).norm() * (radius + orbit); } + void update() override { + BASE::Connectable::update(); + } + void draw() override { float opacity = 150.0f - Clamp(position.dist(SCREEN_MOUSE), 0.0f, 150.0f); diff --git a/src/draggable.h b/src/draggable.h index 6a84a30..4e7be14 100644 --- a/src/draggable.h +++ b/src/draggable.h @@ -56,15 +56,24 @@ namespace VISEQ::BASE { virtual void update() override { if(STATE != IState::HOVER_NODE) select(); - if(entered()){ - STATE = IState::HOVER_NODE; + if(hovering() && z_index > z_hovering) z_hovering = z_index; + + if(z_index == z_hovering || selected){ + if(pickedUp()){ + drag(); + STATE = IState::DRAG_NODE; + } } - if(exited()) STATE = IState::HOVER_CANVAS; - if(pickedUp()){ - drag(); - STATE = IState::DRAG_NODE; + if(STATE != IState::DRAG_NODE){ + if(entered()){ + STATE = IState::HOVER_NODE; + } + if(exited()){ + STATE = IState::HOVER_CANVAS; + } } if(released() && picked_up){ + std::cout << z_hovering << std::endl; putDown(); STATE = IState::HOVER_CANVAS; } diff --git a/src/graph-manager.h b/src/graph-manager.h index 39eec14..99137c2 100644 --- a/src/graph-manager.h +++ b/src/graph-manager.h @@ -2,6 +2,7 @@ #include "datatypes.h" +#include "draggable.h" #include "state.h" #include "vmath.h" #include "raylib.h" @@ -62,7 +63,11 @@ namespace VISEQ::GRAPH { std::ranges::sample(edges, std::back_inserter(o), 1, std::mt19937{std::random_device{}()}); return std::dynamic_pointer_cast(o.front()); } - + + VEC_SPTR_Node getSelection(){ + return nodes | RANGE_FILTER([](SPTR_Node n){return n->selected;}) | std::ranges::to(); + } + void addNode(SPTR_Node node){ nodes.insert(nodes.end(), node); nodes.back()->init(); @@ -197,6 +202,72 @@ namespace VISEQ::GRAPH { remove_edges.clear(); } + VEC_SPTR_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);}); + + VEC_SPTR_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); + } + + return adjacent_nodes; + } + + void removeNodesAndEdges(VEC_SPTR_Node selected_nodes){ + VEC_SPTR_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);}); + } + + 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->nodes, [selected_nodes](SPTR_Node n){ return std::ranges::contains(selected_nodes, n);}); + } + + void pasteNodesAndEdges(VEC_SPTR_Node nodes, Vec2Df position){ + + VEC_SPTR_Edge copy_connections; + for(auto c : edges){ + if(std::ranges::contains(nodes, c->start) && std::ranges::contains(nodes, c->end)) { + copy_connections.push_back(std::make_shared(*c)); + } + } + std::cout << copy_connections.size() << std::endl; + + for(auto old_node : nodes){ + SPTR_Node new_node; + + if(old_node->getNodeType() == NodeType::MIDINODE) { + new_node = copyNode(std::dynamic_pointer_cast(old_node), position + old_node->drag_offset); + } else { + new_node = copyNode(old_node, position + old_node->drag_offset); + } + + new_node->copied = false; + new_node->selected = true; + + for(auto c : copy_connections){ + if(c->start == old_node) { + c->start = new_node; + c->start->connections.push_back(c); + } + if(c->end == old_node) { + c->end = new_node; + c->end->connections.push_back(c); + } + } + } + std::ranges::copy(copy_connections.begin(), copy_connections.end(), std::back_inserter(edges)); + } + void drawEdges(Vec2Df mouse_pos, Camera2D cam){ if(!remove_edges.empty()) removeEdges(); if(!split_edges.empty()) splitEdges(); @@ -205,8 +276,8 @@ namespace VISEQ::GRAPH { Vec2Df 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->GGate(), 1.f, 4.f); - float midi_gate_v2 = Clamp((4.f / 1000.f) * c->end->GGate(), 1.f, 4.f); + float midi_gate_v1 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast(c->start)->GGate(), 1.f, 4.f); + float midi_gate_v2 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast(c->end)->GGate(), 1.f, 4.f); // Line with small connector circles Color col = {229, 181, 103, 255}; @@ -307,6 +378,7 @@ namespace VISEQ::GRAPH { for(auto n : nodes){ if(KEYS_PRESSED.ctrl && n->hovering()) state->hover_position = n->position; } + BASE::Interactable::is_hovering = false; for(auto n : nodes){ n->update(); if(n->picked_up) drawNeighborLines(n, mouse_pos, camera); diff --git a/src/interactable.h b/src/interactable.h index b5b7649..a0161b5 100644 --- a/src/interactable.h +++ b/src/interactable.h @@ -5,10 +5,13 @@ namespace VISEQ::BASE { class Interactable{ public: - Interactable() {} + Interactable() {z_index++;} virtual ~Interactable() {} - bool is_hovering = false; + inline static bool is_hovering = false; + + inline static int z_index = 0; + inline static int z_hovering = 0; virtual bool hovering() = 0; virtual bool entered() {return false;}; diff --git a/src/midi-node.h b/src/midi-node.h index 6f1c5c1..0a4658b 100644 --- a/src/midi-node.h +++ b/src/midi-node.h @@ -81,9 +81,10 @@ namespace VISEQ::GRAPH::NODES { mode = _mode; } - int Ggate(){ + int GGate(){ return midi_gate; } + void interact(){ float wheel = GetMouseWheelMove(); diff --git a/src/node.h b/src/node.h index d7fdbed..3ceddd1 100644 --- a/src/node.h +++ b/src/node.h @@ -26,15 +26,6 @@ namespace VISEQ::GRAPH::NODES { Node(float x, float y) : Draggable(Vec2Df(x, y)) {} Node(Vec2Df p) : Draggable(p) {} - void addConnector() { - connectors.emplace_back(std::make_shared(GraphItem::getptr(), position, radius + 5.0f)); - connectors.back()->init(); - } - - void init() { - addConnector(); - } - NodeType nodeType; std::vector> neighbors; @@ -49,18 +40,25 @@ namespace VISEQ::GRAPH::NODES { float radius = 15.0f; bool config = false; + virtual bool hovering() override { + return STATE != IState::DRAW_SELECTION && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); + } + + void addConnector() { + connectors.emplace_back(std::make_shared(GraphItem::getptr(), position, radius + 5.0f)); + connectors.back()->init(); + } + + void init() { + addConnector(); + } virtual NodeType getNodeType() const {return nodeType;} virtual void SMode(int mode) {}; - virtual int GGate() {return 0;}; - virtual int GActive() {return 0;}; + virtual void trigger() {}; - virtual bool hovering() override { - return STATE != APP::InteractionState::DRAW_SELECTION && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); - } - void update() override{ BASE::Draggable::update(); diff --git a/src/signal-manager.h b/src/signal-manager.h index f4fb5d1..7257c6b 100644 --- a/src/signal-manager.h +++ b/src/signal-manager.h @@ -3,11 +3,11 @@ #include "datatypes.h" #include "graph-manager.h" #include "midi-node.h" +#include "node.h" #include "signal.h" #include "midi.h" #include -#include #include #include @@ -75,6 +75,32 @@ namespace VISEQ::SIGNAL { 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);}); + + for(auto s : reroute_signals){ + float dist = 10000000; + SPTR_Node next_node; + for(auto n : adjacent_nodes){ + if(n->position.dist(s->position) < dist) { + dist = n->position.dist(s->position); + next_node = n; + } + } + s->next = next_node; + s->last = next_node; + } + + } + + void rebaseSignal(VEC_SPTR_Node nodes){ + auto rebase_signals = signals | RANGE_FILTER([nodes](SIGNAL::SPTR_Signal s){return std::ranges::contains(nodes, s->start);}); + + for(auto s : rebase_signals){ + s->start = s->next; + } + } + void removeSignal(std::shared_ptr s){ erase_signals.push_back(s); }