diff --git a/src/canvas.h b/src/canvas.h index 79cf529..10b5ea0 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -1,6 +1,7 @@ #pragma once #include "draggable.h" +#include "raylib.h" #include "raymath.h" #include "state.h" namespace VISEQ::APP::CANVAS { @@ -10,9 +11,10 @@ namespace VISEQ::APP::CANVAS { Camera2D camera; Vec2Df camera_delta; + Vec2Df select_start; - virtual bool hovering() override { - return true; + virtual bool hovering() override { + return true; } virtual void drag() override { @@ -23,15 +25,33 @@ namespace VISEQ::APP::CANVAS { virtual void drawStart(){ BeginMode2D(camera); + state->hovering = false; + if(hovering()) state->istate = InteractionState::HOVER_CANVAS; } virtual void drawEnd(){ EndMode2D(); } + + void select(){ + + if(state->mouse_left.clicked){ + select_start = state->screen_mouse; + state->istate = InteractionState::DRAW_SELECTION; + } + + if(state->mouse_left.down){ + Vec2Df select1 = {state->screen_mouse.x > select_start.x ? select_start.x : state->screen_mouse.x, state->screen_mouse.y > select_start.y ? select_start.y : state->screen_mouse.y}; + Vec2Df select2 = {state->screen_mouse.x > select_start.x ? state->screen_mouse.x - select_start.x : select_start.x - state->screen_mouse.x, state->screen_mouse.y > select_start.y ? state->screen_mouse.y - select_start.y : select_start.y - state->screen_mouse.y}; + DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150}); + state->selection = (Rectangle){select1.x, select1.y, select2.x, select2.y}; + } + } virtual void draw(){ camera_delta = state->mouse_delta * (-1.0f/camera.zoom); if(hovering()) drag(); + if(state->istate == InteractionState::HOVER_CANVAS || state->istate == InteractionState::DRAW_SELECTION) select(); float wheel = GetMouseWheelMove(); if(wheel != 0){ diff --git a/src/connector.h b/src/connector.h index 3de5356..050ae20 100644 --- a/src/connector.h +++ b/src/connector.h @@ -17,6 +17,8 @@ namespace VISEQ::GRAPH { } std::shared_ptr parent; + + bool hover_connect = false; float radius = 5.0f; float orbit = 14.0f; diff --git a/src/graph-item.h b/src/graph-item.h index 9a5fa15..3d6d979 100644 --- a/src/graph-item.h +++ b/src/graph-item.h @@ -6,7 +6,7 @@ #include namespace VISEQ::GRAPH { - class GraphItem{ + class GraphItem : public std::enable_shared_from_this{ public: GraphItem() {newId(-1);} @@ -20,6 +20,10 @@ namespace VISEQ::GRAPH { int id = 0; + std::shared_ptr getptr(){ + return shared_from_this(); + } + void newId(int start){ static int _id; if(start > -1) _id = start; diff --git a/src/graph-manager.h b/src/graph-manager.h index d2ecd24..19962f0 100644 --- a/src/graph-manager.h +++ b/src/graph-manager.h @@ -2,6 +2,7 @@ #include "datatypes.h" +#include "state.h" #include "vmath.h" #include "raylib.h" #include "raymath.h" @@ -44,8 +45,12 @@ namespace VISEQ::GRAPH { EDGES::VEC_SPTR_Edge remove_edges; EDGES::VEC_SPTR_Edge split_edges; + VEC_SPTR_Node selected_nodes; + std::map counter; + std::shared_ptr state = APP::State::get(); + NODES::SPTR_Node getRandomNode(){ VEC_SPTR_GraphItem o; std::ranges::sample(nodes, std::back_inserter(o), 1, std::mt19937{std::random_device{}()}); @@ -294,13 +299,26 @@ namespace VISEQ::GRAPH { Vec2Df nb_position = nb->position - ((nb->position - node->position)).norm() * 20.0f; DrawLineV(n_position, nb_position, VS_COLOR_PINK); } - } } } void drawNodes(Vec2Df mouse_pos, Camera2D camera){ for(auto n : nodes){ + if(CheckCollisionPointRec(n->position, state->selection)) { + n->in_selection_rect = true; + } else { + n->in_selection_rect = false; + } + if(state->istate == APP::InteractionState::DRAW_SELECTION && state->mouse_left.released){ + if(CheckCollisionPointRec(n->position, state->selection)) { + n->selected = true; + n->in_selection_rect = false; + } else { + if(!state->keys_down.shift) n->selected = false; + } + state->selection = (Rectangle){0,0,0,0}; + } n->update(); if(n->picked_up) drawNeighborLines(n, mouse_pos, camera); n->draw(mouse_pos, camera); diff --git a/src/interactable.h b/src/interactable.h index 617f46b..c87ec44 100644 --- a/src/interactable.h +++ b/src/interactable.h @@ -8,6 +8,13 @@ namespace VISEQ::BASE { Interactable() {} virtual ~Interactable() {} + bool in_selection_rect = false; + bool selected = false; + + bool copied = false; + bool highlighted = false; + bool erase = false; + virtual bool hovering() = 0; virtual bool clicked() { diff --git a/src/midi-node.h b/src/midi-node.h index 461163e..9c0ca42 100644 --- a/src/midi-node.h +++ b/src/midi-node.h @@ -166,8 +166,8 @@ namespace VISEQ::GRAPH::NODES { gate_color = ColorAlphaBlend(VS_COLOR_RED, (Color){232, 125, 62, (unsigned char)Clamp(255 - midi_gate_map, 0, 255)}, WHITE); break;} } - if(!picked_up && !selected && !in_rect && !hovering()) DrawCircle(position.x, position.y, radius, gate_color); - if(selected || picked_up || in_rect || hovering()) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255}); + if(!picked_up && !selected && !in_selection_rect && !hovering()) DrawCircle(position.x, position.y, radius, gate_color); + if(selected || picked_up || in_selection_rect || hovering()) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255}); if(distributionMode == Distribution::RANDOM) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_PINK); if(distributionMode == Distribution::ROUNDROBIN) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_YELLOW); diff --git a/src/moveable.h b/src/moveable.h index 36963a4..7fe9eb6 100644 --- a/src/moveable.h +++ b/src/moveable.h @@ -21,16 +21,6 @@ namespace VISEQ::BASE { Vec2Df position; Vec2Df direction; - bool in_rect = false; - - bool hover_connect = false; - bool connecting = false; - bool selected = false; - bool highlighted = false; - bool copied = false; - - bool erase = false; - virtual void setPosition(Vec2Df _position) {position = _position;} virtual Vec2Df getPosition() {return position;}; virtual void update(double frametime) {}; diff --git a/src/node.h b/src/node.h index 8ffd59b..c6f7297 100644 --- a/src/node.h +++ b/src/node.h @@ -25,7 +25,7 @@ namespace VISEQ::GRAPH::NODES { Node(Vec2Df p) : Draggable(p) {} void addConnector() { - connectors.emplace_back(std::make_shared(std::make_shared(this), position, radius + 5.0f)); + connectors.emplace_back(std::make_shared(GraphItem::getptr(), position, radius + 5.0f)); connectors.back()->init(); } @@ -56,12 +56,12 @@ namespace VISEQ::GRAPH::NODES { virtual void trigger() {}; virtual bool hovering() override { - return CheckCollisionPointCircle(state->screen_mouse, position, radius); + return CheckCollisionPointCircle(state->screen_mouse, position, radius); } void update() override{ - - if(pickedUp()) drag(); + if(hovering()) state->hovering = true; + if(pickedUp() || selected) drag(); if(released()) putDown(); int free_connectors = 0; for(auto c : connectors){ diff --git a/src/state.h b/src/state.h index 47e9048..cc84645 100644 --- a/src/state.h +++ b/src/state.h @@ -46,6 +46,8 @@ namespace VISEQ::APP{ InteractionState istate = HOVER_CANVAS; int node_mode = 0; + + bool hovering = false; MouseState mouse_left; MouseState mouse_right; @@ -55,6 +57,7 @@ namespace VISEQ::APP{ ModifierKeys keys_pressed; ModifierKeys keys_released; + Rectangle selection; Vec2Df mouse_delta;