diff --git a/CMakeLists.txt b/CMakeLists.txt index 8aead71..280229f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(graphs VERSION 0.1.5) +project(graphs VERSION 0.1.6) option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF) option(ENABLE_UBSAN "Enable the ub sanitizer" OFF) diff --git a/include/config.h b/include/config.h index f9b56de..486fb31 100644 --- a/include/config.h +++ b/include/config.h @@ -41,6 +41,7 @@ namespace conf } class graph_t; +class selector_t; struct loader_t; #endif //GRAPHS_CONFIG_H diff --git a/include/graph.h b/include/graph.h index 8557715..c553680 100644 --- a/include/graph.h +++ b/include/graph.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,14 +29,6 @@ namespace im = ImGui; -enum class anim_state_t -{ - NONE, - HIGHLIGHT_NODE, - SELECT_NODE, - HIGHLIGHT_TO_SELECT -}; - struct bounding_box { int min_x = 0; @@ -53,6 +46,7 @@ struct bounding_box class graph_t { friend struct loader_t; + friend class selector_t; private: std::vector nodes; blt::hashmap_t names_to_node; @@ -66,14 +60,7 @@ class graph_t int current_iterations = 0; int max_iterations = 5000; std::unique_ptr equation; - - blt::i64 last_selected_node = -1; - blt::i64 last_selected_node2 = -1; - bool is_edge = false; - - blt::quad_easing easing; - blt::quint_easing highlight_easing; - + void create_random_graph(bounding_box bb, blt::size_t min_nodes, blt::size_t max_nodes, blt::f64 connectivity, blt::f64 scaling_connectivity, blt::f64 distance_factor); @@ -130,17 +117,6 @@ class graph_t void render(); - void reset_mouse_drag(); - - void reset_mouse_highlight() - { - highlight_easing.reset(); - } - - void process_mouse_drag(blt::i32 width, blt::i32 height); - - void handle_mouse(); - void use_Eades() { equation = std::make_unique(); @@ -212,6 +188,7 @@ class engine_t friend struct loader_t; private: graph_t graph; + selector_t selector; void draw_gui(const blt::gfx::window_data& data); @@ -228,11 +205,10 @@ class engine_t auto& io = ImGui::GetIO(); if (!io.WantCaptureMouse) - { - graph.process_mouse_drag(data.width, data.height); - } + selector.process_mouse(graph, data.width, data.height); graph.render(); + selector.render(graph, data.width, data.height); } }; diff --git a/include/selection.h b/include/selection.h new file mode 100644 index 0000000..c89cf01 --- /dev/null +++ b/include/selection.h @@ -0,0 +1,46 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef GRAPHS_SELECTION_H +#define GRAPHS_SELECTION_H + +#include + +class selector_t +{ + public: + // called inside the info panel block, used for adding more information + void draw_gui(graph_t& graph, blt::i32 width, blt::i32 height); + + // called once per frame, for rendering animations + void render(graph_t& graph, blt::i32 width, blt::i32 height); + + // called once per frame assuming imgui doesn't want the mouse + void process_mouse(graph_t& graph, blt::i32 width, blt::i32 height); + private: + void set_primary_selection(blt::i64 n); + void set_drag_selection(blt::i64 n); + void set_secondary_selection(blt::i64 n); + private: + blt::i64 drag_selection = -1; + blt::i64 primary_selection = -1; + blt::i64 secondary_selection = -1; + bool edge = false; +}; + +#endif //GRAPHS_SELECTION_H diff --git a/src/graph.cpp b/src/graph.cpp index 77788e9..c7b63cb 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -83,59 +83,6 @@ void graph_t::render() } } -// called every frame as long as imgui doesn't require the mouse. -void graph_t::process_mouse_drag(const blt::i32 width, const blt::i32 height) -{ - const auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(width, height, global_matrices.getScale2D(), global_matrices.getView2D(), - global_matrices.getOrtho())); - - bool mouse_pressed = blt::gfx::isMousePressed(0); - blt::i64 new_selection = -1; - - for (const auto& [index, node] : blt::enumerate(nodes)) - { - const auto pos = node.getPosition(); - const auto dist = pos - mouse_pos; - - const auto mag = dist.magnitude(); - - if (mag < node.getRenderObj().scale && mouse_pressed) - { - new_selection = static_cast(index); - break; - } - } - - if (new_selection != last_selected_node) - { - if (last_selected_node != -1) - nodes[last_selected_node].outline_color = conf::POINT_OUTLINE_COLOR; - } - - if (mouse_pressed && new_selection == -1 && last_selected_node != -1) - { - last_selected_node = -1; - } - - last_selected_node = new_selection; - - if (!mouse_pressed && blt::gfx::mouseReleaseLastFrame()) - { - reset_mouse_drag(); - } - - if (last_selected_node != -1 && mouse_pressed) - { - auto& node = nodes[last_selected_node]; - easing.progress(8 * static_cast(blt::gfx::getFrameDeltaSeconds())); - node.outline_color = conf::POINT_SELECT_COLOR; - node.getPositionRef() = mouse_pos; - } -} - -void graph_t::handle_mouse() -{} - void graph_t::create_random_graph(bounding_box bb, const blt::size_t min_nodes, const blt::size_t max_nodes, const blt::f64 connectivity, const blt::f64 scaling_connectivity, const blt::f64 distance_factor) { @@ -221,16 +168,6 @@ void graph_t::create_random_graph(bounding_box bb, const blt::size_t min_nodes, } } -void graph_t::reset_mouse_drag() -{ - if (last_selected_node != -1) - { - nodes[last_selected_node].outline_color = conf::POINT_OUTLINE_COLOR; - easing.reset(); - } - last_selected_node = -1; -} - void engine_t::draw_gui(const blt::gfx::window_data& data) { double ft = blt::gfx::getFrameDeltaSeconds(); @@ -332,11 +269,7 @@ void engine_t::draw_gui(const blt::gfx::window_data& data) } } } - im::SetNextItemOpen(true, ImGuiCond_Once); - if (im::CollapsingHeader("Node Information")) - { - - } + selector.draw_gui(graph, data.width, data.height); im::End(); } } diff --git a/src/selector.cpp b/src/selector.cpp new file mode 100644 index 0000000..b3d6af1 --- /dev/null +++ b/src/selector.cpp @@ -0,0 +1,88 @@ +/* + * + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include +#include + +extern blt::gfx::batch_renderer_2d renderer_2d; +extern blt::gfx::matrix_state_manager global_matrices; + +void selector_t::render(graph_t& graph, blt::i32 width, blt::i32 height) +{ + +} + +void selector_t::process_mouse(graph_t& graph, blt::i32 width, blt::i32 height) +{ + const auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(width, height, global_matrices.getScale2D(), global_matrices.getView2D(), + global_matrices.getOrtho())); + + bool mouse_pressed = blt::gfx::isMousePressed(0) && blt::gfx::mousePressedLastFrame(); + + for (const auto& [index, node] : blt::enumerate(graph.nodes)) + { + const auto pos = node.getPosition(); + const auto dist = pos - mouse_pos; + const auto mag = dist.magnitude(); + + if (mag < node.getRenderObj().scale && mouse_pressed) + { + set_drag_selection(static_cast(index)); + if (primary_selection == drag_selection || secondary_selection == drag_selection) + { + edge = false; + break; + } + if (blt::gfx::isKeyPressed(GLFW_KEY_LEFT_SHIFT)) + set_secondary_selection(drag_selection); + else + set_primary_selection(drag_selection); + break; + } + } + if (blt::gfx::mouseReleaseLastFrame()) + set_drag_selection(-1); + if (drag_selection >= 0 && drag_selection < static_cast(graph.nodes.size()) && blt::gfx::isMousePressed(0)) + { + graph.nodes[drag_selection].getPositionRef() = mouse_pos; + } +} + +void selector_t::draw_gui(graph_t& graph, blt::i32 width, blt::i32 height) +{ + im::SetNextItemOpen(true, ImGuiCond_Once); + if (im::CollapsingHeader("Selection Information")) + { + im::Text("Silly (%ld) | (%ld || %ld)", drag_selection, primary_selection, secondary_selection); + } +} + +void selector_t::set_secondary_selection(blt::i64 n) +{ + secondary_selection = n; +} + +void selector_t::set_primary_selection(blt::i64 n) +{ + primary_selection = n; +} + +void selector_t::set_drag_selection(blt::i64 n) +{ + drag_selection = n; +}