Search code examples
c++opengltexturesglfwimgui

OpenGL imgui slider ranges


I have a 960x540 window I'm creating using OpenGL. Rendering one texture here and using imgui to implement a slider that let's me translate the x, y, and z positions at runtime.

int window_width = 960;
int window_height = 540;

window = glfwCreateWindow(window_width, window_height, "Object Oriented OpenGL", NULL, NULL);

First I set the slider default values.

glm::vec3 model_matrix_translation(200, 200, 0);

Later in my loop that renders the objects positions frame by frame as long as the window is open, I set the ImGui::SliderFloat3 v_min and v_max params to be the dimensions of my window. It appears all 3 sliders x,y, and z use these values, but is there a way to set a range for each individuals slider? As you can see my slider for the y axis can go beyond 540.

while (!glfwWindowShouldClose(window))
{
    // renderer and other code before this point
    {
        ImGui::SliderFloat3("Model Matrix Translation", &model_matrix_translation.x, 0.0f, 960.0f); 
    }
    ImGui::Render();
    ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());

    glfwSwapBuffers(window); 
    glfwPollEvents();
}

enter image description here


Solution

  • The implementation of SliderFloat3 delegates to SliderScalarN, which is implemented as such:

    bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, int components, const void* v_min, const void* v_max, const char* format, float power)
    {
        ImGuiWindow* window = GetCurrentWindow();
        if (window->SkipItems)
            return false;
    
        ImGuiContext& g = *GImGui;
        bool value_changed = false;
        BeginGroup();
        PushID(label);
        PushMultiItemsWidths(components, CalcItemWidth());
        size_t type_size = GDataTypeInfo[data_type].Size;
        for (int i = 0; i < components; i++)
        {
            PushID(i);
            if (i > 0)
                SameLine(0, g.Style.ItemInnerSpacing.x);
            value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, power);
            PopID();
            PopItemWidth();
            v = (void*)((char*)v + type_size);
        }
        PopID();
    
        const char* label_end = FindRenderedTextEnd(label);
        if (label != label_end)
        {
            SameLine(0, g.Style.ItemInnerSpacing.x);
            TextEx(label, label_end);
        }
    
        EndGroup();
        return value_changed;
    }
    

    For your purposes, you will need to use a modified version of this function that moves v_min and v_max along with v, so in your modified function, change the last line of that for loop to:

    v = (void*)((char*)v + type_size);
    v_min = (void*)((char*)v_min + type_size);
    v_max = (void*)((char*)v_max + type_size);
    

    Or just specialize the whole function to take float* instead and then you can just do v++, v_min++, v_max++; instead.

    Finally, you can call your modified function as follows:

    float mins[] = {0.0f, 0.0f, 0.0f};
    float maxs[] = {960.0f, 540.0f, 0.0f};
    MyModifiedSliderFloat3("Model Matrix Translation", &model_matrix_translation.x, mins, maxs);