From 9e284be10968bacacda206464578dc55652a1a80 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 19 Jul 2026 02:39:19 +0200 Subject: [PATCH] wip rework of interaction event system - broken right now --- src/canvas.cpp | 8 ++-- src/connector.cpp | 2 +- src/draggable.cpp | 32 ++++++++++++---- src/draggable.h | 4 ++ src/graph-manager.cpp | 5 ++- src/interaction-manager.cpp | 74 +++++++++++++++++++++++++++---------- src/interaction-manager.h | 2 +- src/node.cpp | 10 ++++- 8 files changed, 101 insertions(+), 36 deletions(-) diff --git a/src/canvas.cpp b/src/canvas.cpp index 635e3ef..05ba1f9 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -2,6 +2,7 @@ #include "datatypes.h" //#include "interaction-event.h" +#include "interaction-event.h" #include "state.h" #include "draggable.h" #include "raylib.h" @@ -21,14 +22,14 @@ namespace VISEQ::APP::CANVAS { } void Canvas::pickUp() { - //std::cout << "canvas pickUp" << std::endl; + std::cout << "canvas pickUp" << std::endl; BASE::Draggable::pickUp(); select_start = SCREEN_MOUSE; state->pushEvent({getPtr(), Interaction::DESELECT}); } void Canvas::putDown() { - //std::cout << "canvas putDown" << std::endl; + std::cout << "canvas putDown" << std::endl; BASE::Draggable::putDown(); state->pushEvent({getPtr(), Interaction::SELECT}); } @@ -59,8 +60,9 @@ namespace VISEQ::APP::CANVAS { if(state->mouse_right.down) { camera.target = Vector2Add(camera.target, camera_delta); } + if(clicked()) state->pushEvent({getPtr(), APP::Interaction::DESELECT}); - if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG}); if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN}); diff --git a/src/connector.cpp b/src/connector.cpp index 9b69584..d7acf5e 100644 --- a/src/connector.cpp +++ b/src/connector.cpp @@ -38,7 +38,7 @@ namespace VISEQ::GRAPH { void Connector::update() { if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER}); - if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG}); if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN}); if(connected) { diff --git a/src/draggable.cpp b/src/draggable.cpp index 2e12ef3..fe1d2c0 100644 --- a/src/draggable.cpp +++ b/src/draggable.cpp @@ -9,33 +9,49 @@ namespace VISEQ::BASE { return is_hovering && !hovering(); } - bool Draggable::pickedUp() { + bool Draggable::clicked() { + if(hovering() && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){ + last_tp = std::chrono::high_resolution_clock::now(); + } + std::chrono::duration diff = std::chrono::high_resolution_clock::now() - last_tp; + if(released() && diff.count() < 100000){ + std::cout << "draggable clicked" << std::endl; + return true; + } + return false; + } + + bool Draggable::pickedUp() { return held() && picked_up; } - void Draggable::pickUp() { - picked_up = true; + void Draggable::pickUp() { + std::chrono::duration diff = std::chrono::high_resolution_clock::now() - last_tp; + if(held() && diff.count() > 100000){ + std::cout << "draggable pickedUp" << std::endl; + picked_up = true; + } drag_offset = position - SCREEN_MOUSE; } - void Draggable::pickUp(Vec2Df selection_origin) { + void Draggable::pickUp(Vec2Df selection_origin) { picked_up = true; drag_offset = position - selection_origin; } - void Draggable::drag(Vec2Df new_position) { + void Draggable::drag(Vec2Df new_position) { position = new_position; } - void Draggable::putDown() { + void Draggable::putDown() { picked_up = false; } - bool Draggable::select() { + bool Draggable::select() { return CheckCollisionPointRec(position, state->selection); } - void Draggable::deselect() { + void Draggable::deselect() { selected = false; } } diff --git a/src/draggable.h b/src/draggable.h index 22239df..40721e8 100644 --- a/src/draggable.h +++ b/src/draggable.h @@ -4,6 +4,7 @@ #include "selectable.h" #include "state.h" #include "vmath.h" +#include namespace VISEQ::BASE { class Draggable : public Movable, public Selectable{ @@ -19,8 +20,11 @@ namespace VISEQ::BASE { bool picked_up = false; + std::chrono::time_point last_tp; + virtual bool entered() override; virtual bool exited() override; + virtual bool clicked() override; virtual bool pickedUp(); virtual void pickUp() override; virtual void pickUp(Vec2Df selection_origin) override; diff --git a/src/graph-manager.cpp b/src/graph-manager.cpp index 311be3e..a856826 100644 --- a/src/graph-manager.cpp +++ b/src/graph-manager.cpp @@ -90,6 +90,7 @@ namespace VISEQ::GRAPH{ 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(), [](WPTR_Node n){n.lock()->selected = true;}); + std::cout << "selected " << selected_nodes.size() << " nodes" << std::endl; } void GraphManager::deselect(){ @@ -382,8 +383,8 @@ namespace VISEQ::GRAPH{ // Dynamic opacity by distance to mouse unsigned char opacity = 150.0f - Clamp(center_handle.dist(mouse_pos), 0.0f, 130.0f); - unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 220.0f); - unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.0f); + //unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 220.0f); + //unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.0f); float opacity_normalized = Clamp((float)opacity / 255.0f, .0f, 1.0f); //float opacity_from_normalized = Clamp((float)opacity_from / 255.0f, .0f, 1.0f); diff --git a/src/interaction-manager.cpp b/src/interaction-manager.cpp index 2f0ac8f..237e059 100644 --- a/src/interaction-manager.cpp +++ b/src/interaction-manager.cpp @@ -2,11 +2,14 @@ #include "connector.h" #include "datatypes.h" +#include "interaction-event.h" #include "node.h" #include "raylib.h" #include "state.h" #include #include +#include +#include namespace VISEQ::INTERACTION{ @@ -33,7 +36,7 @@ namespace VISEQ::INTERACTION{ gm->cycleModeOfSelectedNodes(false); } - if(IsKeyPressed(KEY_V)){ + if(!KEYS_DOWN.ctrl && IsKeyPressed(KEY_V)){ state->draw_edge_lengths = !state->draw_edge_lengths; } } @@ -41,7 +44,7 @@ namespace VISEQ::INTERACTION{ void InteractionManager::draw(){ doInteraction(); scaleSelection(); - if(!gm->getSelection().empty()){ + if(gm->getSelection().size() > 1){ DrawRectangleRoundedLines(state->bounding_box, 0.1f, 3, VS_COLOR_LIGHTGREY); scale_handle->draw(); } @@ -133,16 +136,37 @@ namespace VISEQ::INTERACTION{ bool exit = false; bool once = false; bool connect_once = false; + bool blocking = false; + + //std::cout << state->mouse_z << std::endl; state->mouse_z = canvas->z_index; - for(auto e : state->event_queue){ + //auto sorted_queue = state->event_queue + + auto nodes_queue = state->event_queue | RANGE_FILTER([](APP::InteractionEvent e) { return e.item->getType() == GraphItemType::NODE; }) | std::ranges::to>(); + auto connector_queue = state->event_queue | RANGE_FILTER([](APP::InteractionEvent e) { return e.item->getType() == GraphItemType::CONNECTOR; }) | std::ranges::to>(); + auto canvas_queue = state->event_queue | RANGE_FILTER([](APP::InteractionEvent e) { return e.item->getType() == GraphItemType::CANVAS; }) | std::ranges::to>(); + + std::sort(nodes_queue.begin(), nodes_queue.end(), [](APP::InteractionEvent a, APP::InteractionEvent b){return a.item->z_index > b.item->z_index;}); + + std::deque state_queue; + state_queue.append_range(nodes_queue); + state_queue.append_range(connector_queue); + state_queue.append_range(canvas_queue); + + state->event_queue.clear(); + + std::cout << state_queue.size() << std::endl; + + for(auto e : state_queue){ if(!connect_once && e.action == APP::Interaction::CONNECT){ + blocking = true; APP::InteractionEvent partner; bool found = false; for(auto ei : state->event_queue){ if(ei.action == APP::Interaction::HOVER && ei.item->getType() == GraphItemType::CONNECTOR) { - std::cout << "YEAH" << std::endl; + //std::cout << "YEAH" << std::endl; partner = ei; found = true; break; @@ -166,12 +190,16 @@ namespace VISEQ::INTERACTION{ connect_once = true; break; } + if(e.item->getType() == GraphItemType::NODE){ + if(e.action == APP::Interaction::DRAG) blocking = true; + } } - while(state->event_queue.size() > 0 && !exit){ - auto e = state->event_queue.front(); + while(state_queue.size() > 0 && !exit){ + auto e = state_queue.front(); if(e.action == APP::Interaction::CLICK){ gm->addToSelection(); + std::cout << "click" << std::endl; } if(e.action == APP::Interaction::RIGHTCLICK){ gm->addToSelection(); @@ -183,19 +211,10 @@ namespace VISEQ::INTERACTION{ state->mouse_z = e.item->z_index; } - if(e.item->getType() == GraphItemType::CANVAS) { - if(e.action == APP::Interaction::SELECT) { - gm->select(); - canvas->clearSelectionRect(); - } - if(e.action == APP::Interaction::DESELECT) { - gm->deselect(); - } - } - if(!once && e.item->getType() == GraphItemType::NODE){ auto node = std::dynamic_pointer_cast(e.item); - if(e.action == APP::Interaction::PICKUP) { + if(!blocking && e.action == APP::Interaction::PICKUP) { + std::cout << "node pickup" << std::endl; node->pickUp(); if(node->selected){ for(auto s : gm->getSelection()){ @@ -205,6 +224,8 @@ namespace VISEQ::INTERACTION{ once = true; } if(e.action == APP::Interaction::DRAG) { + blocking = true; + std::cout << "node drag" << std::endl; if(KEYS_DOWN.ctrl) node->drag(MOD_MOUSE); else if(KEYS_DOWN.shift) { snapPolar(node); @@ -216,9 +237,9 @@ namespace VISEQ::INTERACTION{ s->drag(MOD_MOUSE + s->drag_offset); } } - once = true; } if(e.action == APP::Interaction::PUTDOWN) { + std::cout << "node putdown" << std::endl; node->putDown(); if(node->selected){ for(auto s : gm->getSelection()){ @@ -227,6 +248,19 @@ namespace VISEQ::INTERACTION{ } } } + + if(!blocking && !once && e.item->getType() == GraphItemType::CANVAS) { + if(e.action == APP::Interaction::SELECT) { + std::cout << "canvas select" << std::endl; + gm->select(); + canvas->clearSelectionRect(); + } + if(e.action == APP::Interaction::DESELECT) { + std::cout << "canvas deselect" << std::endl; + gm->deselect(); + } + } + if(exit) break; if(!once && (e.item->getType() == GraphItemType::CONNECTOR || e.item->getType() == GraphItemType::CANVAS || e.item->getType() == GraphItemType::HANDLE)) { @@ -253,8 +287,8 @@ namespace VISEQ::INTERACTION{ } } - state->event_queue.pop_front(); + state_queue.pop_front(); } - state->event_queue.clear(); + state_queue.clear(); } } diff --git a/src/interaction-manager.h b/src/interaction-manager.h index d09735e..8b062fb 100644 --- a/src/interaction-manager.h +++ b/src/interaction-manager.h @@ -34,7 +34,7 @@ namespace VISEQ::INTERACTION{ virtual void update() override { if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER}); - if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG}); if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN}); } diff --git a/src/node.cpp b/src/node.cpp index 2cb4f46..39604a9 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -5,6 +5,7 @@ #include "connector.h" #include "datatypes.h" +#include "interaction-event.h" #include "state.h" #include "vmath.h" @@ -47,9 +48,16 @@ namespace VISEQ::GRAPH::NODES { void Node::update() { if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER}); - if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + + if(clicked()) { + selected = true; + state->pushEvent({getPtr(), APP::Interaction::CLICK}); + } + if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP}); + if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG}); if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN}); + if(hovering() && MOUSE_RIGHT.clicked) { selected = true; config = true;