copy nodes with connections
This commit is contained in:
+68
-43
@@ -40,35 +40,36 @@ bool mouse_clicked = false;
|
|||||||
bool mouse_touched = false;
|
bool mouse_touched = false;
|
||||||
bool mouse_dragging = false;
|
bool mouse_dragging = false;
|
||||||
|
|
||||||
//#include "ui.h"
|
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
|
|
||||||
srand(time(NULL));
|
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();
|
app.ui.init();
|
||||||
|
|
||||||
int monitor = 1; //GetCurrentMonitor();
|
app.settings.fps = 60.0f;
|
||||||
|
|
||||||
SetWindowMonitor(monitor);
|
|
||||||
|
|
||||||
app.settings.fps = 1.0f;
|
|
||||||
app.settings.bpm = 120.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.grid = 120.0f; // 120px for a 16th note
|
||||||
// app.settings.speed = round((((app.settings.fps / (app.settings.bpm / 60.0f)) / app.settings.grid) / 4.0f) / 10.0f) * 10.0f;
|
|
||||||
|
|
||||||
// 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.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f);
|
||||||
|
|
||||||
app.settings.width = GetMonitorWidth(monitor);
|
app.settings.width = monitor_width;
|
||||||
app.settings.height = GetMonitorHeight(monitor);
|
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.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 };
|
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.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();
|
app.sm.startSignalThread();
|
||||||
|
|
||||||
Vec2D<float> drag_offset;
|
enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES};
|
||||||
|
|
||||||
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};
|
|
||||||
InteractionState istate = HOVER_CANVAS;
|
InteractionState istate = HOVER_CANVAS;
|
||||||
|
|
||||||
Vec2D<float> select_start;
|
Vec2D<float> select_start;
|
||||||
Rectangle selection;
|
Rectangle selection;
|
||||||
|
|
||||||
ToggleFullscreen();
|
|
||||||
|
|
||||||
while(!WindowShouldClose()){
|
while(!WindowShouldClose()){
|
||||||
|
|
||||||
@@ -129,6 +121,7 @@ int main(){
|
|||||||
Vec2D<float> delta = mouse_delta * (-1.0f/camera.zoom);
|
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 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 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 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);});
|
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(!connecting_nodes.empty()) istate = InteractionState::CONNECT_NODE;
|
||||||
|
|
||||||
if(!selected_nodes.empty() && IsKeyPressed(KEY_DELETE)) istate = InteractionState::DELETE_SELECTED_NODES;
|
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){
|
switch(istate){
|
||||||
case InteractionState::HOVER_CANVAS:
|
case InteractionState::HOVER_CANVAS:
|
||||||
@@ -200,22 +196,31 @@ int main(){
|
|||||||
}
|
}
|
||||||
case InteractionState::DRAG_NODE:
|
case InteractionState::DRAG_NODE:
|
||||||
{
|
{
|
||||||
if(IsKeyDown(KEY_LEFT_CONTROL)) {
|
if(!dragging_nodes.empty()){
|
||||||
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;
|
|
||||||
for(auto &n : selected_nodes){
|
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;
|
break;
|
||||||
@@ -257,6 +262,26 @@ int main(){
|
|||||||
app.removeNodes();
|
app.removeNodes();
|
||||||
break;
|
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();
|
float wheel = GetMouseWheelMove();
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class NodeManager{
|
class NodeManager{
|
||||||
@@ -21,6 +23,28 @@ class NodeManager{
|
|||||||
return o.front();
|
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){
|
int addNode(float x, float y){
|
||||||
return addNode(Vec2D<float>(x,y));
|
return addNode(Vec2D<float>(x,y));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ class Node : public Movable{
|
|||||||
bool selected = false;
|
bool selected = false;
|
||||||
bool erase = false;
|
bool erase = false;
|
||||||
bool highlighted = false;
|
bool highlighted = false;
|
||||||
|
bool copied = false;
|
||||||
|
|
||||||
int midi_out = -1;
|
int midi_out = -1;
|
||||||
|
|
||||||
|
|||||||
+19
-2
@@ -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(){
|
void removeNodes(){
|
||||||
|
|
||||||
for(auto &n : nm.nodes){
|
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);
|
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){
|
auto reroute_signals = sm.signals | std::ranges::views::filter([erase_nodes_ids](Signal s){
|
||||||
return std::ranges::contains(erase_nodes_ids, s.next);
|
return std::ranges::contains(erase_nodes_ids, s.next);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user