Compare commits

...

2 Commits

Author SHA1 Message Date
Brett e164a1537c silly connection of edges 2024-07-30 03:16:58 -04:00
Brett 780c8ac25a allow removal of nodes! 2024-07-30 02:38:47 -04:00
5 changed files with 68 additions and 11 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(graphs VERSION 0.1.7) project(graphs VERSION 0.1.9)
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)

View File

@ -46,7 +46,9 @@ struct bounding_box
class graph_t class graph_t
{ {
friend struct loader_t; friend struct loader_t;
friend class selector_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;
@ -100,6 +102,18 @@ class graph_t
edges.insert({n1, n2}); edges.insert({n1, n2});
} }
void disconnect(const blt::u64 n1, const blt::u64 n2)
{
connected_nodes[n1].erase(n2);
connected_nodes[n2].erase(n1);
edges.erase({n1, n2});
}
bool is_connected(const blt::u64 n1, const blt::u64 n2)
{
return edges.contains({n1, n2});
}
void connect(const edge_t& edge) void connect(const edge_t& edge)
{ {
connected_nodes[edge.getFirst()].insert(edge.getSecond()); connected_nodes[edge.getFirst()].insert(edge.getSecond());
@ -188,7 +202,7 @@ class engine_t
friend struct loader_t; friend struct loader_t;
private: private:
graph_t graph; graph_t graph;
selector_t selector {graph}; selector_t selector{graph};
void draw_gui(const blt::gfx::window_data& data); void draw_gui(const blt::gfx::window_data& data);

View File

@ -75,6 +75,8 @@ struct node_t
struct edge_t struct edge_t
{ {
// fuck you too :3
friend selector_t;
float ideal_spring_length = conf::DEFAULT_SPRING_LENGTH; float ideal_spring_length = conf::DEFAULT_SPRING_LENGTH;
float thickness = conf::DEFAULT_THICKNESS; float thickness = conf::DEFAULT_THICKNESS;
blt::color4 color = conf::EDGE_COLOR; blt::color4 color = conf::EDGE_COLOR;

View File

@ -98,7 +98,7 @@ std::optional<loader_t> loader_t::load_for(engine_t& engine, const blt::gfx::win
auto ideal_length = load_with_default(edge, "length", conf::DEFAULT_SPRING_LENGTH); auto ideal_length = load_with_default(edge, "length", conf::DEFAULT_SPRING_LENGTH);
auto thickness = load_with_default(edge, "thickness", conf::DEFAULT_THICKNESS); auto thickness = load_with_default(edge, "thickness", conf::DEFAULT_THICKNESS);
::edge_t e{graph.names_to_node[index1], graph.names_to_node[index2]}; edge_t e{graph.names_to_node[index1], graph.names_to_node[index2]};
e.ideal_spring_length = ideal_length; e.ideal_spring_length = ideal_length;
e.thickness = thickness; e.thickness = thickness;

View File

@ -115,10 +115,19 @@ void selector_t::process_keyboard(blt::i32 width, blt::i32 height)
{ {
if (blt::gfx::isKeyPressed(GLFW_KEY_C)) if (blt::gfx::isKeyPressed(GLFW_KEY_C))
{ {
if (placement) if (primary_selection != -1 && secondary_selection != -1)
destroy_node(primary_selection); {
else if (graph.is_connected(primary_selection, secondary_selection))
create_placement_node(mouse_pos); graph.disconnect(primary_selection, secondary_selection);
else
graph.connect(primary_selection, secondary_selection);
} else
{
if (placement)
destroy_node(primary_selection);
else
create_placement_node(mouse_pos);
}
} else if (blt::gfx::isKeyPressed(GLFW_KEY_X)) } else if (blt::gfx::isKeyPressed(GLFW_KEY_X))
{ {
if (primary_selection != -1) if (primary_selection != -1)
@ -192,13 +201,45 @@ void selector_t::destroy_node(blt::i64 node)
{ {
auto& node_v = graph.nodes[node]; auto& node_v = graph.nodes[node];
graph.names_to_node.erase(node_v.name); graph.names_to_node.erase(node_v.name);
erase_if(graph.edges, [node](const edge_t& v) { erase_if(graph.edges, [node](const edge_t& e) {
return static_cast<blt::i64>(v.getFirst()) == node || static_cast<blt::i64>(v.getSecond()) == node; return static_cast<blt::i64>(e.getFirst()) == node || static_cast<blt::i64>(e.getSecond()) == node;
}); });
std::vector<edge_t> corrected_edges;
for (const edge_t& v : graph.edges)
{
auto copy = v;
auto c = static_cast<blt::u64>(node);
if (copy.i1 > c)
copy.i1--;
if (copy.i2 > c)
copy.i2--;
if (v.i1 > c || v.i2 > c)
corrected_edges.push_back(copy);
}
erase_if(graph.edges, [node](const edge_t& e) {
return static_cast<blt::i64>(e.getFirst()) > node || static_cast<blt::i64>(e.getSecond()) > node;
});
for (const auto& v : corrected_edges)
graph.edges.insert(v);
graph.connected_nodes.erase(node); graph.connected_nodes.erase(node);
for (auto& v : graph.connected_nodes) for (auto& v : graph.connected_nodes)
{ {
v.second.erase(node); auto& map = v.second;
// generate the list of corrected nodes.
std::vector<blt::u64> corrected_nodes;
for (auto& n : map)
{
// shift back then nodes after this one by one
if (static_cast<blt::i64>(n) > node)
{
corrected_nodes.push_back(n - 1);
}
}
erase_if(map, [node](blt::u64 n) {
return static_cast<blt::i64>(n) > node;
});
for (const auto& n : corrected_nodes)
map.insert(n);
} }
graph.nodes.erase(graph.nodes.begin() + node); graph.nodes.erase(graph.nodes.begin() + node);