Drag selection and snap to grid ok. Deselect not working though...
This commit is contained in:
+173
-16
@@ -1,12 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
#include "clipboard.h"
|
#include "clipboard.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "canvas.h"
|
||||||
#include "graph-manager.h"
|
#include "graph-manager.h"
|
||||||
#include "interaction-event.h"
|
#include "interaction-event.h"
|
||||||
#include "midi-node.h"
|
#include "midi-node.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
#include "moveable.h"
|
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "signal-manager.h"
|
#include "signal-manager.h"
|
||||||
@@ -16,15 +19,21 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
namespace VISEQ::APP {
|
namespace VISEQ::APP {
|
||||||
|
class AppManager;
|
||||||
|
void to_json(json& j, const AppManager& A);
|
||||||
|
void from_json(const json& j, AppManager& A);
|
||||||
|
|
||||||
class AppManager{
|
class AppManager{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AppManager() : sm(&gm, &mutex), mouse(&gm), ui(&sm, &gm) {}
|
AppManager() : sm(&gm, &mutex), mouse(&gm), ui(&sm, &gm) {}
|
||||||
|
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
|
|
||||||
|
std::shared_ptr<CANVAS::Canvas> canvas = std::make_shared<CANVAS::Canvas>();
|
||||||
VISEQ::GRAPH::GraphManager gm;
|
VISEQ::GRAPH::GraphManager gm;
|
||||||
VISEQ::SIGNAL::SignalManager sm;
|
VISEQ::SIGNAL::SignalManager sm;
|
||||||
VISEQ::APP::Clipboard cb;
|
VISEQ::APP::Clipboard cb;
|
||||||
@@ -34,6 +43,100 @@ namespace VISEQ::APP {
|
|||||||
|
|
||||||
UI::AppUI ui;
|
UI::AppUI ui;
|
||||||
|
|
||||||
|
void init(){
|
||||||
|
canvas->camera.target = (Vector2){ state->settings.width/2.0f, state->settings.height/2.0f };
|
||||||
|
canvas->camera.offset = (Vector2){ state->settings.width/2.0f, state->settings.height/2.0f };
|
||||||
|
canvas->camera.rotation = 0.0f;
|
||||||
|
canvas->camera.zoom = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close(){
|
||||||
|
std::ofstream file("state.json");
|
||||||
|
file << json(*this);
|
||||||
|
std::cout << std::setw(4) << json(*this) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startSignals(){
|
||||||
|
sm.startSignalThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadState(){
|
||||||
|
if(std::filesystem::exists("state.json")){
|
||||||
|
std::ifstream f("state.json");
|
||||||
|
json graph = json::parse(f);
|
||||||
|
|
||||||
|
int highest_id = 0;
|
||||||
|
std::shared_ptr<Node> hid;
|
||||||
|
for(auto n : graph.at("graphmanager").at("nodes")){
|
||||||
|
std::shared_ptr<MidiNode> mn = n;
|
||||||
|
if(mn->id > highest_id) {
|
||||||
|
highest_id = mn->id;
|
||||||
|
hid = mn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
gm.addNode(mn);
|
||||||
|
//app.gm.nodes.push_back(mn);
|
||||||
|
std::cout << std::format("adding node {}", mn->id) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = 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;
|
||||||
|
gm.addConnection(start.front(), end.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gm.edges.back()->newId(highest_id); // set static id counter in base class to highest value from json file
|
||||||
|
|
||||||
|
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 = 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();
|
||||||
|
sm.signals.push_back(ms);
|
||||||
|
|
||||||
|
std::cout << std::format("adding signal with start node {}", start_id) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < 4; ++i){
|
||||||
|
gm.addMidiNode(Vec2Df{(float)i * state->settings.grid*4 + 7 * state->settings.grid, 2 * state->settings.grid*4});
|
||||||
|
}
|
||||||
|
for(int i = 3; i >= 0; --i){
|
||||||
|
gm.addMidiNode(Vec2Df{(float)i * state->settings.grid*4 + 7 * state->settings.grid, 3 * state->settings.grid*4});
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 8; ++i){
|
||||||
|
gm.addConnection(gm.nodes[i], gm.nodes[(i+1) % 8]);
|
||||||
|
}
|
||||||
|
sm.addSignalAtNode(gm.nodes.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void updateMidiPorts(){
|
void updateMidiPorts(){
|
||||||
for(auto&n : gm.nodes | RANGE_FILTER([](VISEQ::GRAPH::NODES::SPTR_Node n){return n->getNodeType() == NodeType::MIDINODE;})){
|
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);
|
auto nc = std::dynamic_pointer_cast<MidiNode>(n);
|
||||||
@@ -58,23 +161,63 @@ namespace VISEQ::APP {
|
|||||||
gm.removeNodesAndEdges(nodes);
|
gm.removeNodesAndEdges(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void doInteraction(){
|
void doInteraction(){
|
||||||
while(event_queue.size() > 0){
|
bool exit = false;
|
||||||
|
while(event_queue.size() > 0 && !exit){
|
||||||
auto e = event_queue.front();
|
auto e = event_queue.front();
|
||||||
std::cout << e.action << " " << e.item->z_index << std::endl;
|
std::cout << e.item->getType() << " " << e.action << std::endl;
|
||||||
|
|
||||||
if(e.item->getType() == GraphItemType::NODE || e.item->getType() == GraphItemType::CONNECTOR || e.item->getType() == GraphItemType::CANVAS) {
|
if(e.item->getType() == GraphItemType::CANVAS) {
|
||||||
|
if(e.action == Interaction::SELECT) {
|
||||||
|
gm.select();
|
||||||
|
std::cout << gm.selected_nodes.size() << std::endl;
|
||||||
|
canvas->clearSelectionRect();
|
||||||
|
}
|
||||||
|
if(e.action == Interaction::DESELECT) gm.deselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(e.item->getType() == GraphItemType::NODE){
|
||||||
|
if(e.action == Interaction::PICKUP) {
|
||||||
|
e.item->pickUp();
|
||||||
|
if(std::dynamic_pointer_cast<Node>(e.item)->selected){
|
||||||
|
for(auto s : gm.selected_nodes){
|
||||||
|
s->pickUp(std::dynamic_pointer_cast<Node>(e.item)->position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit = true;
|
||||||
|
}
|
||||||
|
if(e.action == Interaction::DRAG) {
|
||||||
|
e.item->drag();
|
||||||
|
if(std::dynamic_pointer_cast<Node>(e.item)->selected){
|
||||||
|
for(auto s : gm.selected_nodes){
|
||||||
|
s->drag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit = true;
|
||||||
|
}
|
||||||
|
if(e.action == Interaction::PUTDOWN) {
|
||||||
|
e.item->putDown();
|
||||||
|
if(std::dynamic_pointer_cast<Node>(e.item)->selected){
|
||||||
|
for(auto s : gm.selected_nodes){
|
||||||
|
s->putDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(exit) break;
|
||||||
|
|
||||||
|
if(e.item->getType() == GraphItemType::CONNECTOR || e.item->getType() == GraphItemType::CANVAS) {
|
||||||
switch(e.action){
|
switch(e.action){
|
||||||
case VISEQ::APP::Interaction::PICKUP:
|
case VISEQ::APP::Interaction::PICKUP:
|
||||||
{
|
{
|
||||||
e.item->pickUp();
|
e.item->pickUp();
|
||||||
goto exit_loop;
|
exit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VISEQ::APP::Interaction::DRAG:
|
case VISEQ::APP::Interaction::DRAG:
|
||||||
{
|
{
|
||||||
e.item->drag();
|
e.item->drag();
|
||||||
goto exit_loop;
|
exit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VISEQ::APP::Interaction::PUTDOWN:
|
case VISEQ::APP::Interaction::PUTDOWN:
|
||||||
@@ -83,18 +226,23 @@ namespace VISEQ::APP {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event_queue.pop_front();
|
event_queue.pop_front();
|
||||||
}
|
}
|
||||||
exit_loop:
|
|
||||||
event_queue.clear();
|
event_queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(){
|
void update(){
|
||||||
|
state->update(canvas->camera);
|
||||||
|
canvas->update();
|
||||||
|
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
updateMidiPorts();
|
updateMidiPorts();
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
doInteraction();
|
doInteraction();
|
||||||
mouse.update();
|
mouse.update();
|
||||||
|
|
||||||
@@ -109,15 +257,24 @@ namespace VISEQ::APP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(Vec2Df mouse_pos, Camera2D camera){
|
void draw(){
|
||||||
gm.drawNodes(mouse_pos, camera);
|
BeginDrawing();
|
||||||
gm.drawEdges(mouse_pos, camera);
|
ClearBackground((Color){46,46,46});
|
||||||
sm.drawSignals(mouse_pos, camera);
|
canvas->drawStart();
|
||||||
|
canvas->draw();
|
||||||
|
|
||||||
|
gm.drawNodes(SCREEN_MOUSE, canvas->camera);
|
||||||
|
gm.drawEdges(SCREEN_MOUSE, canvas->camera);
|
||||||
|
sm.drawSignals(SCREEN_MOUSE, canvas->camera);
|
||||||
|
|
||||||
|
canvas->drawEnd();
|
||||||
|
drawUI();
|
||||||
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawUI(Vec2Df mouse_pos, Camera2D camera){
|
void drawUI(){
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
ui.draw(mouse_pos, camera);
|
ui.draw(SCREEN_MOUSE, canvas->camera);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+7
-2
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "interaction-event.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "draggable.h"
|
#include "draggable.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
@@ -25,17 +26,20 @@ namespace VISEQ::APP::CANVAS {
|
|||||||
Vec2Df select1 = {SCREEN_MOUSE.x > select_start.x ? select_start.x : SCREEN_MOUSE.x, SCREEN_MOUSE.y > select_start.y ? select_start.y : SCREEN_MOUSE.y};
|
Vec2Df select1 = {SCREEN_MOUSE.x > select_start.x ? select_start.x : SCREEN_MOUSE.x, SCREEN_MOUSE.y > select_start.y ? select_start.y : SCREEN_MOUSE.y};
|
||||||
Vec2Df select2 = {SCREEN_MOUSE.x > select_start.x ? SCREEN_MOUSE.x - select_start.x : select_start.x - SCREEN_MOUSE.x, SCREEN_MOUSE.y > select_start.y ? SCREEN_MOUSE.y - select_start.y : select_start.y - SCREEN_MOUSE.y};
|
Vec2Df select2 = {SCREEN_MOUSE.x > select_start.x ? SCREEN_MOUSE.x - select_start.x : select_start.x - SCREEN_MOUSE.x, SCREEN_MOUSE.y > select_start.y ? SCREEN_MOUSE.y - select_start.y : select_start.y - SCREEN_MOUSE.y};
|
||||||
state->selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};
|
state->selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};
|
||||||
DrawRectangleLines(state->selection.x, state->selection.y, state->selection.width, state->selection.height, (Color){150,150,150,150});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pickUp() override {
|
virtual void pickUp() override {
|
||||||
BASE::Draggable::pickUp();
|
BASE::Draggable::pickUp();
|
||||||
state->selection = (Rectangle){0,0,0,0};
|
|
||||||
select_start = SCREEN_MOUSE;
|
select_start = SCREEN_MOUSE;
|
||||||
|
state->pushEvent({getPtr(), Interaction::DESELECT});
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void putDown() override {
|
virtual void putDown() override {
|
||||||
BASE::Draggable::putDown();
|
BASE::Draggable::putDown();
|
||||||
|
state->pushEvent({getPtr(), Interaction::SELECT});
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearSelectionRect(){
|
||||||
state->selection = (Rectangle){0,0,0,0};
|
state->selection = (Rectangle){0,0,0,0};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +88,7 @@ namespace VISEQ::APP::CANVAS {
|
|||||||
DrawPixel(x, y, (Color){130,130,130,200});
|
DrawPixel(x, y, (Color){130,130,130,200});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(state->selection.width > 0 || state->selection.height > 0) DrawRectangleLines(state->selection.x, state->selection.y, state->selection.width, state->selection.height, (Color){150,150,150,150});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-11
@@ -36,26 +36,32 @@ namespace VISEQ::BASE {
|
|||||||
picked_up = true;
|
picked_up = true;
|
||||||
drag_offset = position - SCREEN_MOUSE;
|
drag_offset = position - SCREEN_MOUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void pickUp(Vec2Df selection_origin) override {
|
||||||
|
picked_up = true;
|
||||||
|
drag_offset = position - selection_origin;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void drag() override {
|
virtual void drag() override {
|
||||||
state->selection_origin = position;
|
// state->selection_origin = position;
|
||||||
if(KEYS_PRESSED.ctrl){
|
/*if(KEYS_PRESSED.ctrl){*/
|
||||||
selection_offset = position - state->selection_origin;
|
/* selection_offset = position - state->selection_origin;*/
|
||||||
}
|
/*}*/
|
||||||
if(KEYS_DOWN.ctrl){
|
/*if(KEYS_DOWN.ctrl){*/
|
||||||
position = MOD_MOUSE + selection_offset;
|
/* position = MOD_MOUSE + selection_offset;*/
|
||||||
} else {
|
/*} else {*/
|
||||||
position = MOD_MOUSE + drag_offset;
|
position = MOD_MOUSE + drag_offset;
|
||||||
}
|
/*}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void putDown() override {
|
virtual void putDown() override {
|
||||||
picked_up = false;
|
picked_up = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void select() override {
|
virtual bool select() override {
|
||||||
in_selection_rect = CheckCollisionPointRec(position, state->selection);
|
/*in_selection_rect = */
|
||||||
if(MOUSE_LEFT.released) selected = (KEYS_DOWN.shift && selected) || in_selection_rect;
|
/*if(MOUSE_LEFT.released) selected = (KEYS_DOWN.shift && selected) || in_selection_rect;*/
|
||||||
|
return CheckCollisionPointRec(position, state->selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
+18
-3
@@ -46,7 +46,7 @@ namespace VISEQ::GRAPH {
|
|||||||
EDGES::VEC_SPTR_Edge remove_edges;
|
EDGES::VEC_SPTR_Edge remove_edges;
|
||||||
EDGES::VEC_SPTR_Edge split_edges;
|
EDGES::VEC_SPTR_Edge split_edges;
|
||||||
|
|
||||||
//VEC_SPTR_Node selected_nodes;
|
VEC_SPTR_Node selected_nodes;
|
||||||
|
|
||||||
std::map<NODES::SPTR_Node, int> counter;
|
std::map<NODES::SPTR_Node, int> counter;
|
||||||
|
|
||||||
@@ -63,9 +63,24 @@ namespace VISEQ::GRAPH {
|
|||||||
std::ranges::sample(edges, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
|
std::ranges::sample(edges, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
|
||||||
return std::dynamic_pointer_cast<VISEQ::GRAPH::EDGES::Edge>(o.front());
|
return std::dynamic_pointer_cast<VISEQ::GRAPH::EDGES::Edge>(o.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void select(){
|
||||||
|
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;});
|
||||||
|
}
|
||||||
|
|
||||||
|
void deselect(){
|
||||||
|
for(auto s : selected_nodes){
|
||||||
|
s->selected = false;
|
||||||
|
}
|
||||||
|
selected_nodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
VEC_SPTR_Node getSelection(){
|
VEC_SPTR_Node getSelection(){
|
||||||
return nodes | RANGE_FILTER([](SPTR_Node n){return n->selected;}) | std::ranges::to<VEC_SPTR_Node>();
|
return selected_nodes;
|
||||||
|
//return nodes | RANGE_FILTER([](SPTR_Node n){return n->selected;}) | std::ranges::to<VEC_SPTR_Node>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNode(SPTR_Node node){
|
void addNode(SPTR_Node node){
|
||||||
|
|||||||
+5
-2
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
#include "vmath.h"
|
||||||
namespace VISEQ::BASE {
|
namespace VISEQ::BASE {
|
||||||
|
|
||||||
class Interactable{
|
class Interactable{
|
||||||
@@ -13,7 +14,7 @@ namespace VISEQ::BASE {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Interactable() {}
|
virtual ~Interactable() {}
|
||||||
|
|
||||||
bool is_hovering = false;
|
bool is_hovering = false;
|
||||||
|
|
||||||
int z_index = 0;
|
int z_index = 0;
|
||||||
@@ -33,9 +34,11 @@ namespace VISEQ::BASE {
|
|||||||
|
|
||||||
virtual bool released() {
|
virtual bool released() {
|
||||||
return IsMouseButtonReleased(MOUSE_BUTTON_LEFT);
|
return IsMouseButtonReleased(MOUSE_BUTTON_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual GRAPH::GraphItemType getType() = 0;
|
virtual GRAPH::GraphItemType getType() = 0;
|
||||||
virtual void pickUp() = 0;
|
virtual void pickUp() = 0;
|
||||||
|
virtual void pickUp(Vec2Df position) = 0;
|
||||||
virtual void drag() = 0;
|
virtual void drag() = 0;
|
||||||
virtual void putDown() = 0;
|
virtual void putDown() = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
namespace VISEQ::APP{
|
namespace VISEQ::APP{
|
||||||
|
|
||||||
enum Interaction {NONE, HOVER, CLICK, HOLD, RELEASE, PICKUP, DRAG, PUTDOWN, SELECTED};
|
enum Interaction {NONE, HOVER, CLICK, HOLD, RELEASE, PICKUP, DRAG, PUTDOWN, SELECT, DESELECT};
|
||||||
|
|
||||||
struct InteractionEvent{
|
struct InteractionEvent{
|
||||||
std::shared_ptr<BASE::Interactable> item;
|
std::shared_ptr<BASE::Interactable> item;
|
||||||
|
|||||||
+9
-141
@@ -5,45 +5,23 @@
|
|||||||
* 2024 Sebastian Kujas
|
* 2024 Sebastian Kujas
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "canvas.h"
|
|
||||||
#include "state.h"
|
|
||||||
#include "datatypes.h"
|
|
||||||
#include "graph-manager.h"
|
|
||||||
#include "node.h"
|
|
||||||
#include "vmath.h"
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
#define RAYGUI_IMPLEMENTATION
|
#define RAYGUI_IMPLEMENTATION
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
#include <raymath.h>
|
#include <raymath.h>
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
#include "app-manager.h"
|
#include "app-manager.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "midi-node.h"
|
|
||||||
|
|
||||||
#include "nlohmann/json.hpp"
|
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <ranges>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
std::shared_ptr<VISEQ::APP::CANVAS::Canvas> canvas = std::make_shared<VISEQ::APP::CANVAS::Canvas>();
|
|
||||||
VISEQ::APP::AppManager app;
|
VISEQ::APP::AppManager app;
|
||||||
|
|
||||||
std::shared_ptr<VISEQ::APP::State> state = VISEQ::APP::State::get();
|
std::shared_ptr<VISEQ::APP::State> state = VISEQ::APP::State::get();
|
||||||
|
|
||||||
Vec2Df mouse_pos;
|
|
||||||
Vec2Df drag_start;
|
|
||||||
//Vec2Df global_mouse;
|
|
||||||
|
|
||||||
bool mouse_clicked = false;
|
|
||||||
bool mouse_touched = false;
|
|
||||||
bool mouse_dragging = false;
|
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
@@ -60,9 +38,7 @@ int main(){
|
|||||||
SetWindowSize(monitor_width - 300, monitor_height - 300);
|
SetWindowSize(monitor_width - 300, monitor_height - 300);
|
||||||
|
|
||||||
//ToggleFullscreen();
|
//ToggleFullscreen();
|
||||||
|
|
||||||
app.ui.init();
|
|
||||||
|
|
||||||
state->settings.fps = 60.0f;
|
state->settings.fps = 60.0f;
|
||||||
state->settings.bpm = 120.0f;
|
state->settings.bpm = 120.0f;
|
||||||
state->settings.grid = 60.0f; // 120px for a 16th note
|
state->settings.grid = 60.0f; // 120px for a 16th note
|
||||||
@@ -74,111 +50,16 @@ int main(){
|
|||||||
|
|
||||||
SetTargetFPS(state->settings.fps);
|
SetTargetFPS(state->settings.fps);
|
||||||
|
|
||||||
canvas->camera.target = (Vector2){ state->settings.width/2.0f, state->settings.height/2.0f };
|
app.init();
|
||||||
canvas->camera.offset = (Vector2){ state->settings.width/2.0f, state->settings.height/2.0f };
|
app.ui.init();
|
||||||
canvas->camera.rotation = 0.0f;
|
|
||||||
canvas->camera.zoom = 1.0f;
|
|
||||||
|
|
||||||
if(std::filesystem::exists("state.json")){
|
app.loadState();
|
||||||
std::ifstream f("state.json");
|
|
||||||
json graph = json::parse(f);
|
|
||||||
|
|
||||||
// state->settings = graph.at("settings");
|
app.startSignals();
|
||||||
|
|
||||||
int highest_id = 0;
|
|
||||||
std::shared_ptr<Node> hid;
|
|
||||||
for(auto n : graph.at("graphmanager").at("nodes")){
|
|
||||||
std::shared_ptr<MidiNode> mn = n;
|
|
||||||
if(mn->id > highest_id) {
|
|
||||||
highest_id = mn->id;
|
|
||||||
hid = mn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
app.gm.addNode(mn);
|
|
||||||
//app.gm.nodes.push_back(mn);
|
|
||||||
std::cout << std::format("adding node {}", mn->id) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
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>();
|
|
||||||
|
|
||||||
if(!start.empty() && !end.empty()) {
|
|
||||||
std::cout << std::format("connection {} to {}", start_id, end_id) << std::endl;
|
|
||||||
app.gm.addConnection(start.front(), end.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
app.gm.edges.back()->newId(highest_id); // set static id counter in base class to highest value from json file
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
for(int i = 0; i < 4; ++i){
|
|
||||||
app.gm.addMidiNode(Vec2Df{(float)i * state->settings.grid*4 + 7 * state->settings.grid, 2 * state->settings.grid*4});
|
|
||||||
}
|
|
||||||
for(int i = 3; i >= 0; --i){
|
|
||||||
app.gm.addMidiNode(Vec2Df{(float)i * state->settings.grid*4 + 7 * state->settings.grid, 3 * state->settings.grid*4});
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
app.sm.startSignalThread();
|
|
||||||
|
|
||||||
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};
|
|
||||||
InteractionState istate = HOVER_CANVAS;
|
|
||||||
|
|
||||||
Vec2Df node_menu_position;
|
|
||||||
|
|
||||||
Vec2Df select_start;
|
|
||||||
Rectangle selection;
|
|
||||||
|
|
||||||
Vec2Df scale_start;
|
|
||||||
Vec2Df scale_rectangle;
|
|
||||||
|
|
||||||
float drag_distance = 0;
|
|
||||||
|
|
||||||
VEC_SPTR_Node copied_nodes;
|
|
||||||
|
|
||||||
while(!WindowShouldClose()){
|
while(!WindowShouldClose()){
|
||||||
|
app.update();
|
||||||
BeginDrawing();
|
app.draw();
|
||||||
ClearBackground((Color){46,46,46});
|
|
||||||
canvas->drawStart();
|
|
||||||
|
|
||||||
state->update(canvas->camera);
|
|
||||||
|
|
||||||
/*else if(IsKeyDown(KEY_LEFT_SHIFT)){*/
|
/*else if(IsKeyDown(KEY_LEFT_SHIFT)){*/
|
||||||
/* float steps = round((dragNode->neighbors.front()->position.dist(mouse_pos)) / state->settings.grid) * state->settings.grid;*/
|
/* float steps = round((dragNode->neighbors.front()->position.dist(mouse_pos)) / state->settings.grid) * state->settings.grid;*/
|
||||||
@@ -490,22 +371,9 @@ int main(){
|
|||||||
/* }*/
|
/* }*/
|
||||||
/*};*/
|
/*};*/
|
||||||
|
|
||||||
canvas->update();
|
|
||||||
app.update();
|
|
||||||
|
|
||||||
canvas->draw();
|
|
||||||
app.draw(SCREEN_MOUSE, canvas->camera);
|
|
||||||
canvas->drawEnd();
|
|
||||||
|
|
||||||
app.drawUI(SCREEN_MOUSE, canvas->camera);
|
|
||||||
|
|
||||||
EndDrawing();
|
|
||||||
}
|
}
|
||||||
|
app.close();
|
||||||
|
|
||||||
std::ofstream file("state.json");
|
|
||||||
file << json(app);
|
|
||||||
|
|
||||||
std::cout << std::setw(4) << json(app) << std::endl;
|
|
||||||
|
|
||||||
CloseWindow();
|
CloseWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
||||||
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
||||||
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
||||||
if(selected) state->pushEvent({getPtr(), APP::Interaction::SELECTED});
|
|
||||||
|
|
||||||
if(state->selection.width > 0) select();
|
|
||||||
|
|
||||||
int free_connectors = 0;
|
int free_connectors = 0;
|
||||||
for(auto c : connectors){
|
for(auto c : connectors){
|
||||||
|
|||||||
+1
-1
@@ -20,6 +20,6 @@ namespace VISEQ::BASE {
|
|||||||
return (selected || hovering()) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
return (selected || hovering()) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void select() = 0;
|
virtual bool select() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user