2024-10-09 02:01:23 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
2024-11-04 19:28:12 +01:00
|
|
|
* VISEQ - The Visual Sequencer
|
2024-10-30 02:03:03 +01:00
|
|
|
* 2024 Sebastian Kujas
|
2024-10-09 02:01:23 +02:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2024-11-03 03:48:49 +01:00
|
|
|
#include "graph-manager.h"
|
2024-11-03 15:15:42 +01:00
|
|
|
#include "node.h"
|
2024-11-03 03:48:49 +01:00
|
|
|
#include "vmath.h"
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <fstream>
|
2024-10-25 16:41:37 +02:00
|
|
|
#define RAYGUI_IMPLEMENTATION
|
2024-10-13 04:22:09 +02:00
|
|
|
#include <raylib.h>
|
|
|
|
|
#include <raymath.h>
|
|
|
|
|
|
2024-11-02 15:52:16 +01:00
|
|
|
#include "state-manager.h"
|
|
|
|
|
#include "datatypes.h"
|
|
|
|
|
#include "midi-node.h"
|
|
|
|
|
|
|
|
|
|
#include "nlohmann/json.hpp"
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <cmath>
|
2024-11-02 15:52:16 +01:00
|
|
|
#include <ranges>
|
|
|
|
|
#include <memory>
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-11-02 15:52:16 +01:00
|
|
|
using json = nlohmann::json;
|
2024-10-22 01:55:31 +02:00
|
|
|
|
2024-11-03 03:48:49 +01:00
|
|
|
VISEQ::APP::AppState app;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-11-02 15:52:16 +01:00
|
|
|
Vec2Df mouse_pos;
|
|
|
|
|
Vec2Df drag_start;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-10-25 16:41:37 +02:00
|
|
|
Camera2D camera = { {0} };
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
bool mouse_clicked = false;
|
|
|
|
|
bool mouse_touched = false;
|
2024-10-13 04:22:09 +02:00
|
|
|
bool mouse_dragging = false;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
|
|
|
|
int main(){
|
|
|
|
|
|
|
|
|
|
srand(time(NULL));
|
|
|
|
|
|
2024-11-01 14:08:27 +01:00
|
|
|
InitWindow(1920, 1080, "VISEQ - The Visual Sequencer");
|
2024-10-26 16:31:23 +02:00
|
|
|
|
|
|
|
|
int current_monitor = GetCurrentMonitor();
|
|
|
|
|
int monitor_width = GetMonitorWidth(current_monitor);
|
|
|
|
|
int monitor_height = GetMonitorHeight(current_monitor);
|
2024-10-25 16:41:37 +02:00
|
|
|
|
2024-10-26 16:31:23 +02:00
|
|
|
SetWindowMonitor(current_monitor);
|
|
|
|
|
SetWindowState(FLAG_WINDOW_RESIZABLE);
|
|
|
|
|
|
|
|
|
|
SetWindowSize(monitor_width - 300, monitor_height - 300);
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-26 16:31:23 +02:00
|
|
|
//ToggleFullscreen();
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-26 16:31:23 +02:00
|
|
|
app.ui.init();
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-26 16:31:23 +02:00
|
|
|
app.settings.fps = 60.0f;
|
2024-10-25 16:41:37 +02:00
|
|
|
app.settings.bpm = 120.0f;
|
2024-10-30 02:00:40 +01:00
|
|
|
app.settings.grid = 60.0f; // 120px for a 16th note
|
2024-10-23 03:25:57 +02:00
|
|
|
|
2024-10-30 02:00:40 +01:00
|
|
|
app.settings.speed = (app.settings.grid * 16.0f) * (app.settings.bpm / 120.f);
|
2024-10-25 16:41:37 +02:00
|
|
|
|
2024-10-28 02:07:47 +01:00
|
|
|
app.settings.width = monitor_width - 300;
|
|
|
|
|
app.settings.height = monitor_height - 300;
|
2024-10-25 02:43:41 +02:00
|
|
|
|
2024-10-26 16:31:23 +02:00
|
|
|
SetTargetFPS(app.settings.fps);
|
2024-10-13 04:22:09 +02:00
|
|
|
|
2024-10-25 16:41:37 +02:00
|
|
|
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 };
|
2024-10-13 04:22:09 +02:00
|
|
|
camera.rotation = 0.0f;
|
2024-10-25 16:41:37 +02:00
|
|
|
camera.zoom = 1.0f;
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-11-03 03:48:49 +01:00
|
|
|
if(std::filesystem::exists("state.json")){
|
|
|
|
|
std::ifstream f("state.json");
|
|
|
|
|
json graph = json::parse(f);
|
2024-10-22 01:55:31 +02:00
|
|
|
|
2024-11-04 01:00:59 +01:00
|
|
|
app.settings = graph.at("settings");
|
|
|
|
|
|
2024-11-04 09:53:08 +01:00
|
|
|
int highest_id = 0;
|
|
|
|
|
std::shared_ptr<Node> hid;
|
2024-11-03 15:15:42 +01:00
|
|
|
for(auto n : graph.at("graphmanager").at("nodes")){
|
|
|
|
|
std::shared_ptr<MidiNode> mn = n;
|
2024-11-04 09:53:08 +01:00
|
|
|
if(mn->id > highest_id) {
|
|
|
|
|
highest_id = mn->id;
|
|
|
|
|
hid = mn;
|
|
|
|
|
}
|
2024-11-05 00:51:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto e : graph.at("graphmanager").at("edges")){
|
|
|
|
|
if(e.at("id") > highest_id){
|
|
|
|
|
highest_id = e.at("id");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto n : graph.at("graphmanager").at("nodes")){
|
|
|
|
|
std::shared_ptr<MidiNode> mn = n;
|
2024-11-13 14:39:46 +01:00
|
|
|
app.gm.addNode(mn);
|
|
|
|
|
//app.gm.nodes.push_back(mn);
|
2024-11-04 01:00:59 +01:00
|
|
|
std::cout << std::format("adding node {}", mn->id) << std::endl;
|
2024-11-03 15:15:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto e : graph.at("graphmanager").at("edges")){
|
|
|
|
|
int start_id = e.at("start").get<int>();
|
|
|
|
|
int end_id = e.at("end").get<int>();
|
|
|
|
|
|
|
|
|
|
VEC_SPTR_Node start = app.gm.nodes | RANGE_FILTER([start_id](SPTR_Node n){return n->id == start_id;}) | std::ranges::to<VEC_SPTR_Node>();
|
|
|
|
|
VEC_SPTR_Node end = app.gm.nodes | RANGE_FILTER([end_id](SPTR_Node n){return n->id == end_id;}) | std::ranges::to<VEC_SPTR_Node>();
|
|
|
|
|
|
2024-11-04 01:00:59 +01:00
|
|
|
if(!start.empty() && !end.empty()) {
|
|
|
|
|
std::cout << std::format("connection {} to {}", start_id, end_id) << std::endl;
|
|
|
|
|
app.gm.addConnection(start.front(), end.front());
|
|
|
|
|
}
|
2024-11-03 15:15:42 +01:00
|
|
|
|
|
|
|
|
}
|
2024-11-05 00:51:25 +01:00
|
|
|
|
2024-11-05 17:44:12 +01:00
|
|
|
app.gm.edges.back()->newId(highest_id); // set static id counter in base class to highest value from json file
|
2024-11-05 00:51:25 +01:00
|
|
|
|
2024-11-04 01:00:59 +01:00
|
|
|
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_SPTR_Node start = app.gm.nodes | RANGE_FILTER([start_id](SPTR_Node n){return n->id == start_id;}) | std::ranges::to<VEC_SPTR_Node>();
|
|
|
|
|
VEC_SPTR_Node last = app.gm.nodes | RANGE_FILTER([last_id](SPTR_Node n){return n->id == last_id;}) | std::ranges::to<VEC_SPTR_Node>();
|
|
|
|
|
VEC_SPTR_Node next = app.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();
|
|
|
|
|
app.sm.signals.push_back(ms);
|
|
|
|
|
|
|
|
|
|
std::cout << std::format("adding signal with start node {}", start_id) << std::endl;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-03 03:48:49 +01:00
|
|
|
} else {
|
|
|
|
|
for(int i = 0; i < 4; ++i){
|
|
|
|
|
app.gm.addMidiNode(Vec2Df{(float)i * app.settings.grid*4 + 7 * app.settings.grid, 2 * app.settings.grid*4});
|
|
|
|
|
}
|
|
|
|
|
for(int i = 3; i >= 0; --i){
|
|
|
|
|
app.gm.addMidiNode(Vec2Df{(float)i * app.settings.grid*4 + 7 * app.settings.grid, 3 * app.settings.grid*4});
|
|
|
|
|
}
|
2024-11-01 02:38:47 +01:00
|
|
|
|
2024-11-03 03:48:49 +01:00
|
|
|
for(int i = 0; i < 8; ++i){
|
|
|
|
|
app.gm.addConnection(app.gm.nodes[i], app.gm.nodes[(i+1) % 8]);
|
|
|
|
|
}
|
|
|
|
|
app.sm.addSignalAtNode(app.gm.nodes.front());
|
|
|
|
|
}
|
2024-11-01 02:38:47 +01:00
|
|
|
|
2024-10-25 16:41:37 +02:00
|
|
|
app.sm.startSignalThread();
|
2024-10-22 01:55:31 +02:00
|
|
|
|
2024-11-08 01:43:06 +01:00
|
|
|
enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, ADD_NODES_MENU, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, SCALE_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES};
|
2024-10-25 02:43:41 +02:00
|
|
|
InteractionState istate = HOVER_CANVAS;
|
2024-10-24 21:05:05 +02:00
|
|
|
|
2024-11-08 01:43:06 +01:00
|
|
|
Vec2Df node_menu_position;
|
|
|
|
|
|
2024-11-02 15:52:16 +01:00
|
|
|
Vec2Df select_start;
|
2024-10-23 00:23:24 +02:00
|
|
|
Rectangle selection;
|
|
|
|
|
|
2024-11-06 15:35:25 +01:00
|
|
|
Vec2Df scale_start;
|
|
|
|
|
Vec2Df scale_rectangle;
|
|
|
|
|
|
2024-11-08 01:43:06 +01:00
|
|
|
float drag_distance = 0;
|
|
|
|
|
|
2024-11-01 14:08:27 +01:00
|
|
|
VEC_SPTR_Node copied_nodes;
|
2024-10-24 00:39:39 +02:00
|
|
|
|
2024-11-13 15:35:39 +01:00
|
|
|
Vec2Df modified_mouse;
|
2024-11-02 23:12:38 +01:00
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
while(!WindowShouldClose()){
|
2024-10-09 02:01:23 +02:00
|
|
|
|
2024-10-25 02:43:41 +02:00
|
|
|
BeginDrawing();
|
|
|
|
|
ClearBackground((Color){46,46,46});
|
|
|
|
|
BeginMode2D(camera);
|
2024-10-26 02:14:41 +02:00
|
|
|
|
2024-10-30 02:00:40 +01:00
|
|
|
app.settings.speed = (app.settings.grid * 16.0f) * (app.settings.bpm / 120.f);
|
2024-10-23 03:25:57 +02:00
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
Vector2 mp = GetScreenToWorld2D(GetMousePosition(), camera);
|
2024-11-02 15:52:16 +01:00
|
|
|
Vec2Df mouse_pos = {(float)mp.x, (float)mp.y};
|
|
|
|
|
Vec2Df cam_pos = {camera.offset.x, camera.offset.y};
|
2024-10-20 23:42:38 +02:00
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
bool mouse_down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
|
|
|
|
|
bool mouse_clicked = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
|
|
|
|
bool mouse_released = IsMouseButtonReleased(MOUSE_BUTTON_LEFT);
|
2024-10-24 21:05:05 +02:00
|
|
|
|
|
|
|
|
bool mouse_right_down = IsMouseButtonDown(MOUSE_BUTTON_RIGHT);
|
|
|
|
|
bool mouse_right_clicked = IsMouseButtonPressed(MOUSE_BUTTON_RIGHT);
|
|
|
|
|
bool mouse_right_released = IsMouseButtonReleased(MOUSE_BUTTON_RIGHT);
|
2024-10-10 02:59:27 +02:00
|
|
|
|
2024-11-02 15:52:16 +01:00
|
|
|
Vec2Df mouse_delta = {GetMouseDelta().x, GetMouseDelta().y};
|
|
|
|
|
Vec2Df delta = mouse_delta * (-1.0f/camera.zoom);
|
2024-11-13 15:35:39 +01:00
|
|
|
|
|
|
|
|
if(IsKeyDown(KEY_LEFT_CONTROL)) {
|
|
|
|
|
modified_mouse.x = round(mouse_pos.x / app.settings.grid) * app.settings.grid;
|
|
|
|
|
modified_mouse.y = round(mouse_pos.y / app.settings.grid) * app.settings.grid;
|
|
|
|
|
} else if(IsKeyDown(KEY_LEFT_SHIFT)){
|
|
|
|
|
float steps = round((dragNode->neighbors.front()->position.dist(mouse_pos)) / app.settings.grid) * app.settings.grid;
|
|
|
|
|
if(dragNode->neighbors.size() > 1){
|
|
|
|
|
Vec2Df dn1 = dragNode->neighbors[0]->position;
|
|
|
|
|
Vec2Df dn2 = dragNode->neighbors[1]->position;
|
|
|
|
|
Vec2Df v1_orth = dn1.center(dn2);
|
|
|
|
|
|
|
|
|
|
if(dn1.x < dn2.x) std::swap(dn1,dn2);
|
|
|
|
|
|
|
|
|
|
float dist = dn1.dist(dn2);
|
|
|
|
|
float dist_orth = std::sqrt(std::pow(steps,2) - std::pow(dist/2,2));
|
|
|
|
|
|
|
|
|
|
if(mouse_pos.y < v1_orth.y) dist_orth *= -1;
|
|
|
|
|
|
|
|
|
|
Vec2Df v1_orth_t = v1_orth + (dn1-dn2).norm().orth() * dist_orth;
|
|
|
|
|
DrawLineV(dn1, dn2, VS_COLOR_RED);
|
|
|
|
|
DrawLineV(v1_orth, v1_orth_t, VS_COLOR_RED);
|
|
|
|
|
DrawCircleV(v1_orth, 3.0f, VS_COLOR_RED);
|
|
|
|
|
dragNode->position = v1_orth_t;
|
|
|
|
|
} else if(!dragNode->neighbors.empty()){
|
|
|
|
|
float pol_r = steps;
|
|
|
|
|
float pol_theta = Vector2Angle(Vec2Df{1,0},(mouse_pos - dragNode->neighbors.front()->position));
|
|
|
|
|
Vec2Df polar = VISEQ::VMATH::polarToCartesian(pol_r, pol_theta);
|
|
|
|
|
dragNode->position = dragNode->neighbors.front()->position + polar;
|
|
|
|
|
}
|
2024-11-10 01:56:33 +01:00
|
|
|
// auto dragging_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->dragging;});
|
|
|
|
|
/*auto connecting_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->connecting;});*/
|
|
|
|
|
/*auto selected_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->selected && !n->picked_up;}) | std::ranges::to<VEC_SPTR_Node>();*/
|
|
|
|
|
/*auto hovering_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->hovering();});*/
|
|
|
|
|
/*auto hovering_connectors = app.gm.nodes | RANGE_FILTER([&mouse_pos](SPTR_Node n) { return CheckCollisionPointCircle(mouse_pos, (n->position - ((n->position - mouse_pos)).norm() * (n->radius + 14.0f)), 8.0f);});*/
|
|
|
|
|
/**/
|
|
|
|
|
/*for(auto &n : app.gm.nodes ){*/
|
|
|
|
|
/* if(hovering_connectors.empty()) n->hover_connect = false;*/
|
|
|
|
|
/*}*/
|
|
|
|
|
/**/
|
|
|
|
|
/*if(istate != InteractionState::ADD_NODES_MENU && !mouse_down && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::HOVER_CANVAS;*/
|
|
|
|
|
/*if((mouse_clicked || mouse_down || mouse_released) && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty() && istate != InteractionState::SCALE_SELECTION) istate = InteractionState::DRAW_SELECTION;*/
|
|
|
|
|
/**/
|
|
|
|
|
/*if(!hovering_nodes.empty() && !mouse_down && !mouse_right_down) istate = InteractionState::HOVER_NODE;*/
|
|
|
|
|
/*if(!dragging_nodes.empty()) istate = InteractionState::DRAG_NODE; */
|
|
|
|
|
/*if(!hovering_connectors.empty() && !mouse_right_down && istate == InteractionState::HOVER_CANVAS) istate = InteractionState::HOVER_CONNECTOR;*/
|
|
|
|
|
/*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;*/
|
|
|
|
|
/**/
|
|
|
|
|
/*if(IsKeyPressed(KEY_TAB)) {*/
|
|
|
|
|
/* app.settings.mode = (app.settings.mode + 1) % 3;*/
|
|
|
|
|
/* app.gm.setNodeMode(app.settings.mode);*/
|
|
|
|
|
/*}*/
|
|
|
|
|
|
|
|
|
|
/*if(!selected_nodes.empty()){*/
|
|
|
|
|
/* float offset = 30;*/
|
|
|
|
|
/* Vec2Df corner_tl = {50000, 50000};*/
|
|
|
|
|
/* Vec2Df corner_br = {-50000, -50000};*/
|
|
|
|
|
/* std::shared_ptr<Node> node_tl;*/
|
|
|
|
|
/* std::shared_ptr<Node> node_br;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* for(auto n : selected_nodes){*/
|
|
|
|
|
/* float x = n->position.x;*/
|
|
|
|
|
/* float y = n->position.y;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(x < corner_tl.x && y < corner_tl.y) node_tl = n;*/
|
|
|
|
|
/* if(x > corner_br.x && y > corner_br.y) node_br = n;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(x <= corner_tl.x) corner_tl.x = x;*/
|
|
|
|
|
/* if(x >= corner_br.x) corner_br.x = x;*/
|
|
|
|
|
/* if(y <= corner_tl.y) corner_tl.y = y;*/
|
|
|
|
|
/* if(y >= corner_br.y) corner_br.y = y;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* corner_tl -= Vec2Df(offset, offset);*/
|
|
|
|
|
/* corner_br += Vec2Df(offset, offset);*/
|
|
|
|
|
/**/
|
|
|
|
|
/* DrawRectangleLines(corner_tl.x, corner_tl.y, (corner_br.x - corner_tl.x), (corner_br.y - corner_tl.y), VS_COLOR_LIGHTGREY);*/
|
|
|
|
|
/* DrawCircleV(corner_br, 5, YELLOW);*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(istate == InteractionState::SCALE_SELECTION && mouse_released){*/
|
|
|
|
|
/* istate = InteractionState::HOVER_CANVAS;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(mouse_clicked && corner_br.dist(mouse_pos) < 10){*/
|
|
|
|
|
/* scale_start = (corner_br - corner_tl);*/
|
|
|
|
|
/* for(auto n : selected_nodes){*/
|
|
|
|
|
/* n->drag_offset = n->position - node_tl->position;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* istate = InteractionState::SCALE_SELECTION;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(istate == InteractionState::SCALE_SELECTION && mouse_down){*/
|
|
|
|
|
/* Vec2Df scale = (mouse_pos - corner_tl) / scale_start;*/
|
|
|
|
|
/* if(IsKeyDown(KEY_LEFT_SHIFT)) scale.y = scale.x;*/
|
|
|
|
|
/* DrawText(std::format("{:.2f} {:.2f}", scale.x, scale.y).c_str(), corner_br.x+5, corner_br.y+5, 10, RED);*/
|
|
|
|
|
/* for(auto n : selected_nodes){*/
|
|
|
|
|
/* n->position = node_tl->position + (n->drag_offset * scale);*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* istate = InteractionState::SCALE_SELECTION;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/*}*/
|
|
|
|
|
|
|
|
|
|
/*switch(istate){*/
|
|
|
|
|
/* case InteractionState::SCALE_SELECTION:*/
|
|
|
|
|
/* case InteractionState::HOVER_CANVAS:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* for(auto &n : app.gm.nodes){ */
|
|
|
|
|
/* n->hover_connect = false;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(mouse_right_clicked){*/
|
|
|
|
|
/* drag_distance = 0;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(mouse_right_down) {*/
|
|
|
|
|
/* camera.target = Vector2Add(camera.target, delta);*/
|
|
|
|
|
/* drag_distance += delta.length();*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(mouse_right_released && drag_distance < 5) {*/
|
|
|
|
|
/* node_menu_position = mouse_pos;*/
|
|
|
|
|
/* istate = InteractionState::ADD_NODES_MENU;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::ADD_NODES_MENU:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* DrawCircleV(node_menu_position, 30, VS_COLOR_LIGHTGREY);*/
|
|
|
|
|
/* DrawCircleLines(node_menu_position.x, node_menu_position.y, 32, VS_COLOR_DARKGREY);*/
|
|
|
|
|
/**/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::DRAW_SELECTION:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* if(mouse_clicked){*/
|
|
|
|
|
/* select_start = mouse_pos;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(mouse_down){*/
|
|
|
|
|
/* Vec2Df select1 = {mouse_pos.x > select_start.x ? select_start.x : mouse_pos.x, mouse_pos.y > select_start.y ? select_start.y : mouse_pos.y};*/
|
|
|
|
|
/* Vec2Df select2 = {mouse_pos.x > select_start.x ? mouse_pos.x - select_start.x : select_start.x - mouse_pos.x, mouse_pos.y > select_start.y ? mouse_pos.y - select_start.y : select_start.y - mouse_pos.y};*/
|
|
|
|
|
/* DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150});*/
|
|
|
|
|
/* selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};*/
|
|
|
|
|
/**/
|
|
|
|
|
/* for(auto& n : app.gm.nodes){*/
|
|
|
|
|
/* if(CheckCollisionPointRec(n->position, selection)) {*/
|
|
|
|
|
/* n->in_rect = true;*/
|
|
|
|
|
/* } else {*/
|
|
|
|
|
/* n->in_rect = false;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(mouse_released){ */
|
|
|
|
|
/* int n_selected = 0;*/
|
|
|
|
|
/* for(auto& n : app.gm.nodes){*/
|
|
|
|
|
/* if(CheckCollisionPointRec(n->position, selection)) {*/
|
|
|
|
|
/* n->selected = true;*/
|
|
|
|
|
/* n->in_rect = false;*/
|
|
|
|
|
/* n_selected++;*/
|
|
|
|
|
/* } else {*/
|
|
|
|
|
/* if(!IsKeyDown(KEY_LEFT_SHIFT)) n->selected = false;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(n_selected > 0) copied_nodes.clear();*/
|
|
|
|
|
/* selection = (Rectangle){0,0,0,0};*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::HOVER_NODE:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* if(mouse_clicked) {*/
|
|
|
|
|
/* if(IsKeyDown(KEY_LEFT_SHIFT)) {*/
|
|
|
|
|
/* hovering_nodes.front()->selected = true;*/
|
|
|
|
|
/* } else {*/
|
|
|
|
|
/* hovering_nodes.front()->dragging = true;*/
|
|
|
|
|
/* hovering_nodes.front()->drag_offset = hovering_nodes.front()->position - mouse_pos;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(mouse_right_clicked) hovering_nodes.front()->config = true;*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::DRAG_NODE:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* if(!dragging_nodes.empty()){*/
|
|
|
|
|
/* SPTR_Node dragNode = dragging_nodes.front();*/
|
|
|
|
|
/**/
|
|
|
|
|
/* for(auto &n : selected_nodes){*/
|
|
|
|
|
/* if(!n->picked_up) n->drag_offset = n->position - dragNode->position;*/
|
|
|
|
|
/* n->picked_up = true;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(IsKeyDown(KEY_LEFT_CONTROL)) {*/
|
|
|
|
|
/* dragNode->position.x = round((mouse_pos.x + dragNode->drag_offset.x) / app.settings.grid) * app.settings.grid;*/
|
|
|
|
|
/* dragNode->position.y = round((mouse_pos.y + dragNode->drag_offset.y) / app.settings.grid) * app.settings.grid;*/
|
|
|
|
|
/* } else if(IsKeyDown(KEY_LEFT_SHIFT)){*/
|
|
|
|
|
/* float steps = round((dragNode->neighbors.front()->position.dist(mouse_pos)) / app.settings.grid) * app.settings.grid;*/
|
|
|
|
|
/* if(dragNode->neighbors.size() > 1){*/
|
|
|
|
|
/* Vec2Df dn1 = dragNode->neighbors[0]->position;*/
|
|
|
|
|
/* Vec2Df dn2 = dragNode->neighbors[1]->position;*/
|
|
|
|
|
/* Vec2Df v1_orth = dn1.center(dn2);*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(dn1.x < dn2.x) std::swap(dn1,dn2);*/
|
|
|
|
|
/**/
|
|
|
|
|
/* float dist = dn1.dist(dn2);*/
|
|
|
|
|
/* float dist_orth = std::sqrt(std::pow(steps,2) - std::pow(dist/2,2));*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(mouse_pos.y < v1_orth.y) dist_orth *= -1;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* Vec2Df v1_orth_t = v1_orth + (dn1-dn2).norm().orth() * dist_orth;*/
|
|
|
|
|
/* DrawLineV(dn1, dn2, VS_COLOR_RED);*/
|
|
|
|
|
/* DrawLineV(v1_orth, v1_orth_t, VS_COLOR_RED);*/
|
|
|
|
|
/* DrawCircleV(v1_orth, 3.0f, VS_COLOR_RED);*/
|
|
|
|
|
/* dragNode->position = v1_orth_t;*/
|
|
|
|
|
/* } else if(!dragNode->neighbors.empty()){*/
|
|
|
|
|
/* float pol_r = steps;*/
|
|
|
|
|
/* float pol_theta = Vector2Angle(Vec2Df{1,0},(mouse_pos - dragNode->neighbors.front()->position));*/
|
|
|
|
|
/* Vec2Df polar = VISEQ::VMATH::polarToCartesian(pol_r, pol_theta); */
|
|
|
|
|
/* dragNode->position = dragNode->neighbors.front()->position + polar;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* } else {*/
|
|
|
|
|
/* dragNode->position = mouse_pos + dragNode->drag_offset;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/**/
|
|
|
|
|
/* for(auto &n : selected_nodes){*/
|
|
|
|
|
/* n->position = dragNode->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;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::HOVER_CONNECTOR:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* if(!hovering_connectors.empty()){*/
|
|
|
|
|
/* hovering_connectors.front()->hover_connect = true;*/
|
|
|
|
|
/* if(mouse_clicked) hovering_connectors.front()->connecting = true;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::CONNECT_NODE:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* Vec2Df connector_position = connecting_nodes.front()->position - ((connecting_nodes.front()->position - mouse_pos)).norm() * (connecting_nodes.front()->radius + 14.0f);*/
|
|
|
|
|
/* Vec2Df target_position = mouse_pos;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(IsKeyDown(KEY_LEFT_CONTROL)) {*/
|
|
|
|
|
/* target_position.x = round((mouse_pos.x) / app.settings.grid) * app.settings.grid;*/
|
|
|
|
|
/* target_position.y = round((mouse_pos.y) / app.settings.grid) * app.settings.grid;*/
|
|
|
|
|
/* } else if(IsKeyDown(KEY_LEFT_SHIFT)){*/
|
|
|
|
|
/* std::shared_ptr<Node> closest = app.gm.getClosestNode(mouse_pos);*/
|
|
|
|
|
/* float steps = round((closest->position.dist(mouse_pos)) / app.settings.grid) * app.settings.grid;*/
|
|
|
|
|
/* float pol_r = steps;*/
|
|
|
|
|
/* float pol_theta = Vector2Angle(Vec2Df{1,0},(mouse_pos - closest->position));*/
|
|
|
|
|
/**/
|
|
|
|
|
/* Vec2Df polar = VISEQ::VMATH::polarToCartesian(pol_r, pol_theta); */
|
|
|
|
|
/* target_position = closest->position + polar;*/
|
|
|
|
|
/* } else {*/
|
|
|
|
|
/* target_position = mouse_pos;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(connecting_nodes.front()->connecting && mouse_down){*/
|
|
|
|
|
/* DrawLine(connector_position.x, connector_position.y, target_position.x, target_position.y, (Color){229, 181, 103, 255});*/
|
|
|
|
|
/* connecting_nodes.front()->hover_connect = true;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(!hovering_connectors.empty()) {*/
|
|
|
|
|
/* hovering_connectors.front()->hover_connect = true;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(mouse_released) {*/
|
|
|
|
|
/* if(&hovering_nodes.front() != &connecting_nodes.front() && &connecting_nodes.front() != &hovering_connectors.front()){*/
|
|
|
|
|
/* if(!hovering_nodes.empty()){*/
|
|
|
|
|
/* app.gm.addConnection(connecting_nodes.front(), hovering_nodes.front());*/
|
|
|
|
|
/* } else if(!hovering_connectors.empty()){*/
|
|
|
|
|
/* app.gm.addConnection(connecting_nodes.front(), hovering_connectors.front());*/
|
|
|
|
|
/* } else {*/
|
|
|
|
|
/* SPTR_Node new_node = app.gm.copyNode(std::dynamic_pointer_cast<MidiNode>(connecting_nodes.front()), target_position);*/
|
|
|
|
|
/* new_node->connecting = false;*/
|
|
|
|
|
/* app.gm.addConnection(connecting_nodes.front(), new_node);*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* connecting_nodes.front()->connecting = false;*/
|
|
|
|
|
/* istate = InteractionState::HOVER_CANVAS;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::DELETE_SELECTED_NODES:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* app.removeNodes(selected_nodes | std::ranges::to<VEC_SPTR_Node>());*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::COPY_SELECTED_NODES:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* std::ranges::copy(selected_nodes.begin(), selected_nodes.end(), std::back_inserter(copied_nodes));*/
|
|
|
|
|
/* std::ranges::for_each(selected_nodes.begin(), selected_nodes.end(), [](SPTR_Node n){n->selected = false;});*/
|
|
|
|
|
/* selected_nodes.clear();*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* case InteractionState::PASTE_SELECTED_NODES:*/
|
|
|
|
|
/* {*/
|
|
|
|
|
/* for(auto n: copied_nodes){*/
|
|
|
|
|
/* n->drag_offset = (n->position - copied_nodes.front()->position);*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* app.copyNodesAndConnections(copied_nodes, mouse_pos);*/
|
|
|
|
|
/* //copied_nodes.clear();*/
|
|
|
|
|
/* break;*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/*};*/
|
|
|
|
|
|
|
|
|
|
/*float wheel = GetMouseWheelMove();*/
|
|
|
|
|
/*if(wheel != 0){*/
|
|
|
|
|
/* if(!hovering_nodes.empty() && hovering_nodes.front()->getNodeType() == NodeType::MIDINODE) {*/
|
|
|
|
|
/* VEC_SPTR_Node modify_nodes;*/
|
|
|
|
|
/* std::copy_if(selected_nodes.begin(), selected_nodes.end(), std::back_inserter(modify_nodes), [](SPTR_Node n){ return n->getNodeType() == NodeType::MIDINODE;});*/
|
|
|
|
|
/* if(selected_nodes.empty()) std::copy_if(hovering_nodes.begin(), hovering_nodes.end(), std::back_inserter(modify_nodes), [modify_nodes](SPTR_Node n){ return n->getNodeType() == NodeType::MIDINODE && !std::ranges::contains(modify_nodes, n);});*/
|
|
|
|
|
/**/
|
|
|
|
|
/* for(auto n : modify_nodes){*/
|
|
|
|
|
/* std::shared_ptr<MidiNode> midiNode = std::dynamic_pointer_cast<MidiNode>(n);*/
|
|
|
|
|
/* if(IsKeyDown(KEY_LEFT_CONTROL) && !IsKeyDown(KEY_LEFT_ALT)){*/
|
|
|
|
|
/* switch(app.settings.mode){*/
|
|
|
|
|
/* case 0:{*/
|
|
|
|
|
/* midiNode->midi_note += wheel;*/
|
|
|
|
|
/* break;}*/
|
|
|
|
|
/* case 1:{*/
|
|
|
|
|
/* midiNode->midi_cc += wheel;*/
|
|
|
|
|
/* break;}*/
|
|
|
|
|
/* case 2:{*/
|
|
|
|
|
/* midiNode->midi_pitch_bend += wheel;*/
|
|
|
|
|
/* break;}*/
|
|
|
|
|
/* };*/
|
|
|
|
|
/* if(midiNode->midi_note < 0 ) midiNode->midi_note = VISEQ::MIDI::Notes.size()-1;*/
|
|
|
|
|
/* if(midiNode->midi_note >= VISEQ::MIDI::Notes.size() ) midiNode->midi_note = 0;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(midiNode->midi_cc < 0 ) midiNode->midi_cc = 127;*/
|
|
|
|
|
/* if(midiNode->midi_cc > 127 ) midiNode->midi_cc = 0;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* if(midiNode->midi_pitch_bend < 0 ) midiNode->midi_pitch_bend = 0;*/
|
|
|
|
|
/* if(midiNode->midi_pitch_bend > 16383 ) midiNode->midi_pitch_bend = 16383;*/
|
|
|
|
|
/**/
|
|
|
|
|
/* } else if(IsKeyDown(KEY_LEFT_SHIFT) && !IsKeyDown(KEY_LEFT_ALT)) {*/
|
|
|
|
|
/* midiNode->midi_velocity += wheel;*/
|
|
|
|
|
/* if(midiNode->midi_velocity < 0 ) midiNode->midi_velocity = 127;*/
|
|
|
|
|
/* if(midiNode->midi_velocity > 127 ) midiNode->midi_velocity = 0; */
|
|
|
|
|
/* } else if(IsKeyDown(KEY_LEFT_ALT)) {*/
|
|
|
|
|
/* switch(app.settings.mode){*/
|
|
|
|
|
/* case 0:{*/
|
|
|
|
|
/* float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f);*/
|
|
|
|
|
/* midiNode->midi_gate += incr;*/
|
|
|
|
|
/* if(midiNode->midi_gate < 0 ) midiNode->midi_gate = 0;*/
|
|
|
|
|
/* break;}*/
|
|
|
|
|
/* case 1:{*/
|
|
|
|
|
/* midiNode->midi_cc_value += wheel;*/
|
|
|
|
|
/* if(midiNode->midi_cc_value < 0 ) midiNode->midi_cc_value = 0;*/
|
|
|
|
|
/* if(midiNode->midi_cc_value > 127 ) midiNode->midi_cc_value = 127;*/
|
|
|
|
|
/* break;}*/
|
|
|
|
|
/* case 2:{*/
|
|
|
|
|
/* float incr = (float)wheel * (IsKeyDown(KEY_LEFT_SHIFT) ? 100.0f : IsKeyDown(KEY_LEFT_CONTROL) ? 1000.0f : 10.0f);*/
|
|
|
|
|
/* midiNode->midi_pitch_bend += incr;*/
|
|
|
|
|
/* if(midiNode->midi_pitch_bend < 0 ) midiNode->midi_pitch_bend = 0;*/
|
|
|
|
|
/* if(midiNode->midi_pitch_bend > 16383 ) midiNode->midi_pitch_bend = 16383;*/
|
|
|
|
|
/* break;}*/
|
|
|
|
|
/* };*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/* if(!IsKeyDown(KEY_LEFT_SHIFT) && !IsKeyDown(KEY_LEFT_CONTROL) && !IsKeyDown(KEY_LEFT_ALT)){*/
|
|
|
|
|
/* Vector2 mouseWorldPos = GetScreenToWorld2D(GetMousePosition(), camera);*/
|
|
|
|
|
/* camera.offset = GetMousePosition();*/
|
|
|
|
|
/* camera.target = mouseWorldPos;*/
|
|
|
|
|
/* float scaleFactor = 1.0f + (0.25f*fabsf(wheel));*/
|
|
|
|
|
/* if (wheel < 0) scaleFactor = 1.0f/scaleFactor;*/
|
|
|
|
|
/* camera.zoom = Clamp(camera.zoom*scaleFactor, 0.125f, 64.0f);*/
|
|
|
|
|
/* }*/
|
|
|
|
|
/*}*/
|
2024-10-20 23:42:38 +02:00
|
|
|
|
2024-10-25 16:41:37 +02:00
|
|
|
for(int x = -app.settings.grid*100; x < app.settings.grid*100; x+=app.settings.grid){
|
|
|
|
|
for(int y = -app.settings.grid*100; y < app.settings.grid*100; y+=app.settings.grid){
|
2024-10-25 02:43:41 +02:00
|
|
|
DrawPixel(x, y, (Color){130,130,130,200});
|
|
|
|
|
}
|
2024-10-10 02:59:27 +02:00
|
|
|
}
|
2024-10-26 02:14:41 +02:00
|
|
|
|
2024-11-01 02:38:47 +01:00
|
|
|
app.draw(mouse_pos, camera);
|
2024-10-23 03:25:57 +02:00
|
|
|
|
2024-10-25 02:43:41 +02:00
|
|
|
EndMode2D();
|
2024-10-24 00:39:39 +02:00
|
|
|
|
2024-10-25 16:41:37 +02:00
|
|
|
app.drawUI(&mouse_pos, &camera);
|
2024-10-13 04:22:09 +02:00
|
|
|
|
|
|
|
|
EndDrawing();
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-04 01:00:59 +01:00
|
|
|
std::ofstream file("state.json");
|
|
|
|
|
file << json(app);
|
2024-11-03 03:48:49 +01:00
|
|
|
|
|
|
|
|
std::cout << std::setw(4) << json(app) << std::endl;
|
2024-11-02 23:12:38 +01:00
|
|
|
|
2024-10-13 04:22:09 +02:00
|
|
|
CloseWindow();
|
|
|
|
|
|
|
|
|
|
return 0;
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|