diff --git a/src/app-manager.h b/src/app-manager.h index 12de590..4fd6646 100644 --- a/src/app-manager.h +++ b/src/app-manager.h @@ -121,11 +121,14 @@ namespace VISEQ::APP { } std::erase_if(gm.nodes, [nodes](SPTR_Node n){ return std::ranges::contains(nodes, n);}); } - - void draw(Vec2Df mouse_pos, Camera2D camera){ + + void update(){ mutex.lock(); updateMidiPorts(); mutex.unlock(); + } + + void draw(Vec2Df mouse_pos, Camera2D camera){ gm.drawNodes(mouse_pos, camera); gm.drawEdges(mouse_pos, camera); sm.drawSignals(mouse_pos, camera); diff --git a/src/canvas.h b/src/canvas.h index 10b5ea0..7663b9c 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -25,17 +25,18 @@ namespace VISEQ::APP::CANVAS { virtual void drawStart(){ BeginMode2D(camera); - state->hovering = false; - if(hovering()) state->istate = InteractionState::HOVER_CANVAS; + /*state->hovering = false;*/ + /*if(hovering()) state->istate = InteractionState::HOVER_CANVAS;*/ } virtual void drawEnd(){ EndMode2D(); } - void select(){ + void select_rect(){ if(state->mouse_left.clicked){ + state->selection = (Rectangle){0,0,0,0}; select_start = state->screen_mouse; state->istate = InteractionState::DRAW_SELECTION; } @@ -43,15 +44,18 @@ namespace VISEQ::APP::CANVAS { 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}; } + + if(state->mouse_left.released){ + state->istate = InteractionState::HOVER_CANVAS; + } } - virtual void draw(){ + virtual void update() override { camera_delta = state->mouse_delta * (-1.0f/camera.zoom); if(hovering()) drag(); - if(state->istate == InteractionState::HOVER_CANVAS || state->istate == InteractionState::DRAW_SELECTION) select(); + if(state->istate == InteractionState::HOVER_CANVAS || state->istate == InteractionState::DRAW_SELECTION) select_rect(); float wheel = GetMouseWheelMove(); if(wheel != 0){ @@ -63,6 +67,10 @@ namespace VISEQ::APP::CANVAS { camera.zoom = Clamp(camera.zoom*scaleFactor, 0.125f, 64.0f); } } + } + + virtual void draw(){ + if(state->istate == InteractionState::DRAW_SELECTION) DrawRectangleLines(state->selection.x, state->selection.y, state->selection.width, state->selection.height, (Color){150,150,150,150}); for(int x = -state->settings.grid*100; x < state->settings.grid*100; x+=state->settings.grid){ for(int y = -state->settings.grid*100; y < state->settings.grid*100; y+=state->settings.grid){ diff --git a/src/draggable.h b/src/draggable.h index 9ed02b7..20584b9 100644 --- a/src/draggable.h +++ b/src/draggable.h @@ -1,11 +1,13 @@ #pragma once -#include "interactable.h" #include "moveable.h" +#include "raylib.h" +#include "selectable.h" +#include "state.h" #include "vmath.h" namespace VISEQ::BASE { - class Draggable : public Movable, public Interactable{ + class Draggable : public Movable, public Selectable{ public: Draggable() {} Draggable(float x, float y) : Movable(Vec2Df(x, y), 960.0f) {} @@ -17,7 +19,7 @@ namespace VISEQ::BASE { bool picked_up = false; virtual bool pickedUp() { - if(clicked() && held()) { + if(clicked() && held() && state->istate == APP::InteractionState::HOVER_NODE) { picked_up = true; drag_offset = position - state->screen_mouse; } @@ -35,5 +37,19 @@ namespace VISEQ::BASE { virtual void putDown(){ picked_up = false; } + + virtual void select() override { + selected = (state->keys_down.shift && selected) || CheckCollisionPointRec(position, state->selection); + /**/ + /*//std::cout << "select" << std::endl;*/ + /*if(CheckCollisionPointRec(position, state->selection)) {*/ + /* in_selection_rect = true;*/ + /*} else {*/ + /* in_selection_rect = false;*/ + /*}*/ + /*if(released() && in_selection_rect) selected = true;*/ + /*if(released() && !in_selection_rect) selected = false;*/ + } + }; } diff --git a/src/graph-manager.h b/src/graph-manager.h index 19962f0..e076c06 100644 --- a/src/graph-manager.h +++ b/src/graph-manager.h @@ -305,20 +305,6 @@ namespace VISEQ::GRAPH { 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 c87ec44..b5b7649 100644 --- a/src/interactable.h +++ b/src/interactable.h @@ -8,14 +8,11 @@ namespace VISEQ::BASE { Interactable() {} virtual ~Interactable() {} - bool in_selection_rect = false; - bool selected = false; - - bool copied = false; - bool highlighted = false; - bool erase = false; + bool is_hovering = false; virtual bool hovering() = 0; + virtual bool entered() {return false;}; + virtual bool exited() {return false;}; virtual bool clicked() { return hovering() && IsMouseButtonPressed(MOUSE_BUTTON_LEFT); diff --git a/src/main.cpp b/src/main.cpp index 21782dd..19982f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -490,6 +490,9 @@ int main(){ /* }*/ /*};*/ + canvas.update(); + app.update(); + canvas.draw(); app.draw(state->screen_mouse, canvas.camera); canvas.drawEnd(); diff --git a/src/midi-node.h b/src/midi-node.h index 9c0ca42..b814d63 100644 --- a/src/midi-node.h +++ b/src/midi-node.h @@ -136,7 +136,7 @@ namespace VISEQ::GRAPH::NODES { void draw(Vec2Df mouse, Camera2D cam) override { Node::draw(); - if(hovering()) interact(); + if(hovering() || selected) interact(); last = time; time = GetTime(); @@ -167,7 +167,8 @@ namespace VISEQ::GRAPH::NODES { break;} } 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(selected || picked_up || in_selection_rect || hovering()) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255}); + if(selected) DrawCircle(position.x, position.y, radius, (Color){255, 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/node.h b/src/node.h index c6f7297..15a869c 100644 --- a/src/node.h +++ b/src/node.h @@ -7,6 +7,7 @@ #include "datatypes.h" #include "draggable.h" #include "graph-item.h" +#include "state.h" #include "vmath.h" namespace VISEQ::GRAPH::EDGES{ @@ -56,13 +57,30 @@ namespace VISEQ::GRAPH::NODES { virtual void trigger() {}; virtual bool hovering() override { - return CheckCollisionPointCircle(state->screen_mouse, position, radius); + return state->istate != APP::InteractionState::DRAW_SELECTION && CheckCollisionPointCircle(state->screen_mouse, position, radius); + } + + virtual bool entered() override { + return !is_hovering && hovering(); + } + + virtual bool exited() override { + return is_hovering && !hovering(); } void update() override{ - if(hovering()) state->hovering = true; - if(pickedUp() || selected) drag(); - if(released()) putDown(); + if((held() && !picked_up) || (clicked() && !state->keys_down.shift)) select(); + if(entered()) state->istate = APP::InteractionState::HOVER_NODE; + if(exited()) state->istate = APP::InteractionState::HOVER_CANVAS; + if(pickedUp()){ + drag(); + state->istate = APP::InteractionState::DRAG_NODE; + } + if(released() && picked_up){ + putDown(); + state->istate = APP::InteractionState::HOVER_CANVAS; + } + int free_connectors = 0; for(auto c : connectors){ if(!c->partner) free_connectors++; @@ -70,6 +88,7 @@ namespace VISEQ::GRAPH::NODES { c->update(); } if(free_connectors == 0) addConnector(); + is_hovering = hovering(); } void draw(Vec2Df mp, Camera2D cam) override {} diff --git a/src/selectable.h b/src/selectable.h new file mode 100644 index 0000000..6f28cff --- /dev/null +++ b/src/selectable.h @@ -0,0 +1,23 @@ +#pragma once + +#include "interactable.h" + +namespace VISEQ::BASE { + class Selectable : public Interactable{ + public: + Selectable() {} + + bool in_selection_rect = false; + bool selected = false; + + bool copied = false; + bool highlighted = false; + bool erase = false; + + virtual bool clicked() override { + return (selected || hovering()) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT); + } + + virtual void select() = 0; + }; +} diff --git a/src/state.h b/src/state.h index cc84645..9eb1d2f 100644 --- a/src/state.h +++ b/src/state.h @@ -19,6 +19,8 @@ namespace VISEQ::APP{ 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}; + inline std::vector state_string = {"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"}; + struct MouseState{ bool down = false; bool clicked = false; @@ -44,6 +46,7 @@ namespace VISEQ::APP{ Vec2Df mod_mouse; InteractionState istate = HOVER_CANVAS; + InteractionState old_istate = HOVER_CANVAS; int node_mode = 0; @@ -62,6 +65,8 @@ namespace VISEQ::APP{ Vec2Df mouse_delta; void update(Camera2D camera){ + if(istate != old_istate) std::cout << state_string[istate] << std::endl; + mouse_delta = {GetMouseDelta().x, GetMouseDelta().y}; settings.speed = (settings.grid * 16.0f) * (settings.bpm / 120.f); @@ -97,6 +102,7 @@ namespace VISEQ::APP{ mod_mouse.x = round(mouse_pos.x / settings.grid) * settings.grid; mod_mouse.y = round(mouse_pos.y / settings.grid) * settings.grid; } + old_istate = istate; } inline static std::shared_ptr instance;