From e519b7c758eaf4ca5956b1e82af505a10d620c2f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 6 Nov 2024 15:35:25 +0100 Subject: [PATCH] scale groups of nodes is so cool! --- src/graph-manager.h | 16 +++++++++++++- src/main.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/graph-manager.h b/src/graph-manager.h index 22f926f..e52b10f 100644 --- a/src/graph-manager.h +++ b/src/graph-manager.h @@ -201,7 +201,21 @@ namespace VISEQ::GRAPH { Color col = {229, 181, 103, 255}; if(c->GActive()) col = {108, 153, 187, 255}; DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col); - + { + float d = c->start->position.dist(c->end->position); + std::string frac = MIDI::Fractions.at(std::clamp(round(d/60) - 1, 0, 31)); + Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f); + Vector2 text_length_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f); + + Vec2Df middle_handle = c->start->position + (c->end->position - c->start->position) * ((d - text_length.x)*0.5f)/d; + Vec2Df middle_handle_frac = c->start->position + (c->end->position - c->start->position) * ((d - text_length_frac.x)*0.5f)/d; + Vec2Df text_position = middle_handle + (c->start->position - c->end->position).norm().orth() * 12.0f; + Vec2Df text_position_frac = middle_handle_frac - (c->start->position - c->end->position).norm().orth() * 4.0f; + + float rotation = Vector2Angle((Vector2){1,0}, (c->end->position - c->start->position)) * RAD2DEG; + DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); + if( (int)d % 60 == 0) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); + } if(midi_gate_v1 == 4.0f) col = VS_COLOR_RED; DrawCircle(v1_position.x, v1_position.y, midi_gate_v1, col); diff --git a/src/main.cpp b/src/main.cpp index f6edcf0..b7eea0d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -154,12 +154,15 @@ int main(){ app.sm.startSignalThread(); - enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES}; + enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, SCALE_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES}; InteractionState istate = HOVER_CANVAS; Vec2Df select_start; Rectangle selection; + Vec2Df scale_start; + Vec2Df scale_rectangle; + VEC_SPTR_Node copied_nodes; @@ -198,7 +201,7 @@ int main(){ } if(!mouse_down && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::HOVER_CANVAS; - if((mouse_clicked || mouse_down || mouse_released) && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty()) istate = InteractionState::DRAW_SELECTION; + if((mouse_clicked || mouse_down || mouse_released) && !mouse_right_down && dragging_nodes.empty() && connecting_nodes.empty() && hovering_nodes.empty() && hovering_connectors.empty() && istate != InteractionState::SCALE_SELECTION) istate = InteractionState::DRAW_SELECTION; if(!hovering_nodes.empty() && !mouse_down && !mouse_right_down) istate = InteractionState::HOVER_NODE; if(!dragging_nodes.empty()) istate = InteractionState::DRAG_NODE; @@ -215,7 +218,54 @@ int main(){ app.gm.setNodeMode(app.settings.mode); } + if(!selected_nodes.empty()){ + float offset = 30; + Vec2Df corner_tl = {50000, 50000}; + Vec2Df corner_br = {-50000, -50000}; + std::shared_ptr node_tl; + std::shared_ptr node_br; + + for(auto n : selected_nodes){ + float x = n->position.x; + float y = n->position.y; + + if(x < corner_tl.x && y < corner_tl.y) node_tl = n; + if(x > corner_br.x && y > corner_br.y) node_br = n; + + if(x < corner_tl.x) corner_tl.x = x; + if(x > corner_br.x) corner_br.x = x; + if(y < corner_tl.y) corner_tl.y = y; + if(y > corner_br.y) corner_br.y = y; + } + corner_tl -= Vec2Df(offset, offset); + corner_br += Vec2Df(offset, offset); + + DrawRectangleLines(corner_tl.x, corner_tl.y, (corner_br.x - corner_tl.x), (corner_br.y - corner_tl.y), VS_COLOR_LIGHTGREY); + DrawCircleV(corner_br, 5, YELLOW); + + if(istate == InteractionState::SCALE_SELECTION && mouse_released){ + istate = InteractionState::HOVER_CANVAS; + } + if(mouse_clicked && corner_br.dist(mouse_pos) < 10){ + scale_start = (corner_br - corner_tl); + for(auto n : selected_nodes){ + n->drag_offset = n->position - node_tl->position; + } + istate = InteractionState::SCALE_SELECTION; + } + if(istate == InteractionState::SCALE_SELECTION && mouse_down){ + Vec2Df scale = (mouse_pos - corner_tl) / scale_start; + if(IsKeyDown(KEY_LEFT_SHIFT)) scale.y = scale.x; + DrawText(std::format("{:.2f} {:.2f}", scale.x, scale.y).c_str(), corner_br.x+5, corner_br.y+5, 10, RED); + for(auto n : selected_nodes){ + n->position = node_tl->position + (n->drag_offset * scale); + } + istate = InteractionState::SCALE_SELECTION; + } + } + switch(istate){ + case InteractionState::SCALE_SELECTION: case InteractionState::HOVER_CANVAS: { for(auto &n : app.gm.nodes){