copy nodes with connections

This commit is contained in:
Sebastian
2024-10-26 16:31:23 +02:00
parent 53289bb9e2
commit cb08f69e3b
4 changed files with 112 additions and 45 deletions
+68 -43
View File
@@ -40,35 +40,36 @@ bool mouse_clicked = false;
bool mouse_touched = false;
bool mouse_dragging = false;
//#include "ui.h"
int main(){
srand(time(NULL));
InitWindow(2560, 1440, "VISEQ");
InitWindow(1920, 1080, "VISEQ");
int current_monitor = GetCurrentMonitor();
int monitor_width = GetMonitorWidth(current_monitor);
int monitor_height = GetMonitorHeight(current_monitor);
SetWindowMonitor(current_monitor);
SetWindowState(FLAG_WINDOW_RESIZABLE);
SetWindowSize(monitor_width - 300, monitor_height - 300);
//ToggleFullscreen();
app.ui.init();
int monitor = 1; //GetCurrentMonitor();
SetWindowMonitor(monitor);
app.settings.fps = 1.0f;
app.settings.fps = 60.0f;
app.settings.bpm = 120.0f;
app.settings.grid = 120.0f; //round(((app.settings.fps / (app.settings.bpm / 60.0f)) * app.settings.speed) / 4.0f); // from quarter notes to 16th notes = div by 4
// app.settings.speed = round((((app.settings.fps / (app.settings.bpm / 60.0f)) / app.settings.grid) / 4.0f) / 10.0f) * 10.0f;
app.settings.grid = 120.0f; // 120px for a 16th note
// 16th note = 120px (festgelegt)
// ganze note = 1920px
// ganze note bei 120bpm = 2s
// 120bpm = 960px/s
app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f);
app.settings.width = GetMonitorWidth(monitor);
app.settings.height = GetMonitorHeight(monitor);
app.settings.width = monitor_width;
app.settings.height = monitor_height;
SetTargetFPS(60.0f);
SetTargetFPS(app.settings.fps);
camera.target = (Vector2){ app.settings.width/2.0f, app.settings.height/2.0f };
camera.offset = (Vector2){ app.settings.width/2.0f, app.settings.height/2.0f };
@@ -86,24 +87,15 @@ int main(){
app.cm.addConnection(app.nm.nodes[i].id, app.nm.nodes[(i+1) % 8].id);
}
app.sm.addSignalAtNode((app.nm.nodes | std::views::values).front().id);
app.sm.addSignalAtNode((app.nm.nodes | std::views::values).front().id);
app.sm.startSignalThread();
Vec2D<float> drag_offset;
Vec2D<float> cam_drag_offset;
Vec2D<float> cam_mouse_drag_offset;
double drag_timer = GetTime();
enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES};
enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES};
InteractionState istate = HOVER_CANVAS;
Vec2D<float> select_start;
Rectangle selection;
ToggleFullscreen();
while(!WindowShouldClose()){
@@ -129,6 +121,7 @@ int main(){
Vec2D<float> delta = mouse_delta * (-1.0f/camera.zoom);
auto dragging_nodes = app.nm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n) { return n.dragging;});
auto copied_nodes = app.nm.nodes | std::ranges::views::values | std::ranges::views::filter([](Node n) { return n.copied;});
auto connecting_nodes = app.nm.nodes | std::ranges::views::values| std::ranges::views::filter([](Node n) { return n.connecting;});
auto selected_nodes = app.nm.nodes | std::ranges::views::values| std::ranges::views::filter([](Node n) { return n.selected && !n.dragging;});
auto hovering_nodes = app.nm.nodes | std::ranges::views::values| std::ranges::views::filter([&mouse_pos](Node n) { return CheckCollisionPointCircle(mouse_pos, n.position, n.radius);});
@@ -143,6 +136,9 @@ int main(){
if(!connecting_nodes.empty()) istate = InteractionState::CONNECT_NODE;
if(!selected_nodes.empty() && IsKeyPressed(KEY_DELETE)) istate = InteractionState::DELETE_SELECTED_NODES;
if(!selected_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_C)) istate = InteractionState::COPY_SELECTED_NODES;
if(!copied_nodes.empty() && IsKeyDown(KEY_LEFT_CONTROL) && IsKeyPressed(KEY_V)) istate = InteractionState::PASTE_SELECTED_NODES;
switch(istate){
case InteractionState::HOVER_CANVAS:
@@ -200,22 +196,31 @@ int main(){
}
case InteractionState::DRAG_NODE:
{
if(IsKeyDown(KEY_LEFT_CONTROL)) {
dragging_nodes.front().position = (Vec2D<float>){round((mouse_pos.x+dragging_nodes.front().drag_offset.x)/app.settings.grid)*app.settings.grid, round((mouse_pos.y+dragging_nodes.front().drag_offset.y)/app.settings.grid)*app.settings.grid};
} else {
dragging_nodes.front().position = mouse_pos + dragging_nodes.front().drag_offset;
}
for(auto &n : selected_nodes){
if(!n.picked_up) n.drag_offset = n.position - dragging_nodes.front().position;
n.picked_up = true;
n.position = dragging_nodes.front().position + n.drag_offset;
}
if(mouse_released) {
dragging_nodes.front().dragging = false;
if(!dragging_nodes.empty()){
for(auto &n : selected_nodes){
n.picked_up = false;
if(!n.picked_up) n.drag_offset = n.position - dragging_nodes.front().position;
n.picked_up = true;
}
if(IsKeyDown(KEY_LEFT_CONTROL)) {
dragging_nodes.front().position = (Vec2D<float>){round((mouse_pos.x+dragging_nodes.front().drag_offset.x)/app.settings.grid)*app.settings.grid, round((mouse_pos.y+dragging_nodes.front().drag_offset.y)/app.settings.grid)*app.settings.grid};
} else {
dragging_nodes.front().position = mouse_pos + dragging_nodes.front().drag_offset;
}
for(auto &n : selected_nodes){
n.position = dragging_nodes.front().position + n.drag_offset;
}
if(mouse_released) {
for(auto &n : dragging_nodes){
n.dragging = false;
n.picked_up = false;
}
for(auto &n : selected_nodes){
n.picked_up = false;
n.dragging = false;
}
}
}
break;
@@ -257,6 +262,26 @@ int main(){
app.removeNodes();
break;
}
case InteractionState::COPY_SELECTED_NODES:
{
for(auto &n: copied_nodes){
n.copied = false;
}
for(auto &n: selected_nodes){
n.copied = true;
n.selected = false;
}
break;
}
case InteractionState::PASTE_SELECTED_NODES:
{
for(auto &n: copied_nodes){
n.drag_offset = (n.position - copied_nodes.front().position);
}
// app.nm.copyNodes(mouse_pos);
app.copyNodesAndConnections(mouse_pos);
break;
}
};
float wheel = GetMouseWheelMove();
+24
View File
@@ -1,9 +1,11 @@
#pragma once
#include "node.h"
#include <algorithm>
#include <iterator>
#include <random>
#include <ranges>
#include <utility>
#include <vector>
class NodeManager{
@@ -21,6 +23,28 @@ class NodeManager{
return 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++;
}
}
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;
}
int addNode(float x, float y){
return addNode(Vec2D<float>(x,y));
}
+1
View File
@@ -36,6 +36,7 @@ class Node : public Movable{
bool selected = false;
bool erase = false;
bool highlighted = false;
bool copied = false;
int midi_out = -1;
+19 -2
View File
@@ -44,6 +44,25 @@ class AppState{
}
}
void copyNodesAndConnections(Vec2D<float> position){
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);});
for(auto &n : copy_nodes_ids){
int old_id = n;
int new_id = nm.copyNode(n, position + nm.nodes[n].drag_offset);
for(auto &c : copy_connections){
if(c.v1 == old_id) c.v1 = new_id;
if(c.v2 == old_id) c.v2 = new_id;
}
}
cm.connections.insert(cm.connections.end(), copy_connections.cbegin(), copy_connections.cend());
}
void removeNodes(){
for(auto &n : nm.nodes){
@@ -66,8 +85,6 @@ class AppState{
if(!nm.nodes.at(c.v2).selected) adjacent_nodes_ids.push_back(c.v2);
}
// std::ranges::for_each(adjacent_nodes_ids, [this](int id){ nm.nodes.at(id).highlighted = true;} );
auto reroute_signals = sm.signals | std::ranges::views::filter([erase_nodes_ids](Signal s){
return std::ranges::contains(erase_nodes_ids, s.next);
});