m select
parent
e927954d6a
commit
9516c479f2
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
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_ADDRSAN "Enable the address sanitizer" OFF)
|
||||||
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace conf
|
||||||
}
|
}
|
||||||
|
|
||||||
class graph_t;
|
class graph_t;
|
||||||
|
class selector_t;
|
||||||
struct loader_t;
|
struct loader_t;
|
||||||
|
|
||||||
#endif //GRAPHS_CONFIG_H
|
#endif //GRAPHS_CONFIG_H
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <graph_base.h>
|
#include <graph_base.h>
|
||||||
|
#include <selection.h>
|
||||||
#include <force_algorithms.h>
|
#include <force_algorithms.h>
|
||||||
#include <blt/gfx/window.h>
|
#include <blt/gfx/window.h>
|
||||||
#include <blt/math/interpolation.h>
|
#include <blt/math/interpolation.h>
|
||||||
|
@ -28,14 +29,6 @@
|
||||||
|
|
||||||
namespace im = ImGui;
|
namespace im = ImGui;
|
||||||
|
|
||||||
enum class anim_state_t
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
HIGHLIGHT_NODE,
|
|
||||||
SELECT_NODE,
|
|
||||||
HIGHLIGHT_TO_SELECT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct bounding_box
|
struct bounding_box
|
||||||
{
|
{
|
||||||
int min_x = 0;
|
int min_x = 0;
|
||||||
|
@ -53,6 +46,7 @@ struct bounding_box
|
||||||
class graph_t
|
class graph_t
|
||||||
{
|
{
|
||||||
friend struct loader_t;
|
friend struct loader_t;
|
||||||
|
friend class selector_t;
|
||||||
private:
|
private:
|
||||||
std::vector<node_t> nodes;
|
std::vector<node_t> nodes;
|
||||||
blt::hashmap_t<std::string, blt::u64> names_to_node;
|
blt::hashmap_t<std::string, blt::u64> names_to_node;
|
||||||
|
@ -66,14 +60,7 @@ class graph_t
|
||||||
int current_iterations = 0;
|
int current_iterations = 0;
|
||||||
int max_iterations = 5000;
|
int max_iterations = 5000;
|
||||||
std::unique_ptr<force_equation> equation;
|
std::unique_ptr<force_equation> 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,
|
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);
|
blt::f64 scaling_connectivity, blt::f64 distance_factor);
|
||||||
|
|
||||||
|
@ -130,17 +117,6 @@ class graph_t
|
||||||
|
|
||||||
void render();
|
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()
|
void use_Eades()
|
||||||
{
|
{
|
||||||
equation = std::make_unique<Eades_equation>();
|
equation = std::make_unique<Eades_equation>();
|
||||||
|
@ -212,6 +188,7 @@ class engine_t
|
||||||
friend struct loader_t;
|
friend struct loader_t;
|
||||||
private:
|
private:
|
||||||
graph_t graph;
|
graph_t graph;
|
||||||
|
selector_t selector;
|
||||||
|
|
||||||
void draw_gui(const blt::gfx::window_data& data);
|
void draw_gui(const blt::gfx::window_data& data);
|
||||||
|
|
||||||
|
@ -228,11 +205,10 @@ class engine_t
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
|
|
||||||
if (!io.WantCaptureMouse)
|
if (!io.WantCaptureMouse)
|
||||||
{
|
selector.process_mouse(graph, data.width, data.height);
|
||||||
graph.process_mouse_drag(data.width, data.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
graph.render();
|
graph.render();
|
||||||
|
selector.render(graph, data.width, data.height);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHS_SELECTION_H
|
||||||
|
#define GRAPHS_SELECTION_H
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
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
|
|
@ -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<blt::i64>(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<float>(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,
|
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)
|
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)
|
void engine_t::draw_gui(const blt::gfx::window_data& data)
|
||||||
{
|
{
|
||||||
double ft = blt::gfx::getFrameDeltaSeconds();
|
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);
|
selector.draw_gui(graph, data.width, data.height);
|
||||||
if (im::CollapsingHeader("Node Information"))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
im::End();
|
im::End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* <Short Description>
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <selection.h>
|
||||||
|
#include <graph.h>
|
||||||
|
#include <blt/gfx/raycast.h>
|
||||||
|
|
||||||
|
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<blt::i64>(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<blt::i64>(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;
|
||||||
|
}
|
Loading…
Reference in New Issue