From f04838bffae473ae07379f1a65493480dfbec4cf Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 24 Nov 2024 03:08:06 +0100 Subject: [PATCH] Super simple events added. Seems to be a good way for handling interaction. Modified a few base classes. --- src/app-manager.h | 30 ++++++++++++++++++++++++ src/canvas.h | 7 +++++- src/connectable.h | 9 -------- src/connector.h | 18 ++++++++++++--- src/datatypes.h | 2 +- src/draggable.h | 40 +++++++------------------------- src/graph-item.h | 10 ++++---- src/interactable.h | 5 ++++ src/interaction-event.h | 16 +++++++++++++ src/midi-node.h | 6 ++--- src/mouse.h | 51 +++++++++++++++++++++++++++++++++++++---- src/node.h | 20 ++++++++++++---- src/state-io.h | 2 +- src/state.h | 11 +++++++-- 14 files changed, 160 insertions(+), 67 deletions(-) create mode 100644 src/interaction-event.h diff --git a/src/app-manager.h b/src/app-manager.h index 095a5e8..438ecf9 100644 --- a/src/app-manager.h +++ b/src/app-manager.h @@ -56,10 +56,40 @@ namespace VISEQ::APP { gm.removeNodesAndEdges(nodes); } + void doInteraction(){ + while(event_queue.size() > 0){ + auto e = event_queue.front(); + std::cout << e.action << " " << e.item->z_index << std::endl; + + if(e.item->getType() == GraphItemType::NODE || e.item->getType() == GraphItemType::CONNECTOR) { + switch(e.action){ + case VISEQ::APP::Interaction::PICKUP: + { + e.item->pickUp(); + break; + } + case VISEQ::APP::Interaction::DRAG: + { + e.item->drag(); + break; + } + case VISEQ::APP::Interaction::PUTDOWN: + { + e.item->putDown(); + break; + } + } + } + + event_queue.pop(); + } + } + void update(){ mutex.lock(); updateMidiPorts(); mutex.unlock(); + doInteraction(); mouse.update(); if(KEYS_DOWN.ctrl && IsKeyPressed(KEY_C)){ diff --git a/src/canvas.h b/src/canvas.h index f8a173c..8da40a8 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -1,6 +1,7 @@ #pragma once +#include "datatypes.h" #include "state.h" #include "draggable.h" #include "raylib.h" @@ -32,7 +33,11 @@ namespace VISEQ::APP::CANVAS { virtual void drawEnd(){ EndMode2D(); } - + + GRAPH::GraphItemType getType() override { + return GRAPH::GraphItemType::CANVAS; + } + void makeSelection(){ if(MOUSE_LEFT.clicked){ state->selection = (Rectangle){0,0,0,0}; diff --git a/src/connectable.h b/src/connectable.h index fb232b9..f8f3ebb 100644 --- a/src/connectable.h +++ b/src/connectable.h @@ -23,15 +23,6 @@ namespace VISEQ::BASE { DrawLineV(position, MOD_MOUSE, (Color){229, 181, 103, 255}); } - void update() override{ - if(STATE != IState::DRAG_NODE){ - Draggable::update(); - if(pickedUp()) drag(); - if(released()) putDown(); - // is_hovering = hovering(); - } - } - void putDown() override { connect(); Draggable::putDown(); diff --git a/src/connector.h b/src/connector.h index 47dd8be..de4a056 100644 --- a/src/connector.h +++ b/src/connector.h @@ -1,7 +1,9 @@ #pragma once #include "connectable.h" +#include "datatypes.h" #include "graph-item.h" +#include "moveable.h" #include "raymath.h" #include "state.h" #include "vmath.h" @@ -9,13 +11,17 @@ namespace VISEQ::GRAPH { class Connector : public BASE::Connectable, public GraphItem{ public: - using GraphItem::state; + using BASE::Movable::state; Connector() {} Connector(std::shared_ptr parent, Vec2Df center_position, float orbit) : orbit(orbit) { setPosition(center_position); setParent(parent); } + + GraphItemType getType() override{ + return GraphItemType::CONNECTOR; + } std::shared_ptr parent; @@ -24,9 +30,13 @@ namespace VISEQ::GRAPH { float radius = 5.0f; float orbit = 14.0f; Vec2Df center_position; + + std::shared_ptr getPtr(){ + return std::static_pointer_cast(shared_from_this()); + } virtual bool hovering() override { - return STATE != IState::DRAW_SELECTION && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); + return CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); } void setParent(std::shared_ptr _parent){ @@ -40,7 +50,9 @@ namespace VISEQ::GRAPH { } void update() override { - BASE::Connectable::update(); + if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG}); + if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN}); } void draw() override { diff --git a/src/datatypes.h b/src/datatypes.h index a3fef9c..518239a 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -33,7 +33,7 @@ namespace VISEQ::GRAPH::NODES { namespace VISEQ::GRAPH{ - enum GraphItemType {NODE, EDGE}; + enum GraphItemType {NODE, EDGE, CONNECTOR, CANVAS}; enum NodeType {OSCNODE, MIDINODE, CONFIGNODE}; enum EdgeType {MIDIEDGE, CONFIGEDGE}; } diff --git a/src/draggable.h b/src/draggable.h index 794bb63..c2436ab 100644 --- a/src/draggable.h +++ b/src/draggable.h @@ -14,6 +14,8 @@ namespace VISEQ::BASE { Draggable(Vec2Df p) : Movable(p, 960.0f) {} virtual ~Draggable() {} + std::shared_ptr state = APP::State::get(); + Vec2Df drag_offset; bool picked_up = false; @@ -27,14 +29,15 @@ namespace VISEQ::BASE { } virtual bool pickedUp() { - if(clicked() && held() && (STATE == IState::HOVER_NODE || STATE == IState::DRAG_NODE)) { + return held() && picked_up; + } + + virtual void pickUp() override { picked_up = true; drag_offset = position - SCREEN_MOUSE; - } - return picked_up; } - virtual void drag() { + virtual void drag() override { if(KEYS_PRESSED.ctrl){ selection_offset = position - state->hover_position; } @@ -45,7 +48,7 @@ namespace VISEQ::BASE { } } - virtual void putDown(){ + virtual void putDown() override { picked_up = false; } @@ -54,32 +57,5 @@ namespace VISEQ::BASE { if(MOUSE_LEFT.released) selected = (KEYS_DOWN.shift && selected) || in_selection_rect; } - virtual void update() override { - if(STATE != IState::HOVER_NODE) select(); - if((pickedUp() || hovering()) && z_hovering == -1) z_hovering = z_index; - - if(z_index == z_hovering || selected){ - if(pickedUp()){ - drag(); - STATE = IState::DRAG_NODE; - } - } - if(STATE != IState::DRAG_NODE){ - if(entered()){ - STATE = IState::HOVER_NODE; - std::cout << "z_index=" << z_index << " z_hovering=" << z_hovering << std::endl; - is_hovering = true; - } - if(exited()){ - STATE = IState::HOVER_CANVAS; - is_hovering = false; - } - } - if(released() && picked_up){ - putDown(); - STATE = IState::HOVER_CANVAS; - if(hovering()) STATE = IState::HOVER_NODE; - } - } }; } diff --git a/src/graph-item.h b/src/graph-item.h index 3d6d979..affe564 100644 --- a/src/graph-item.h +++ b/src/graph-item.h @@ -1,8 +1,8 @@ #pragma once -#include "state.h" #include "raylib.h" #include "datatypes.h" +#include "vmath.h" #include namespace VISEQ::GRAPH { @@ -12,11 +12,11 @@ namespace VISEQ::GRAPH { GraphItem() {newId(-1);} GraphItem(const GraphItem& G) { newId(-1); - graphItemType = G.graphItemType; + gItemType = G.gItemType; } - GraphItemType graphItemType; - std::shared_ptr state = APP::State::get(); + GraphItemType gItemType; + int id = 0; @@ -33,7 +33,7 @@ namespace VISEQ::GRAPH { virtual void draw() {}; virtual void draw(Vec2Df mouse, Camera2D cam) {}; - virtual GraphItemType getType() {return graphItemType;} + virtual GraphItemType getType() {return gItemType;} virtual ~GraphItem() = default; }; diff --git a/src/interactable.h b/src/interactable.h index e25fc55..f761d64 100644 --- a/src/interactable.h +++ b/src/interactable.h @@ -1,5 +1,6 @@ #pragma once +#include "datatypes.h" #include "raylib.h" namespace VISEQ::BASE { @@ -33,6 +34,10 @@ namespace VISEQ::BASE { virtual bool released() { return IsMouseButtonReleased(MOUSE_BUTTON_LEFT); } + virtual GRAPH::GraphItemType getType() = 0; + virtual void pickUp() = 0; + virtual void drag() = 0; + virtual void putDown() = 0; }; } diff --git a/src/interaction-event.h b/src/interaction-event.h new file mode 100644 index 0000000..fb9327b --- /dev/null +++ b/src/interaction-event.h @@ -0,0 +1,16 @@ +#pragma once + +#include "interactable.h" +#include +#include +namespace VISEQ::APP{ + + enum Interaction {HOVER, CLICK, HOLD, RELEASE, PICKUP, DRAG, PUTDOWN}; + + struct InteractionEvent{ + std::shared_ptr item; + Interaction action; + }; + + inline static std::queue event_queue; +} diff --git a/src/midi-node.h b/src/midi-node.h index 13b2539..0ed0535 100644 --- a/src/midi-node.h +++ b/src/midi-node.h @@ -1,7 +1,6 @@ #pragma once #include "datatypes.h" -#include "graph-item.h" #include "node.h" #include "raymath.h" #include @@ -13,7 +12,6 @@ namespace VISEQ::GRAPH::NODES { class MidiNode : public Node{ public: - using GraphItem::state; struct NodeMidiOut{ int i; @@ -89,7 +87,7 @@ namespace VISEQ::GRAPH::NODES { float wheel = GetMouseWheelMove(); if(KEYS_DOWN.ctrl && !KEYS_DOWN.alt){ - switch(GraphItem::state->node_mode){ + switch(state->node_mode){ case 0:{ midi_note += wheel; break;} @@ -114,7 +112,7 @@ namespace VISEQ::GRAPH::NODES { if(midi_velocity < 0 ) midi_velocity = 127; if(midi_velocity > 127 ) midi_velocity = 0; } else if(KEYS_DOWN.alt) { - switch(GraphItem::state->node_mode){ + switch(state->node_mode){ case 0:{ float incr = (float)wheel * (KEYS_DOWN.shift ? 100.0f : KEYS_DOWN.ctrl ? 1000.0f : 10.0f); midi_gate += incr; diff --git a/src/mouse.h b/src/mouse.h index 9985e70..3ff0fc8 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -2,6 +2,7 @@ #include "draggable.h" #include "graph-manager.h" +#include "interaction-event.h" #include namespace VISEQ::APP { class Mouse { @@ -12,11 +13,53 @@ namespace VISEQ::APP { GraphManager *gm; void update(){ - auto hovering_nodes = gm->nodes | RANGE_FILTER([](SPTR_Node n) { return n->is_hovering;}) | std::ranges::to>>(); + auto hovering_nodes = gm->nodes | RANGE_FILTER([](SPTR_Node n) { return n->hovering() || n->picked_up;}) | std::ranges::to>>(); + + /*if(!hovering_nodes.empty()){*/ + /* hovering_nodes.front()->is_hovering = true;*/ + /**/ + /* if(hovering_nodes.front()->pickedUp()) hovering_nodes.front()->drag();*/ + /* if(hovering_nodes.front()->released()) hovering_nodes.front()->putDown();*/ + /**/ + /*}*/ - if(!hovering_nodes.empty()){ - //hovering_nodes.front()->is_hovering = true; - } } + + void interact(InteractionEvent e){ + + } + + /*virtual void select() override {*/ + /* if(STATE == IState::DRAW_SELECTION) in_selection_rect = CheckCollisionPointRec(position, state->selection);*/ + /* if(MOUSE_LEFT.released) selected = (KEYS_DOWN.shift && selected) || in_selection_rect;*/ + /*}*/ + /**/ + /*virtual void update() override {*/ + /* if(STATE != IState::HOVER_NODE) select();*/ + /* if((pickedUp() || hovering()) && z_hovering == -1) z_hovering = z_index;*/ + /**/ + /* if(z_index == z_hovering || selected){*/ + /* if(pickedUp()){*/ + /* drag();*/ + /* STATE = IState::DRAG_NODE;*/ + /* }*/ + /* }*/ + /* if(STATE != IState::DRAG_NODE){*/ + /* if(entered()){*/ + /* STATE = IState::HOVER_NODE;*/ + /* std::cout << "z_index=" << z_index << " z_hovering=" << z_hovering << std::endl;*/ + /* is_hovering = true;*/ + /* }*/ + /* if(exited()){*/ + /* STATE = IState::HOVER_CANVAS;*/ + /* is_hovering = false;*/ + /* }*/ + /* }*/ + /* if(released() && picked_up){*/ + /* putDown();*/ + /* STATE = IState::HOVER_CANVAS;*/ + /* if(hovering()) STATE = IState::HOVER_NODE;*/ + /* }*/ + /*}*/ }; } diff --git a/src/node.h b/src/node.h index 008d782..8068c48 100644 --- a/src/node.h +++ b/src/node.h @@ -8,6 +8,7 @@ #include "datatypes.h" #include "draggable.h" #include "graph-item.h" +#include "interaction-event.h" #include "state.h" #include "vmath.h" @@ -17,10 +18,9 @@ namespace VISEQ::GRAPH::EDGES{ namespace VISEQ::GRAPH::NODES { - class Node : public BASE::Draggable, public GraphItem{ + class Node : public BASE::Draggable, public GraphItem { public: - using GraphItem::state; Node() {} Node(float x, float y) : Draggable(Vec2Df(x, y)) {} @@ -41,7 +41,7 @@ namespace VISEQ::GRAPH::NODES { bool config = false; virtual bool hovering() override { - return STATE != IState::DRAW_SELECTION && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); + return CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); } void addConnector() { @@ -59,8 +59,19 @@ namespace VISEQ::GRAPH::NODES { virtual void trigger() {}; + GraphItemType getType() override{ + return GraphItemType::NODE; + } + + std::shared_ptr getPtr(){ + return std::static_pointer_cast(shared_from_this()); + } + void update() override{ - BASE::Draggable::update(); + + if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG}); + if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN}); int free_connectors = 0; for(auto c : connectors){ @@ -69,7 +80,6 @@ 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/state-io.h b/src/state-io.h index 1f61366..e009102 100644 --- a/src/state-io.h +++ b/src/state-io.h @@ -136,7 +136,7 @@ namespace VISEQ::GRAPH::NODES { namespace VISEQ::GRAPH { inline void to_json(json& j, const GraphItem& G){ std::cout << "Movable" << std::endl; - j = json{{"id", G.id}, {"type", G.graphItemType}}; + j = json{{"id", G.id}, {"type", G.gItemType}}; } inline void to_json(json& j, const SPTR_GraphItem& G){ diff --git a/src/state.h b/src/state.h index af2e4d8..38c3065 100644 --- a/src/state.h +++ b/src/state.h @@ -1,8 +1,10 @@ #pragma once +#include "interaction-event.h" #include "raylib.h" #include "vmath.h" #include +#include #define STATE state->istate #define SETTINGS state->settings @@ -30,7 +32,7 @@ namespace VISEQ::APP{ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(AppSettings, width, height, grid, bpm, fps, speed, gui_selected_midi_out) 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{ @@ -59,7 +61,7 @@ namespace VISEQ::APP{ InteractionState istate = HOVER_CANVAS; InteractionState old_istate = HOVER_CANVAS; - + int node_mode = 0; bool hovering = false; @@ -77,8 +79,13 @@ namespace VISEQ::APP{ Vec2Df mouse_delta; Vec2Df hover_position; + + void pushEvent(InteractionEvent e){ + event_queue.push(e); + } void update(Camera2D camera){ + if(istate != old_istate) std::cout << state_string[istate] << std::endl; mouse_delta = {GetMouseDelta().x, GetMouseDelta().y};