Files
fn_registry/cpp/functions/gfx/uniform_panel.cpp
T
egutierrez c7821c4c99 feat(shaders_lab): uniform annotations → auto-generated ImGui controls
- cpp/functions/gfx/uniform_parser: regex-based parser of @slider/@color/@toggle/@xy annotations (+ inline tests)
- cpp/functions/gfx/uniform_panel: ImGui widgets + value store + glUniform* apply
- shader_canvas: optional uniforms callback invoked per-frame
- gl_loader: +glUniform1i/3f/4f
- seed plasma: demo uniforms u_speed + u_color
- rebuild Windows .exe

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 21:02:35 +02:00

92 lines
3.4 KiB
C++

#include "gfx/uniform_panel.h"
#include "gfx/gl_loader.h"
#include "imgui.h"
namespace fn::gfx {
void uniforms_sync(UniformStore& store, const std::vector<UniformDescriptor>& descs) {
// Remove keys no longer present
for (auto it = store.values.begin(); it != store.values.end(); ) {
bool found = false;
for (auto& d : descs) if (d.name == it->first) { found = true; break; }
it = found ? std::next(it) : store.values.erase(it);
}
// Add new entries with defaults
for (auto& d : descs) {
if (store.values.count(d.name)) continue;
std::array<float, 4> arr = {
d.defaults[0], d.defaults[1], d.defaults[2], d.defaults[3]
};
store.values[d.name] = arr;
}
}
void uniforms_panel(UniformStore& store, const std::vector<UniformDescriptor>& descs) {
if (descs.empty()) {
ImGui::TextDisabled("Declare uniforms with @slider ... annotations.");
return;
}
for (auto& d : descs) {
auto it = store.values.find(d.name);
if (it == store.values.end()) continue;
float* v = it->second.data();
switch (d.widget) {
case WidgetKind::Slider: {
if (d.glsl_type == GLSLType::Int) {
int tmp = static_cast<int>(v[0]);
if (ImGui::SliderInt(d.name.c_str(), &tmp,
static_cast<int>(d.min[0]),
static_cast<int>(d.max[0]))) {
v[0] = static_cast<float>(tmp);
}
} else {
ImGuiSliderFlags flags = d.log_scale ? ImGuiSliderFlags_Logarithmic : 0;
ImGui::SliderFloat(d.name.c_str(), &v[0], d.min[0], d.max[0], "%.3f", flags);
}
break;
}
case WidgetKind::Color: {
if (d.glsl_type == GLSLType::Vec4)
ImGui::ColorEdit4(d.name.c_str(), v);
else
ImGui::ColorEdit3(d.name.c_str(), v);
break;
}
case WidgetKind::Toggle: {
bool tmp = v[0] != 0.0f;
if (ImGui::Checkbox(d.name.c_str(), &tmp))
v[0] = tmp ? 1.0f : 0.0f;
break;
}
case WidgetKind::XY: {
ImGui::SliderFloat2(d.name.c_str(), v, d.min[0], d.max[0]);
break;
}
}
}
}
void uniforms_apply(const UniformStore& store, const std::vector<UniformDescriptor>& descs, unsigned int program) {
for (auto& d : descs) {
auto it = store.values.find(d.name);
if (it == store.values.end()) continue;
const float* v = it->second.data();
GLint loc = glGetUniformLocation(program, d.name.c_str());
if (loc < 0) continue;
switch (d.glsl_type) {
case GLSLType::Float: glUniform1f(loc, v[0]); break;
case GLSLType::Int: glUniform1i(loc, static_cast<GLint>(v[0])); break;
case GLSLType::Bool: glUniform1i(loc, v[0] != 0.0f ? 1 : 0); break;
case GLSLType::Vec2: glUniform2f(loc, v[0], v[1]); break;
case GLSLType::Vec3: glUniform3f(loc, v[0], v[1], v[2]); break;
case GLSLType::Vec4: glUniform4f(loc, v[0], v[1], v[2], v[3]); break;
}
}
}
} // namespace fn::gfx