Commit 31dec45d authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

gui: add application class to move static variables

parent e35da6e7
Pipeline #27843 passed with stage
in 1 minute and 40 seconds
......@@ -120,31 +120,39 @@ get_executable_directory()
}
#endif
path_manager::path_manager(window_logger& logger)
application::settings_manager::settings_manager() noexcept
{
if (auto home = get_home_directory(); home) {
home_dir = home.value();
home_dir /= "irritator";
} else {
logger.log(
3, "Fail to retrieve home directory. Use current directory instead");
home_dir = std::filesystem::current_path();
}
try {
if (auto home = get_home_directory(); home) {
home_dir = home.value();
home_dir /= "irritator";
} else {
log_w.log(
3,
"Fail to retrieve home directory. Use current directory instead");
home_dir = std::filesystem::current_path();
}
if (auto install = get_executable_directory(); install) {
install_dir = install.value();
} else {
logger.log(
3,
"Fail to retrieve executable directory. Use current directory "
"instead");
install_dir = std::filesystem::current_path();
}
if (auto install = get_executable_directory(); install) {
executable_dir = install.value();
} else {
log_w.log(
3,
"Fail to retrieve executable directory. Use current directory "
"instead");
executable_dir = std::filesystem::current_path();
}
logger.log(5,
"home: %s\ninstall: %s\n",
home_dir.u8string().c_str(),
install_dir.u8string().c_str());
log_w.log(5,
"home: %s\ninstall: %s\n",
home_dir.u8string().c_str(),
executable_dir.u8string().c_str());
// TODO Fill the libraries vectors with users and systems directory.
} catch (const std::exception& /*e*/) {
log_w.log(2, "Fail to initialize application");
}
}
struct file_dialog
......
......@@ -11,13 +11,13 @@
namespace irt {
void
node_editor_initialize();
application_initialize();
bool
node_editor_show();
application_show();
void
node_editor_shutdown();
application_shutdown();
/* Move into internal API */
......
......@@ -120,7 +120,7 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init(glsl_version);
imnodes::Initialize();
irt::node_editor_initialize();
irt::application_initialize();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can
......@@ -169,7 +169,7 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
if (!irt::node_editor_show())
if (!irt::application_show())
glfwSetWindowShouldClose(window, GLFW_TRUE);
// Rendering
......@@ -189,7 +189,7 @@ main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
// Cleanup
irt::node_editor_shutdown();
irt::application_shutdown();
imnodes::Shutdown();
ImGui_ImplOpenGL3_Shutdown();
......
......@@ -97,7 +97,7 @@ int main(int, char**)
g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart());
imnodes::Initialize();
irt::node_editor_initialize();
irt::application_initialize();
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
......@@ -141,7 +141,7 @@ int main(int, char**)
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
if (!irt::node_editor_show())
if (!irt::application_show())
::PostMessage(hwnd, WM_CLOSE, 0, 0);
// Rendering
......@@ -180,7 +180,7 @@ int main(int, char**)
frameCtxt->FenceValue = fenceValue;
}
irt::node_editor_shutdown();
irt::application_shutdown();
imnodes::Shutdown();
......
......@@ -23,37 +23,14 @@
namespace irt {
static int kernel_model_cache = 1024;
static int kernel_message_cache = 32768;
static int gui_node_cache = 1024;
static ImVec4 gui_model_color{ .27f, .27f, .54f, 1.f };
static ImVec4 gui_model_transition_color{ .27f, .54f, .54f, 1.f };
static ImVec4 gui_cluster_color{ .27f, .54f, .27f, 1.f };
static ImU32 gui_hovered_model_color;
static ImU32 gui_selected_model_color;
static ImU32 gui_hovered_model_transition_color;
static ImU32 gui_selected_model_transition_color;
static ImU32 gui_hovered_cluster_color;
static ImU32 gui_selected_cluster_color;
static int automatic_layout_iteration_limit = 200;
static auto automatic_layout_x_distance = 350.f;
static auto automatic_layout_y_distance = 350.f;
static auto grid_layout_x_distance = 250.f;
static auto grid_layout_y_distance = 250.f;
static bool show_dynamics_inputs_in_editor = false;
static ImVec4
operator*(const ImVec4& lhs, const float rhs) noexcept
{
return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs);
}
static void
compute_color() noexcept
void
editor::settings_manager::compute_colors() noexcept
{
gui_hovered_model_color =
ImGui::ColorConvertFloat4ToU32(gui_model_color * 1.25f);
......@@ -130,9 +107,6 @@ for_each(DataArray& d_array, Container& container, Function f) noexcept
}
}
static window_logger log_w;
static data_array<editor, editor_id> editors;
void
editor::clear() noexcept
{
......@@ -766,10 +740,11 @@ editor::compute_grid_layout() noexcept
int elem = 0;
for (int i = 0; i < column; ++i) {
new_pos.y = panning.y + static_cast<float>(i) * grid_layout_y_distance;
new_pos.y =
panning.y + static_cast<float>(i) * settings.grid_layout_y_distance;
for (int j = 0; j < line; ++j) {
new_pos.x =
panning.x + static_cast<float>(j) * grid_layout_x_distance;
new_pos.x = panning.x +
static_cast<float>(j) * settings.grid_layout_x_distance;
imnodes::SetNodeGridSpacePos(top.children[elem].second, new_pos);
positions[elem].x = new_pos.x;
positions[elem].y = new_pos.y;
......@@ -778,9 +753,11 @@ editor::compute_grid_layout() noexcept
}
new_pos.x = panning.x;
new_pos.y = panning.y + static_cast<float>(column) * grid_layout_y_distance;
new_pos.y =
panning.y + static_cast<float>(column) * settings.grid_layout_y_distance;
for (int j = 0; j < remaining; ++j) {
new_pos.x = panning.x + static_cast<float>(j) * grid_layout_x_distance;
new_pos.x =
panning.x + static_cast<float>(j) * settings.grid_layout_x_distance;
imnodes::SetNodeGridSpacePos(top.children[elem].second, new_pos);
positions[elem].x = new_pos.x;
positions[elem].y = new_pos.y;
......@@ -809,8 +786,10 @@ editor::compute_automatic_layout() noexcept
remaining -= column;
}
const float W = static_cast<float>(column) * automatic_layout_x_distance;
const float L = line + (remaining > 0) ? automatic_layout_y_distance : 0.f;
const float W =
static_cast<float>(column) * settings.automatic_layout_x_distance;
const float L =
line + (remaining > 0) ? settings.automatic_layout_y_distance : 0.f;
const float area = W * L;
const float k_square = area / static_cast<float>(top.children.size());
const float k = std::sqrt(k_square);
......@@ -819,9 +798,11 @@ editor::compute_automatic_layout() noexcept
// static_cast<float>(automatic_layout_iteration_limit);
// t *= t;
float t = 1.f - 1.f / static_cast<float>(automatic_layout_iteration_limit);
float t =
1.f - 1.f / static_cast<float>(settings.automatic_layout_iteration_limit);
for (int iteration = 0; iteration < automatic_layout_iteration_limit;
for (int iteration = 0;
iteration < settings.automatic_layout_iteration_limit;
++iteration) {
for (int i_v = 0; i_v < size; ++i_v) {
const int v = i_v;
......@@ -953,12 +934,12 @@ editor::copy(const ImVector<int>& nodes) noexcept
status
editor::initialize(u32 id) noexcept
{
irt_return_if_bad(sim.init(to_unsigned(kernel_model_cache),
to_unsigned(kernel_message_cache)));
irt_return_if_bad(sim.init(to_unsigned(settings.kernel_model_cache),
to_unsigned(settings.kernel_message_cache)));
irt_return_if_bad(clusters.init(sim.models.capacity()));
irt_return_if_bad(top.init(to_unsigned(gui_node_cache)));
irt_return_if_bad(plot_outs.init(to_unsigned(kernel_model_cache)));
irt_return_if_bad(file_outs.init(to_unsigned(kernel_model_cache)));
irt_return_if_bad(top.init(to_unsigned(settings.gui_node_cache)));
irt_return_if_bad(plot_outs.init(to_unsigned(settings.kernel_model_cache)));
irt_return_if_bad(file_outs.init(to_unsigned(settings.kernel_model_cache)));
try {
observation_outputs.resize(sim.models.capacity());
......@@ -2026,7 +2007,7 @@ editor::show_model_dynamics(model& mdl) noexcept
add_input_attribute(*this, dyn);
ImGui::PushItemWidth(120.0f);
if (show_dynamics_inputs_in_editor)
if (settings.show_dynamics_inputs_in_editor)
show_dynamics_inputs(dyn);
ImGui::PopItemWidth();
add_output_attribute(*this, dyn);
......@@ -2121,25 +2102,27 @@ editor::show_top() noexcept
if (st != editor_status::editing &&
models_make_transition[get_index(id)]) {
imnodes::PushColorStyle(imnodes::ColorStyle_TitleBar,
ImGui::ColorConvertFloat4ToU32(
gui_model_transition_color));
imnodes::PushColorStyle(
imnodes::ColorStyle_TitleBar,
ImGui::ColorConvertFloat4ToU32(
settings.gui_model_transition_color));
imnodes::PushColorStyle(imnodes::ColorStyle_TitleBarHovered,
gui_hovered_model_transition_color);
imnodes::PushColorStyle(
imnodes::ColorStyle_TitleBarHovered,
settings.gui_hovered_model_transition_color);
imnodes::PushColorStyle(
imnodes::ColorStyle_TitleBarSelected,
gui_selected_model_transition_color);
settings.gui_selected_model_transition_color);
} else {
imnodes::PushColorStyle(
imnodes::ColorStyle_TitleBar,
ImGui::ColorConvertFloat4ToU32(gui_model_color));
ImGui::ColorConvertFloat4ToU32(settings.gui_model_color));
imnodes::PushColorStyle(imnodes::ColorStyle_TitleBarHovered,
gui_hovered_model_color);
settings.gui_hovered_model_color);
imnodes::PushColorStyle(
imnodes::ColorStyle_TitleBarSelected,
gui_selected_model_color);
settings.gui_selected_model_color);
}
imnodes::BeginNode(top.children[i].second);
......@@ -2173,11 +2156,11 @@ editor::show_top() noexcept
if (auto* gp = clusters.try_to_get(id); gp) {
imnodes::PushColorStyle(
imnodes::ColorStyle_TitleBar,
ImGui::ColorConvertFloat4ToU32(gui_cluster_color));
ImGui::ColorConvertFloat4ToU32(settings.gui_cluster_color));
imnodes::PushColorStyle(imnodes::ColorStyle_TitleBarHovered,
gui_hovered_cluster_color);
settings.gui_hovered_cluster_color);
imnodes::PushColorStyle(imnodes::ColorStyle_TitleBarSelected,
gui_selected_cluster_color);
settings.gui_selected_cluster_color);
imnodes::BeginNode(top.children[i].second);
imnodes::BeginNodeTitleBar();
......@@ -2205,6 +2188,46 @@ editor::show_top() noexcept
}
}
void
editor::settings_manager::show(bool* is_open)
{
ImGui::SetNextWindowPos(ImVec2(300, 300), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(350, 400), ImGuiCond_Once);
if (!ImGui::Begin("Settings", is_open)) {
ImGui::End();
return;
}
ImGui::Text("Kernel");
ImGui::DragInt("model cache", &kernel_model_cache, 1.f, 1024, 1024 * 1024);
ImGui::DragInt("msg cache", &kernel_message_cache, 1.f, 1024, 1024 * 1024);
ImGui::Text("Graphics");
ImGui::DragInt("node cache", &gui_node_cache, 1.f, 1024, 1024 * 1024);
if (ImGui::ColorEdit3(
"model", (float*)&gui_model_color, ImGuiColorEditFlags_NoOptions))
compute_colors();
if (ImGui::ColorEdit3(
"cluster", (float*)&gui_cluster_color, ImGuiColorEditFlags_NoOptions))
compute_colors();
ImGui::Text("Automatic layout parameters");
ImGui::DragInt(
"max iteration", &automatic_layout_iteration_limit, 1.f, 0, 1000);
ImGui::DragFloat(
"a-x-distance", &automatic_layout_x_distance, 1.f, 150.f, 500.f);
ImGui::DragFloat(
"a-y-distance", &automatic_layout_y_distance, 1.f, 150.f, 500.f);
ImGui::Text("Grid layout parameters");
ImGui::DragFloat(
"g-x-distance", &grid_layout_x_distance, 1.f, 150.f, 500.f);
ImGui::DragFloat(
"g-y-distance", &grid_layout_y_distance, 1.f, 150.f, 500.f);
ImGui::End();
}
void
add_popup_menuitem(editor& ed, dynamics_type type, model_id* new_model)
{
......@@ -2280,13 +2303,15 @@ editor::show_editor() noexcept
if (ImGui::BeginMenu("Edition")) {
ImGui::MenuItem("Show parameter in models",
nullptr,
&show_dynamics_inputs_in_editor);
&settings.show_dynamics_inputs_in_editor);
if (ImGui::MenuItem("Clear"))
clear();
if (ImGui::MenuItem("Grid Reorder"))
compute_grid_layout();
if (ImGui::MenuItem("Automatic Layout"))
compute_automatic_layout();
if (ImGui::MenuItem("Settings"))
show_settings = true;
ImGui::EndMenu();
}
......@@ -2599,15 +2624,15 @@ editor::show_editor() noexcept
if (num_selected_nodes > 0) {
selected_nodes.resize(num_selected_nodes, -1);
if (ImGui::IsKeyReleased('X')) {
if (ImGui::GetIO().KeyCtrl && ImGui::IsKeyReleased('X')) {
imnodes::GetSelectedNodes(selected_nodes.begin());
log_w.log(7, "%d model(s) to delete\n", num_selected_nodes);
free_children(selected_nodes);
} else if (ImGui::IsKeyReleased('D')) {
} else if (ImGui::GetIO().KeyCtrl && ImGui::IsKeyReleased('D')) {
imnodes::GetSelectedNodes(selected_nodes.begin());
log_w.log(7, "%d model(s)/group(s) to copy\n", num_selected_nodes);
copy(selected_nodes);
} else if (ImGui::IsKeyReleased('G')) {
} else if (ImGui::GetIO().KeyCtrl && ImGui::IsKeyReleased('G')) {
if (num_selected_nodes > 1) {
imnodes::GetSelectedNodes(selected_nodes.begin());
log_w.log(7, "%d model(s) to group\n", num_selected_nodes);
......@@ -2622,7 +2647,7 @@ editor::show_editor() noexcept
} else if (num_selected_links > 0) {
selected_links.resize(static_cast<size_t>(num_selected_links));
if (ImGui::IsKeyReleased('X')) {
if (ImGui::GetIO().KeyCtrl && ImGui::IsKeyReleased('X')) {
std::fill_n(selected_links.begin(), selected_links.size(), -1);
imnodes::GetSelectedLinks(selected_links.begin());
std::sort(
......@@ -2669,6 +2694,13 @@ editor::show_editor() noexcept
selected_nodes.resize(num_selected_nodes, -1);
imnodes::GetSelectedNodes(selected_nodes.begin());
static std::vector<std::string> names;
names.clear();
names.resize(selected_nodes.size());
for (int i = 0, e = selected_nodes.size(); i != e; ++i)
names[i] = fmt::format("{}", selected_nodes[i]);
for (int i = 0, e = selected_nodes.size(); i != e; ++i) {
const auto index = top.get_index(selected_nodes[i]);
......@@ -2684,9 +2716,8 @@ editor::show_editor() noexcept
if (!mdl)
continue;
// TODO use the dynamic or model name.
const auto& name = dynamics_type_names[static_cast<int>(mdl->type)];
if (ImGui::TreeNodeEx(name, ImGuiTreeNodeFlags_DefaultOpen)) {
if (ImGui::TreeNodeEx(names[i].c_str(),
ImGuiTreeNodeFlags_DefaultOpen)) {
auto& out = observation_outputs[get_index(id)];
auto* plot = plot_outs.try_to_get(out.plot_id);
......@@ -2695,6 +2726,9 @@ editor::show_editor() noexcept
irt_assert(!(file && plot));
int choose = plot ? 1 : file ? 2 : 0;
ImGui::Text("%s",
dynamics_type_names[static_cast<int>(mdl->type)]);
ImGui::RadioButton("none", &choose, 0);
ImGui::SameLine();
ImGui::RadioButton("plot", &choose, 1);
......@@ -2708,11 +2742,11 @@ editor::show_editor() noexcept
}
if (!plot) {
plot_output& tf = plot_outs.alloc("unamed");
plot_output& tf = plot_outs.alloc(names[i].c_str());
plot = &tf;
out.plot_id = plot_outs.get_id(tf);
auto& o =
sim.observers.alloc(0.01, "unamed", (void*)plot);
auto& o = sim.observers.alloc(
0.01, names[i].c_str(), (void*)plot);
o.initialize = &observation_plot_output_initialize;
o.observe = &observation_plot_output_observe;
o.free = &observation_plot_output_free;
......@@ -2720,7 +2754,7 @@ editor::show_editor() noexcept
}
ImGui::InputText(
"name##plot", plot->name.begin(), plot->name.size());
"name##plot", plot->name.begin(), plot->name.capacity());
} else if (choose == 2) {
if (plot) {
plot_outs.free(*plot);
......@@ -2728,18 +2762,18 @@ editor::show_editor() noexcept
}
if (!file) {
file_output& tf = file_outs.alloc("unamed");
file_output& tf = file_outs.alloc(names[i].c_str());
file = &tf;
out.file_id = file_outs.get_id(tf);
auto& o =
sim.observers.alloc(0.01, "unamed", (void*)file);
auto& o = sim.observers.alloc(
0.01, names[i].c_str(), (void*)file);
o.initialize = &observation_file_output_initialize;
o.observe = &observation_file_output_observe;
o.free = &observation_file_output_free;
sim.observe(*mdl, o);
}
ImGui::InputText(
"name##file", file->name.begin(), file->name.size());
"name##file", file->name.begin(), file->name.capacity());
} else {
if (plot) {
plot_outs.free(*plot);
......@@ -2771,7 +2805,7 @@ editor::show_editor() noexcept
}
editor*
editors_new()
application::alloc_editor()
{
if (!editors.can_alloc(1u)) {
log_w.log(2, "Too many open editor\n");
......@@ -2790,32 +2824,51 @@ editors_new()
}
void
editors_free(editor& ed)
application::free_editor(editor& ed)
{
log_w.log(5, "Close editor %s\n", ed.name.c_str());
editors.free(ed);
}
void
application::settings_manager::show(bool* is_open)
{
ImGui::SetNextWindowPos(ImVec2(300, 300), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(350, 400), ImGuiCond_Once);
if (!ImGui::Begin("Settings", is_open)) {
ImGui::End();
return;
}
ImGui::Text("Home.......: %s", home_dir.u8string().c_str());
ImGui::Text("Executable.: %s", executable_dir.u8string().c_str());
ImGui::Text("Libraries..:");
for (sz i = 0u, e = libraries_dir.size(); i != e; ++i)
ImGui::Text("- %s", libraries_dir[i].c_str());
ImGui::End();
}
editor*
make_combo_editor_name(editor_id& current) noexcept
make_combo_editor_name(application& app, editor_id& current) noexcept
{
editor* first = editors.try_to_get(current);
editor* first = app.editors.try_to_get(current);
if (first == nullptr) {
if (!editors.next(first)) {
if (!app.editors.next(first)) {
current = undefined<editor_id>();
return nullptr;
}
}
current = editors.get_id(first);
current = app.editors.get_id(first);
if (ImGui::BeginCombo("Name", first->name.c_str())) {
editor* ed = nullptr;
while (editors.next(ed)) {
const bool is_selected = current == editors.get_id(ed);
while (app.editors.next(ed)) {
const bool is_selected = current == app.editors.get_id(ed);
if (ImGui::Selectable(ed->name.c_str(), is_selected))
current = editors.get_id(ed);
current = app.editors.get_id(ed);
if (is_selected)
ImGui::SetItemDefaultFocus();
......@@ -2824,63 +2877,11 @@ make_combo_editor_name(editor_id& current) noexcept
ImGui::EndCombo();
}
return editors.try_to_get(current);
}
static void
show_settings_window(bool* is_open)
{
ImGui::SetNextWindowPos(ImVec2(300, 300), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(350, 400), ImGuiCond_Once);
if (!ImGui::Begin("Settings", is_open)) {
ImGui::End();
return;
}
ImGui::Text("Kernel");
ImGui::DragInt("model cache", &kernel_model_cache, 1.f, 1024, 1024 * 1024);
ImGui::DragInt("msg cache", &kernel_message_cache, 1.f, 1024, 1024 * 1024);
ImGui::Text("Graphics");
ImGui::DragInt("node cache", &gui_node_cache, 1.f, 1024, 1024 * 1024);
if (ImGui::ColorEdit3(
"model", (float*)&gui_model_color, ImGuiColorEditFlags_NoOptions))
compute_color();
if (ImGui::ColorEdit3(
"cluster", (float*)&gui_cluster_color, ImGuiColorEditFlags_NoOptions))
compute_color();
ImGui::Text("Automatic layout parameters");
ImGui::DragInt(
"max iteration", &automatic_layout_iteration_limit, 1.f, 0, 1000);
ImGui::DragFloat(
"a-x-distance", &automatic_layout_x_distance, 1.f, 150.f, 500.f);
ImGui::DragFloat(
"a-y-distance", &automatic_layout_y_distance, 1.f, 150.f, 500.f);
ImGui::Text("Grid layout parameters");
ImGui::DragFloat(
"g-x-distance", &grid_layout_x_distance, 1.f, 150.f, 500.f);
ImGui::DragFloat(
"g-y-distance", &grid_layout_y_distance, 1.f, 150.f, 500.f);
ImGui::End();
return app.editors.try_to_get(current);
}
void