removing nodes causes problems!
|
@ -1,5 +1,5 @@
|
|||
cmake_minimum_required(VERSION 3.25)
|
||||
project(graphs VERSION 0.1.6)
|
||||
project(graphs VERSION 0.1.7)
|
||||
|
||||
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
|
||||
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace conf
|
|||
inline constexpr float DEFAULT_INITIAL_TEMPERATURE = 100;
|
||||
|
||||
inline constexpr float POINT_SIZE = 35;
|
||||
inline constexpr auto DEFAULT_IMAGE = "parker_point";
|
||||
inline constexpr auto DEFAULT_IMAGE = "unknown";
|
||||
inline constexpr auto POINT_OUTLINE_COLOR = blt::make_color(0, 0.6, 0.6);
|
||||
inline constexpr auto POINT_HIGHLIGHT_COLOR = blt::make_color(0, 1.0, 1.0);
|
||||
inline constexpr auto POINT_SELECT_COLOR = blt::make_color(0, 0.9, 0.7);
|
||||
|
|
|
@ -188,7 +188,7 @@ class engine_t
|
|||
friend struct loader_t;
|
||||
private:
|
||||
graph_t graph;
|
||||
selector_t selector;
|
||||
selector_t selector {graph};
|
||||
|
||||
void draw_gui(const blt::gfx::window_data& data);
|
||||
|
||||
|
@ -205,10 +205,12 @@ class engine_t
|
|||
auto& io = ImGui::GetIO();
|
||||
|
||||
if (!io.WantCaptureMouse)
|
||||
selector.process_mouse(graph, data.width, data.height);
|
||||
selector.process_mouse(data.width, data.height);
|
||||
if (!io.WantCaptureKeyboard)
|
||||
selector.process_keyboard(data.width, data.height);
|
||||
|
||||
graph.render();
|
||||
selector.render(graph, data.width, data.height);
|
||||
selector.render(data.width, data.height);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -24,23 +24,36 @@
|
|||
class selector_t
|
||||
{
|
||||
public:
|
||||
explicit selector_t(graph_t& graph): graph(graph)
|
||||
{}
|
||||
|
||||
// called inside the info panel block, used for adding more information
|
||||
void draw_gui(graph_t& graph, blt::i32 width, blt::i32 height);
|
||||
void draw_gui(blt::i32 width, blt::i32 height);
|
||||
|
||||
// called once per frame, for rendering animations
|
||||
void render(graph_t& graph, blt::i32 width, blt::i32 height);
|
||||
void render(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);
|
||||
void process_mouse(blt::i32 width, blt::i32 height);
|
||||
|
||||
void process_keyboard(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);
|
||||
|
||||
void create_placement_node(const blt::vec2& pos);
|
||||
void destroy_node(blt::i64 node);
|
||||
|
||||
private:
|
||||
blt::i64 drag_selection = -1;
|
||||
blt::i64 primary_selection = -1;
|
||||
blt::i64 secondary_selection = -1;
|
||||
bool edge = false;
|
||||
bool placement = false;
|
||||
graph_t& graph;
|
||||
};
|
||||
|
||||
#endif //GRAPHS_SELECTION_H
|
||||
|
|
After Width: | Height: | Size: 361 KiB |
After Width: | Height: | Size: 3.9 MiB |
After Width: | Height: | Size: 498 KiB |
After Width: | Height: | Size: 2.8 MiB |
After Width: | Height: | Size: 809 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 1.2 MiB |
|
@ -269,7 +269,7 @@ void engine_t::draw_gui(const blt::gfx::window_data& data)
|
|||
}
|
||||
}
|
||||
}
|
||||
selector.draw_gui(graph, data.width, data.height);
|
||||
selector.draw_gui(data.width, data.height);
|
||||
im::End();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,13 @@ void init(const blt::gfx::window_data& data)
|
|||
resources.enqueue("res/parker.png", "parker");
|
||||
resources.enqueue("res/parkerpoint.png", "parker_point");
|
||||
resources.enqueue("res/parker cat ears.jpg", "parkercat");
|
||||
resources.enqueue("res/ivy.jpg", "ivy");
|
||||
resources.enqueue("res/sayori.jpg", "sayori");
|
||||
resources.enqueue("res/jacob.jpg", "jacob");
|
||||
resources.enqueue("res/braxton.jpg", "braxton");
|
||||
resources.enqueue("res/ben.jpg", "ben");
|
||||
resources.enqueue("res/no_image.jpg", "unknown");
|
||||
resources.enqueue("res/me.png", "me");
|
||||
|
||||
if (auto loader = loader_t::load_for(engine, data, "default.json", "save.json"))
|
||||
{
|
||||
|
@ -76,6 +83,7 @@ void update(const blt::gfx::window_data& data)
|
|||
|
||||
engine.render(data);
|
||||
|
||||
if (!im::GetIO().WantCaptureKeyboard)
|
||||
camera.update();
|
||||
camera.update_view(global_matrices);
|
||||
global_matrices.update();
|
||||
|
|
138
src/selector.cpp
|
@ -18,22 +18,67 @@
|
|||
#include <selection.h>
|
||||
#include <graph.h>
|
||||
#include <blt/gfx/raycast.h>
|
||||
#include <blt/std/memory.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)
|
||||
blt::expanding_buffer<char> name_input;
|
||||
blt::expanding_buffer<char> texture_input;
|
||||
blt::expanding_buffer<char> description_input;
|
||||
|
||||
struct callback_data_t
|
||||
{
|
||||
std::string& str;
|
||||
blt::expanding_buffer<char>& buffer;
|
||||
};
|
||||
|
||||
void from_string(std::string& str, blt::expanding_buffer<char>& buf)
|
||||
{
|
||||
if (buf.size() <= str.size())
|
||||
buf.resize(str.size() + 1);
|
||||
std::memcpy(buf.data(), str.data(), str.size());
|
||||
buf.data()[str.size()] = '\0';
|
||||
}
|
||||
|
||||
int text_input_callback(ImGuiInputTextCallbackData* data)
|
||||
{
|
||||
auto [str, buffer] = *static_cast<callback_data_t*>(data->UserData);
|
||||
|
||||
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
|
||||
{
|
||||
buffer.resize(data->BufSize);
|
||||
data->Buf = buffer.data();
|
||||
} else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit || data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
|
||||
str = std::string_view{data->Buf, static_cast<blt::size_t>(data->BufTextLen)};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void selector_t::render(blt::i32 width, blt::i32 height)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void selector_t::process_mouse(graph_t& graph, blt::i32 width, blt::i32 height)
|
||||
void selector_t::process_mouse(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();
|
||||
|
||||
if (placement)
|
||||
{
|
||||
if (mouse_pressed)
|
||||
{
|
||||
placement = false;
|
||||
set_drag_selection(-1);
|
||||
} else if (blt::gfx::isKeyPressed(GLFW_KEY_ESCAPE))
|
||||
{
|
||||
destroy_node(primary_selection);
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (const auto& [index, node] : blt::enumerate(graph.nodes))
|
||||
{
|
||||
const auto pos = node.getPosition();
|
||||
|
@ -43,46 +88,121 @@ void selector_t::process_mouse(graph_t& graph, blt::i32 width, blt::i32 height)
|
|||
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);
|
||||
set_secondary_selection(-1);
|
||||
}
|
||||
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))
|
||||
}
|
||||
if (drag_selection >= 0 && drag_selection < static_cast<blt::i64>(graph.nodes.size()) && (blt::gfx::isMousePressed(0) || placement))
|
||||
{
|
||||
graph.nodes[drag_selection].getPositionRef() = mouse_pos;
|
||||
}
|
||||
}
|
||||
|
||||
void selector_t::draw_gui(graph_t& graph, blt::i32 width, blt::i32 height)
|
||||
void selector_t::process_keyboard(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()));
|
||||
if (blt::gfx::keyPressedLastFrame())
|
||||
{
|
||||
if (blt::gfx::isKeyPressed(GLFW_KEY_C))
|
||||
{
|
||||
if (placement)
|
||||
destroy_node(primary_selection);
|
||||
else
|
||||
create_placement_node(mouse_pos);
|
||||
} else if (blt::gfx::isKeyPressed(GLFW_KEY_X))
|
||||
{
|
||||
if (primary_selection != -1)
|
||||
destroy_node(primary_selection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void selector_t::draw_gui(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);
|
||||
if (primary_selection >= 0)
|
||||
{
|
||||
if (secondary_selection >= 0)
|
||||
{
|
||||
} else
|
||||
{
|
||||
im::InputFloat("Size", &graph.nodes[primary_selection].point.scale);
|
||||
callback_data_t name_data{graph.nodes[primary_selection].name, name_input};
|
||||
callback_data_t texture_data{graph.nodes[primary_selection].texture, texture_input};
|
||||
callback_data_t description_data{graph.nodes[primary_selection].description, description_input};
|
||||
im::InputText("Name", name_input.data(), name_input.size(),
|
||||
ImGuiInputTextFlags_CallbackResize | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackCompletion,
|
||||
text_input_callback, &name_data);
|
||||
im::InputText("Texture", texture_input.data(), texture_input.size(),
|
||||
ImGuiInputTextFlags_CallbackResize | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackCompletion,
|
||||
text_input_callback, &texture_data);
|
||||
im::InputTextMultiline("Description", description_input.data(), description_input.size(), {},
|
||||
ImGuiInputTextFlags_CallbackResize | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackCompletion,
|
||||
text_input_callback, &description_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void selector_t::set_secondary_selection(blt::i64 n)
|
||||
{
|
||||
secondary_selection = n;
|
||||
|
||||
}
|
||||
|
||||
void selector_t::set_primary_selection(blt::i64 n)
|
||||
{
|
||||
primary_selection = n;
|
||||
if (primary_selection >= 0)
|
||||
{
|
||||
from_string(graph.nodes[primary_selection].name, name_input);
|
||||
from_string(graph.nodes[primary_selection].texture, texture_input);
|
||||
from_string(graph.nodes[primary_selection].description, description_input);
|
||||
}
|
||||
}
|
||||
|
||||
void selector_t::set_drag_selection(blt::i64 n)
|
||||
{
|
||||
drag_selection = n;
|
||||
}
|
||||
|
||||
void selector_t::create_placement_node(const blt::vec2& pos)
|
||||
{
|
||||
auto node = static_cast<blt::i64>(graph.nodes.size());
|
||||
graph.nodes.push_back(node_t{{pos, conf::POINT_SIZE}});
|
||||
set_drag_selection(node);
|
||||
set_primary_selection(node);
|
||||
placement = true;
|
||||
}
|
||||
|
||||
void selector_t::destroy_node(blt::i64 node)
|
||||
{
|
||||
auto& node_v = graph.nodes[node];
|
||||
graph.names_to_node.erase(node_v.name);
|
||||
erase_if(graph.edges, [node](const edge_t& v) {
|
||||
return static_cast<blt::i64>(v.getFirst()) == node || static_cast<blt::i64>(v.getSecond()) == node;
|
||||
});
|
||||
graph.connected_nodes.erase(node);
|
||||
for (auto& v : graph.connected_nodes)
|
||||
{
|
||||
v.second.erase(node);
|
||||
}
|
||||
|
||||
graph.nodes.erase(graph.nodes.begin() + node);
|
||||
set_drag_selection(-1);
|
||||
set_primary_selection(-1);
|
||||
placement = false;
|
||||
}
|
||||
|
|