merge: issue/0046-cpp-refactor-raw-imgui — implementación paralela

This commit is contained in:
2026-04-29 00:30:36 +02:00
4 changed files with 54 additions and 43 deletions
+28 -25
View File
@@ -14,6 +14,7 @@
#include "core/page_header.h" #include "core/page_header.h"
#include "core/toast.h" #include "core/toast.h"
#include "core/app_menubar.h" #include "core/app_menubar.h"
#include "core/tree_view.h"
#include "demos.h" #include "demos.h"
#include "demo.h" #include "demo.h"
@@ -90,35 +91,37 @@ static const DemoEntry* find_demo(const std::string& id) {
} }
static void draw_sidebar() { static void draw_sidebar() {
using namespace fn_tokens;
ImGui::BeginChild("##gallery_sidebar", ImVec2(220, 0), ImGui::BeginChild("##gallery_sidebar", ImVec2(220, 0),
ImGuiChildFlags_Borders); ImGuiChildFlags_Borders);
const char* current_category = nullptr; // Agrupar por categoria como rama del tree_view (categorias abiertas por
for (int i = 0; i < k_demo_count; i++) { // defecto). Cada demo es una hoja seleccionable.
const auto& d = k_demos[i]; int i = 0;
if (!current_category || std::strcmp(current_category, d.category) != 0) { while (i < k_demo_count) {
if (current_category) ImGui::Dummy(ImVec2(0, spacing::sm)); const char* category = k_demos[i].category;
ImGui::PushStyleColor(ImGuiCol_Text, colors::text_dim);
ImGui::TextUnformatted(d.category); // Default-open la rama la primera vez que se abre el sidebar.
ImGui::PopStyleColor(); ImGui::SetNextItemOpen(true, ImGuiCond_FirstUseEver);
ImGui::Separator(); if (fn_ui::tree_branch_begin(category, category, /*selected=*/false)) {
current_category = d.category; // Recorrer todas las demos consecutivas con esta misma categoria.
while (i < k_demo_count
&& std::strcmp(k_demos[i].category, category) == 0) {
const auto& d = k_demos[i];
const bool selected = (g_selected_id == d.id);
fn_ui::tree_leaf(d.id, d.label, selected);
if (fn_ui::tree_node_clicked()) {
g_selected_id = d.id;
}
i++;
}
fn_ui::tree_branch_end();
} else {
// Rama colapsada — saltar todos sus items.
while (i < k_demo_count
&& std::strcmp(k_demos[i].category, category) == 0) {
i++;
}
} }
const bool selected = (g_selected_id == d.id);
ImGui::PushStyleColor(ImGuiCol_Header, selected ? colors::surface_hover : ImVec4(0,0,0,0));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, colors::surface_hover);
ImGui::PushStyleColor(ImGuiCol_HeaderActive, colors::surface);
ImGui::PushStyleColor(ImGuiCol_Text, selected ? colors::primary : colors::text);
char label[96];
std::snprintf(label, sizeof(label), "%s##sel_%s", d.label, d.id);
if (ImGui::Selectable(label, selected)) {
g_selected_id = d.id;
}
ImGui::PopStyleColor(4);
} }
ImGui::EndChild(); ImGui::EndChild();
+4
View File
@@ -17,6 +17,10 @@ add_imgui_app(shaders_lab
${CMAKE_SOURCE_DIR}/functions/gfx/dag_node_previews.cpp ${CMAKE_SOURCE_DIR}/functions/gfx/dag_node_previews.cpp
${CMAKE_SOURCE_DIR}/functions/gfx/shaderlab_db.cpp ${CMAKE_SOURCE_DIR}/functions/gfx/shaderlab_db.cpp
${CMAKE_SOURCE_DIR}/functions/gfx/code_to_generator.cpp ${CMAKE_SOURCE_DIR}/functions/gfx/code_to_generator.cpp
# Primitivos UI usados por el modal Save-as-generator.
${CMAKE_SOURCE_DIR}/functions/core/modal_dialog.cpp
${CMAKE_SOURCE_DIR}/functions/core/text_input.cpp
${CMAKE_SOURCE_DIR}/functions/core/button.cpp
# fps_overlay, panel_menu, layouts_menu, app_menubar, layout_storage ya # fps_overlay, panel_menu, layouts_menu, app_menubar, layout_storage ya
# viven en fn_framework. # viven en fn_framework.
) )
+22 -18
View File
@@ -17,6 +17,10 @@
#include "core/panel_menu.h" #include "core/panel_menu.h"
#include "core/layouts_menu.h" #include "core/layouts_menu.h"
#include "core/layout_storage.h" #include "core/layout_storage.h"
#include "core/modal_dialog.h"
#include "core/text_input.h"
#include "core/button.h"
#include "core/tokens.h"
#include "compiler.h" #include "compiler.h"
@@ -236,41 +240,41 @@ static void render() {
// --- Code window --- // --- Code window ---
if (g_show_code) { if (g_show_code) {
if (ImGui::Begin("Code", &g_show_code)) { if (ImGui::Begin("Code", &g_show_code)) {
if (ImGui::Button("Save as generator...")) { if (fn_ui::button("Save as generator...", fn_ui::ButtonVariant::Secondary)) {
g_save_modal_open = true; g_save_modal_open = true;
g_save_err.clear(); g_save_err.clear();
ImGui::OpenPopup("save_as_generator");
} }
if (ImGui::BeginPopupModal("save_as_generator", &g_save_modal_open, if (fn_ui::modal_dialog_begin("Save as generator", &g_save_modal_open,
ImGuiWindowFlags_AlwaysAutoResize)) { ImVec2(420, 0))) {
ImGui::Text("Guardar shader actual como nodo Gen del DAG."); ImGui::TextUnformatted("Guardar shader actual como nodo Gen del DAG.");
ImGui::Spacing(); ImGui::Spacing();
ImGui::InputText("name (snake_case)", g_save_name, sizeof(g_save_name)); fn_ui::text_input("name (snake_case)", g_save_name, sizeof(g_save_name),
ImGui::InputText("label", g_save_label, sizeof(g_save_label)); "ej: my_shader");
fn_ui::text_input("label", g_save_label, sizeof(g_save_label));
ImGui::InputTextMultiline("description", g_save_desc, sizeof(g_save_desc), ImGui::InputTextMultiline("description", g_save_desc, sizeof(g_save_desc),
ImVec2(380, 60)); ImVec2(380, 60));
ImGui::InputText("tags (CSV)", g_save_tags, sizeof(g_save_tags)); fn_ui::text_input("tags (CSV)", g_save_tags, sizeof(g_save_tags));
if (!g_save_err.empty()) { if (!g_save_err.empty()) {
ImGui::TextColored(ImVec4(1, 0.4f, 0.4f, 1), "%s", g_save_err.c_str()); ImGui::PushStyleColor(ImGuiCol_Text, fn_tokens::colors::error);
ImGui::TextWrapped("%s", g_save_err.c_str());
ImGui::PopStyleColor();
} }
ImGui::Spacing(); ImGui::Separator();
if (ImGui::Button("Save", ImVec2(120, 0))) { if (fn_ui::button("Cancel", fn_ui::ButtonVariant::Subtle)) {
g_save_modal_open = false;
}
ImGui::SameLine();
if (fn_ui::button("Save", fn_ui::ButtonVariant::Primary)) {
g_save_err = save_current_as_generator(); g_save_err = save_current_as_generator();
if (g_save_err.empty()) { if (g_save_err.empty()) {
g_save_modal_open = false; g_save_modal_open = false;
ImGui::CloseCurrentPopup();
} }
} }
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120, 0))) {
g_save_modal_open = false;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
} }
fn_ui::modal_dialog_end();
ImVec2 avail = ImGui::GetContentRegionAvail(); ImVec2 avail = ImGui::GetContentRegionAvail();
float footer_h = g_code_err.empty() ? 0.0f : ImGui::GetTextLineHeightWithSpacing() + 8.0f; float footer_h = g_code_err.empty() ? 0.0f : ImGui::GetTextLineHeightWithSpacing() + 8.0f;