From 06f3fd8c1c4ae6468e100d519672157685cca708 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Mon, 2 Feb 2026 15:44:55 +0100 Subject: [PATCH 01/10] feat: add ImPlot3DSpec and ImPlot3DProp_X --- implot3d.h | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/implot3d.h b/implot3d.h index fa0c7b52..4b90a7c3 100644 --- a/implot3d.h +++ b/implot3d.h @@ -20,7 +20,8 @@ // [SECTION] Plot Items // [SECTION] Plot Utils // [SECTION] Miscellaneous -// [SECTION] Styles +// [SECTION] Specs API +// [SECTION] Styles API (legacy) // [SECTION] Demo // [SECTION] Debugging // [SECTION] ImPlot3DPoint @@ -74,6 +75,7 @@ typedef int ImAxis3D; // -> ImAxis3D_ // Enum: Axis ind typedef int ImPlane3D; // -> ImPlane3D_ // Enum: Plane indices typedef int ImPlot3DScale; // -> ImPlot3DScale_ // Enum: Axis scale (linear, log, etc.) typedef int ImPlot3DColormap; // -> ImPlot3DColormap_ // Enum: Colormaps +typedef int ImPlot3DProp; // -> ImPlot3DProp_ // Enum: Plot properties // Flags typedef int ImPlot3DFlags; // -> ImPlot3DFlags_ // Flags: for BeginPlot() @@ -167,7 +169,8 @@ enum ImPlot3DStyleVar_ { }; enum ImPlot3DMarker_ { - ImPlot3DMarker_None = -1, // No marker + ImPlot3DMarker_None = -2, // No marker + ImPlot3DMarker_Auto = -1, // Automatic marker selection ImPlot3DMarker_Circle, // Circle marker (default) ImPlot3DMarker_Square, // Square maker ImPlot3DMarker_Diamond, // Diamond marker @@ -337,6 +340,19 @@ enum ImPlot3DColormap_ { ImPlot3DColormap_Greys = 15, // White/black }; +// Plotting properties. These provide syntactic sugar for creating ImPlot3DSpec from (ImPlot3DProp,value) pairs +enum ImPlot3DProp_ { + ImPlot3DProp_LineColor, // Line color (applies to lines, marker edges); IMPLOT3D_AUTO_COL will use next Colormap color + ImPlot3DProp_LineWeight, // Line weight in pixels (applies to lines, marker edges) + ImPlot3DProp_FillColor, // Fill color (applies to shaded regions, marker faces); IMPLOT3D_AUTO_COL will use next Colormap color + ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor) + ImPlot3DProp_Marker, // Marker type + ImPlot3DProp_Size, // Size of markers (radius) + ImPlot3DProp_Offset, // Data index offset + ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX + ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags +}; + //----------------------------------------------------------------------------- // [SECTION] Callbacks //----------------------------------------------------------------------------- @@ -583,7 +599,88 @@ IMPLOT3D_API ImVec2 GetPlotRectSize(); IMPLOT3D_API ImDrawList* GetPlotDrawList(); //----------------------------------------------------------------------------- -// [SECTION] Styles +// [SECTION] Specs API +//----------------------------------------------------------------------------- + +// Plot item styling specification. Provide these to PlotX functions to override styling, specify +// offsetting or stride, or set optional flags. This struct can be used in the following ways: +// +// 1. By declaring and defining a struct instance: +// +// ImPlot3DSpec spec; +// spec.LineColor = ImVec4(1,0,0,1); +// spec.LineWeight = 2.0f; +// spec.Marker = ImPlot3DMarker_Circle; +// spec.Flags = ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments; +// ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, spec); +// +// 2. Inline using ImProp,value pairs (order does NOT matter): +// +// ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, { +// ImPlot3DProp_LineColor, ImVec4(1,0,0,1), +// ImPlot3DProp_LineWeight, 2.0f, +// ImPlot3DProp_Marker, ImPlot3DMarker_Circle, +// ImPlot3DProp_Flags, ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments +// }); +struct ImPlot3DSpec { + ImVec4 LineColor = IMPLOT3D_AUTO_COL; // Line color (applies to lines, marker edges); IMPLOT_AUTO_COL will use next Colormap color + float LineWeight = 1.0f; // Line weight in pixels (applies to lines, marker edges) + ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions, marker faces); IMPLOT_AUTO_COL will use next Colormap color + float FillAlpha = 1.0f; // Alpha multiplier (applies to FillColor) + ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type; specify ImPlot3DMarker_Auto to use the next unused marker + float Size = 4; // Size of markers (radius) *in pixels* + int Offset = 0; // Data index offset + int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX + ImPlot3DItemFlags Flags = + ImPlot3DItemFlags_None; // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags + + ImPlot3DSpec() {} + + // Construct a plot item specification from (ImPlot3DProp,value) pairs in any order + // E.g. ImPlot3DSpec(ImPlot3DProp_LineColor, my_color, ImPlot3DProp_Marker, ImPlot3DMarker_Circle) + template ImPlot3DSpec(Args... args) { + static_assert((sizeof...(Args)) % 2 == 0, "Odd number of arguments! You must provide (ImPlot3DProp,value) pairs!"); + SetProp(args...); + } + + // Set properties from (ImPlot3DProp,value) pairs in any order + // E.g. SetProp(ImPlot3DProp_LineColor, my_color, ImPlot3DProp_Marker, ImPlot3DMarker_Circle) + template void SetProp(ImPlot3DProp prop, Arg arg, Args... args) { + static_assert((sizeof...(Args)) % 2 == 0, "Odd number of arguments! You must provide (ImPlot3DProp,value) pairs!"); + SetProp(prop, arg); + SetProp(args...); + } + + // Set a property from a scalar value. + template void SetProp(ImPlot3DProp prop, T v) { + switch (prop) { + case ImPlot3DProp_LineColor: LineColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; + case ImPlot3DProp_LineWeight: LineWeight = (float)v; return; + case ImPlot3DProp_FillColor: FillColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; + case ImPlot3DProp_FillAlpha: FillAlpha = (float)v; return; + case ImPlot3DProp_Marker: Marker = (ImPlot3DMarker)v; return; + case ImPlot3DProp_Size: Size = (float)v; return; + case ImPlot3DProp_Offset: Offset = (int)v; return; + case ImPlot3DProp_Stride: Stride = (int)v; return; + case ImPlot3DProp_Flags: Flags = (ImPlot3DItemFlags)v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from scalar value!"); + } + + // Set a property from an ImVec4 value. + void SetProp(ImPlot3DProp prop, const ImVec4& v) { + switch (prop) { + case ImPlot3DProp_LineColor: LineColor = v; return; + case ImPlot3DProp_FillColor: FillColor = v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from ImVec4 value!"); + } +}; + +//----------------------------------------------------------------------------- +// [SECTION] Styles API (legacy) //----------------------------------------------------------------------------- // Get current style From aa71f53a6acff104a23c0c8c705463646133938b Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Mon, 2 Feb 2026 17:56:31 +0100 Subject: [PATCH 02/10] feat!: update begin item to use ImPlot3DSpec --- implot3d.cpp | 36 ++------ implot3d.h | 189 +++++++++++++++++++--------------------- implot3d_demo.cpp | 14 +-- implot3d_internal.h | 15 +--- implot3d_items.cpp | 206 +++++++++++++++++++++----------------------- 5 files changed, 203 insertions(+), 257 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index 99c198ed..680c1607 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -48,6 +48,9 @@ Below is a change-log of API breaking changes only. If you are using one of the When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot3d files. You can read releases logs https://github.com/brenocq/implot3d/releases for more details. +- 2026/02/02 (0.4) - Item colors removed from ImPlot3DCol_, it's no longer possible to push/pop individual item colors. +- 2026/02/02 (0.4) - ImPlot3DStyle::MarkerWeight was removed. The marker line weight is now controlled by ImPlot3DStyle::LineWeight. + - 2025/11/15 (0.3) - Renamed GetPlotPos() -> GetPlotRectPos() and GetPlotSize() -> GetPlotRectSize() for clarity in 3D context. Old functions are marked as deprecated and will be removed in v1.0. - 2025/10/22 (0.3) - **IMPORTANT** All plot coordinate types migrated from float to double precision to fix sorting issues with large values: @@ -2733,11 +2736,10 @@ struct ImPlot3DStyleVarInfo { static const ImPlot3DStyleVarInfo GPlot3DStyleVarInfo[] = { // Item style - {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, LineWeight)}, // ImPlot3DStyleVar_LineWeight - {ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlot3DStyle, Marker)}, // ImPlot3DStyleVar_Marker - {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, MarkerSize)}, // ImPlot3DStyleVar_MarkerSize - {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, MarkerWeight)}, // ImPlot3DStyleVar_MarkerWeight - {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, FillAlpha)}, // ImPlot3DStyleVar_FillAlpha + {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, LineWeight)}, // ImPlot3DStyleVar_LineWeight + {ImGuiDataType_S32, 1, (ImU32)offsetof(ImPlot3DStyle, Marker)}, // ImPlot3DStyleVar_Marker + {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, MarkerSize)}, // ImPlot3DStyleVar_MarkerSize + {ImGuiDataType_Float, 1, (ImU32)offsetof(ImPlot3DStyle, FillAlpha)}, // ImPlot3DStyleVar_FillAlpha // Plot style {ImGuiDataType_Float, 2, (ImU32)offsetof(ImPlot3DStyle, PlotDefaultSize)}, // ImPlot3DStyleVar_Plot3DDefaultSize @@ -2765,10 +2767,6 @@ void StyleColorsAuto(ImPlot3DStyle* dst) { ImPlot3DStyle* style = dst ? dst : &ImPlot3D::GetStyle(); ImVec4* colors = style->Colors; - colors[ImPlot3DCol_Line] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_Fill] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerOutline] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerFill] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_TitleText] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_InlayText] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_FrameBg] = IMPLOT3D_AUTO_COL; @@ -2786,10 +2784,6 @@ void StyleColorsDark(ImPlot3DStyle* dst) { ImPlot3DStyle* style = dst ? dst : &ImPlot3D::GetStyle(); ImVec4* colors = style->Colors; - colors[ImPlot3DCol_Line] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_Fill] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerOutline] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerFill] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_TitleText] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImPlot3DCol_InlayText] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImPlot3DCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f); @@ -2807,10 +2801,6 @@ void StyleColorsLight(ImPlot3DStyle* dst) { ImPlot3DStyle* style = dst ? dst : &ImPlot3D::GetStyle(); ImVec4* colors = style->Colors; - colors[ImPlot3DCol_Line] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_Fill] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerOutline] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerFill] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_TitleText] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); colors[ImPlot3DCol_InlayText] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); colors[ImPlot3DCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); @@ -2828,10 +2818,6 @@ void StyleColorsClassic(ImPlot3DStyle* dst) { ImPlot3DStyle* style = dst ? dst : &ImPlot3D::GetStyle(); ImVec4* colors = style->Colors; - colors[ImPlot3DCol_Line] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_Fill] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerOutline] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerFill] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_TitleText] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImPlot3DCol_InlayText] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImPlot3DCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f); @@ -3218,10 +3204,6 @@ bool IsColorAuto(ImPlot3DCol idx) { return IsColorAuto(GImPlot3D->Style.Colors[i ImVec4 GetAutoColor(ImPlot3DCol idx) { switch (idx) { - case ImPlot3DCol_Line: return IMPLOT3D_AUTO_COL; // Plot dependent - case ImPlot3DCol_Fill: return IMPLOT3D_AUTO_COL; // Plot dependent - case ImPlot3DCol_MarkerOutline: return IMPLOT3D_AUTO_COL; // Plot dependent - case ImPlot3DCol_MarkerFill: return IMPLOT3D_AUTO_COL; // Plot dependent case ImPlot3DCol_TitleText: return ImGui::GetStyleColorVec4(ImGuiCol_Text); case ImPlot3DCol_InlayText: return ImGui::GetStyleColorVec4(ImGuiCol_Text); case ImPlot3DCol_FrameBg: return ImGui::GetStyleColorVec4(ImGuiCol_FrameBg); @@ -3239,8 +3221,7 @@ ImVec4 GetAutoColor(ImPlot3DCol idx) { const char* GetStyleColorName(ImPlot3DCol idx) { static const char* color_names[ImPlot3DCol_COUNT] = { - "Line", "Fill", "MarkerOutline", "MarkerFill", "TitleText", "InlayText", "FrameBg", "PlotBg", - "PlotBorder", "LegendBg", "LegendBorder", "LegendText", "AxisText", "AxisGrid", "AxisTick", + "TitleText", "InlayText", "FrameBg", "PlotBg", "PlotBorder", "LegendBg", "LegendBorder", "LegendText", "AxisText", "AxisGrid", "AxisTick", }; return color_names[idx]; } @@ -3838,7 +3819,6 @@ ImPlot3DStyle::ImPlot3DStyle() { LineWeight = 1.0f; Marker = ImPlot3DMarker_None; MarkerSize = 4.0f; - MarkerWeight = 1.0f; FillAlpha = 1.0f; // Plot style PlotDefaultSize = ImVec2(400, 400); diff --git a/implot3d.h b/implot3d.h index 4b90a7c3..46587e48 100644 --- a/implot3d.h +++ b/implot3d.h @@ -13,6 +13,7 @@ // [SECTION] Macros and Defines // [SECTION] Forward declarations and basic types // [SECTION] Flags & Enumerations +// [SECTION] Specs API // [SECTION] Callbacks // [SECTION] Context // [SECTION] Begin/End Plot @@ -20,7 +21,6 @@ // [SECTION] Plot Items // [SECTION] Plot Utils // [SECTION] Miscellaneous -// [SECTION] Specs API // [SECTION] Styles API (legacy) // [SECTION] Demo // [SECTION] Debugging @@ -125,11 +125,6 @@ enum ImPlot3DCond_ { }; enum ImPlot3DCol_ { - // Item colors - ImPlot3DCol_Line = 0, // Line color - ImPlot3DCol_Fill, // Fill color - ImPlot3DCol_MarkerOutline, // Marker outline color - ImPlot3DCol_MarkerFill, // Marker fill color // Plot colors ImPlot3DCol_TitleText, // Title color ImPlot3DCol_InlayText, // Color for texts appearing inside of plots @@ -150,11 +145,10 @@ enum ImPlot3DCol_ { // Plot styling variables enum ImPlot3DStyleVar_ { // Item style - ImPlot3DStyleVar_LineWeight, // float, plot item line weight in pixels - ImPlot3DStyleVar_Marker, // int, marker specification - ImPlot3DStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") - ImPlot3DStyleVar_MarkerWeight, // float, plot outline weight of markers in pixels - ImPlot3DStyleVar_FillAlpha, // float, alpha modifier applied to all plot item fills + ImPlot3DStyleVar_LineWeight, // float, plot item line weight in pixels + ImPlot3DStyleVar_Marker, // int, marker specification + ImPlot3DStyleVar_MarkerSize, // float, marker size in pixels (roughly the marker's "radius") + ImPlot3DStyleVar_FillAlpha, // float, alpha modifier applied to all plot item fills // Plot style ImPlot3DStyleVar_PlotDefaultSize, // ImVec2, default size used when ImVec2(0,0) is passed to BeginPlot ImPlot3DStyleVar_PlotMinSize, // ImVec2, minimum size plot frame can be when shrunk @@ -353,6 +347,87 @@ enum ImPlot3DProp_ { ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags }; +//----------------------------------------------------------------------------- +// [SECTION] Specs API +//----------------------------------------------------------------------------- + +// Plot item styling specification. Provide these to PlotX functions to override styling, specify +// offsetting or stride, or set optional flags. This struct can be used in the following ways: +// +// 1. By declaring and defining a struct instance: +// +// ImPlot3DSpec spec; +// spec.LineColor = ImVec4(1,0,0,1); +// spec.LineWeight = 2.0f; +// spec.Marker = ImPlot3DMarker_Circle; +// spec.Flags = ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments; +// ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, spec); +// +// 2. Inline using ImProp,value pairs (order does NOT matter): +// +// ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, { +// ImPlot3DProp_LineColor, ImVec4(1,0,0,1), +// ImPlot3DProp_LineWeight, 2.0f, +// ImPlot3DProp_Marker, ImPlot3DMarker_Circle, +// ImPlot3DProp_Flags, ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments +// }); +struct ImPlot3DSpec { + ImVec4 LineColor = IMPLOT3D_AUTO_COL; // Line color (applies to lines, marker edges); IMPLOT_AUTO_COL will use next Colormap color + float LineWeight = 1.0f; // Line weight in pixels (applies to lines, marker edges) + ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions, marker faces); IMPLOT_AUTO_COL will use next Colormap color + float FillAlpha = IMPLOT3D_AUTO; // Alpha multiplier (applies to FillColor) + ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type; specify ImPlot3DMarker_Auto to use the next unused marker + float Size = IMPLOT3D_AUTO; // Size of markers (radius) *in pixels* + int Offset = 0; // Data index offset + int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX + ImPlot3DItemFlags Flags = + ImPlot3DItemFlags_None; // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags + + ImPlot3DSpec() {} + + // Construct a plot item specification from (ImPlot3DProp,value) pairs in any order + // E.g. ImPlot3DSpec(ImPlot3DProp_LineColor, my_color, ImPlot3DProp_Marker, ImPlot3DMarker_Circle) + template ImPlot3DSpec(Args... args) { + static_assert((sizeof...(Args)) % 2 == 0, "Odd number of arguments! You must provide (ImPlot3DProp,value) pairs!"); + SetProp(args...); + } + + // Set properties from (ImPlot3DProp,value) pairs in any order + // E.g. SetProp(ImPlot3DProp_LineColor, my_color, ImPlot3DProp_Marker, ImPlot3DMarker_Circle) + template void SetProp(ImPlot3DProp prop, Arg arg, Args... args) { + static_assert((sizeof...(Args)) % 2 == 0, "Odd number of arguments! You must provide (ImPlot3DProp,value) pairs!"); + SetProp(prop, arg); + SetProp(args...); + } + + // Set a property from a scalar value. + template void SetProp(ImPlot3DProp prop, T v) { + switch (prop) { + case ImPlot3DProp_LineColor: LineColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; + case ImPlot3DProp_LineWeight: LineWeight = (float)v; return; + case ImPlot3DProp_FillColor: FillColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; + case ImPlot3DProp_FillAlpha: FillAlpha = (float)v; return; + case ImPlot3DProp_Marker: Marker = (ImPlot3DMarker)v; return; + case ImPlot3DProp_Size: Size = (float)v; return; + case ImPlot3DProp_Offset: Offset = (int)v; return; + case ImPlot3DProp_Stride: Stride = (int)v; return; + case ImPlot3DProp_Flags: Flags = (ImPlot3DItemFlags)v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from scalar value!"); + } + + // Set a property from an ImVec4 value. + void SetProp(ImPlot3DProp prop, const ImVec4& v) { + switch (prop) { + case ImPlot3DProp_LineColor: LineColor = v; return; + case ImPlot3DProp_FillColor: FillColor = v; return; + default: break; + } + IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from ImVec4 value!"); + } +}; + //----------------------------------------------------------------------------- // [SECTION] Callbacks //----------------------------------------------------------------------------- @@ -508,7 +583,7 @@ IMPLOT3D_API void SetupLegend(ImPlot3DLocation location, ImPlot3DLegendFlags fla // struct Vector3f { float X, Y, Z; }; // ... // Vector3f data[42]; -// ImPlot3D::PlotLine("line", &data[0].X, &data[0].Y, &data[0].Z, 42, 0, 0, sizeof(Vector3f)); +// ImPlot3D::PlotLine("line", &data[0].X, &data[0].Y, &data[0].Z, 42, {ImPlot3DProp_Stride, sizeof(Vector2f)}); // // 2. If your data is in separate arrays or requires computation, you can copy/transform // it into temporary float or double arrays before plotting. @@ -598,87 +673,6 @@ IMPLOT3D_API ImVec2 GetPlotRectSize(); // Returns the ImDrawList used for rendering plot items. Use this to add custom rendering inside plots IMPLOT3D_API ImDrawList* GetPlotDrawList(); -//----------------------------------------------------------------------------- -// [SECTION] Specs API -//----------------------------------------------------------------------------- - -// Plot item styling specification. Provide these to PlotX functions to override styling, specify -// offsetting or stride, or set optional flags. This struct can be used in the following ways: -// -// 1. By declaring and defining a struct instance: -// -// ImPlot3DSpec spec; -// spec.LineColor = ImVec4(1,0,0,1); -// spec.LineWeight = 2.0f; -// spec.Marker = ImPlot3DMarker_Circle; -// spec.Flags = ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments; -// ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, spec); -// -// 2. Inline using ImProp,value pairs (order does NOT matter): -// -// ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, { -// ImPlot3DProp_LineColor, ImVec4(1,0,0,1), -// ImPlot3DProp_LineWeight, 2.0f, -// ImPlot3DProp_Marker, ImPlot3DMarker_Circle, -// ImPlot3DProp_Flags, ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments -// }); -struct ImPlot3DSpec { - ImVec4 LineColor = IMPLOT3D_AUTO_COL; // Line color (applies to lines, marker edges); IMPLOT_AUTO_COL will use next Colormap color - float LineWeight = 1.0f; // Line weight in pixels (applies to lines, marker edges) - ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions, marker faces); IMPLOT_AUTO_COL will use next Colormap color - float FillAlpha = 1.0f; // Alpha multiplier (applies to FillColor) - ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type; specify ImPlot3DMarker_Auto to use the next unused marker - float Size = 4; // Size of markers (radius) *in pixels* - int Offset = 0; // Data index offset - int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX - ImPlot3DItemFlags Flags = - ImPlot3DItemFlags_None; // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags - - ImPlot3DSpec() {} - - // Construct a plot item specification from (ImPlot3DProp,value) pairs in any order - // E.g. ImPlot3DSpec(ImPlot3DProp_LineColor, my_color, ImPlot3DProp_Marker, ImPlot3DMarker_Circle) - template ImPlot3DSpec(Args... args) { - static_assert((sizeof...(Args)) % 2 == 0, "Odd number of arguments! You must provide (ImPlot3DProp,value) pairs!"); - SetProp(args...); - } - - // Set properties from (ImPlot3DProp,value) pairs in any order - // E.g. SetProp(ImPlot3DProp_LineColor, my_color, ImPlot3DProp_Marker, ImPlot3DMarker_Circle) - template void SetProp(ImPlot3DProp prop, Arg arg, Args... args) { - static_assert((sizeof...(Args)) % 2 == 0, "Odd number of arguments! You must provide (ImPlot3DProp,value) pairs!"); - SetProp(prop, arg); - SetProp(args...); - } - - // Set a property from a scalar value. - template void SetProp(ImPlot3DProp prop, T v) { - switch (prop) { - case ImPlot3DProp_LineColor: LineColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; - case ImPlot3DProp_LineWeight: LineWeight = (float)v; return; - case ImPlot3DProp_FillColor: FillColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; - case ImPlot3DProp_FillAlpha: FillAlpha = (float)v; return; - case ImPlot3DProp_Marker: Marker = (ImPlot3DMarker)v; return; - case ImPlot3DProp_Size: Size = (float)v; return; - case ImPlot3DProp_Offset: Offset = (int)v; return; - case ImPlot3DProp_Stride: Stride = (int)v; return; - case ImPlot3DProp_Flags: Flags = (ImPlot3DItemFlags)v; return; - default: break; - } - IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from scalar value!"); - } - - // Set a property from an ImVec4 value. - void SetProp(ImPlot3DProp prop, const ImVec4& v) { - switch (prop) { - case ImPlot3DProp_LineColor: LineColor = v; return; - case ImPlot3DProp_FillColor: FillColor = v; return; - default: break; - } - IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from ImVec4 value!"); - } -}; - //----------------------------------------------------------------------------- // [SECTION] Styles API (legacy) //----------------------------------------------------------------------------- @@ -993,11 +987,10 @@ struct ImPlot3DQuat { struct ImPlot3DStyle { // Item style - float LineWeight; // Line weight in pixels - int Marker; // Default marker type (ImPlot3DMarker_None) - float MarkerSize; // Marker size in pixels (roughly the marker's "radius") - float MarkerWeight; // Marker outline weight in pixels - float FillAlpha; // Alpha modifier applied to plot fills + float LineWeight; // Line weight in pixels + int Marker; // Default marker type (ImPlot3DMarker_None) + float MarkerSize; // Marker size in pixels (roughly the marker's "radius") + float FillAlpha; // Alpha modifier applied to plot fills // Plot style ImVec2 PlotDefaultSize; // Default size used when ImVec2(0,0) is passed to BeginPlot ImVec2 PlotMinSize; // Minimum size plot frame can be when shrunk diff --git a/implot3d_demo.cpp b/implot3d_demo.cpp index 3b11099f..851b6e79 100644 --- a/implot3d_demo.cpp +++ b/implot3d_demo.cpp @@ -426,8 +426,8 @@ void DemoMeshPlots() { ImGui::ColorEdit4("Fill Color##Mesh", (float*)&fill_color); // Choose marker color - static ImVec4 marker_color = ImVec4(0.5f, 0.5f, 0.2f, 0.6f); - ImGui::ColorEdit4("Marker Color##Mesh", (float*)&marker_color); + // static ImVec4 marker_color = ImVec4(0.5f, 0.5f, 0.2f, 0.6f); + // ImGui::ColorEdit4("Marker Color##Mesh", (float*)&marker_color); // Mesh flags static ImPlot3DMeshFlags flags = ImPlot3DMeshFlags_NoMarkers; @@ -445,7 +445,7 @@ void DemoMeshPlots() { ImPlot3D::SetNextLineStyle(line_color); // Set marker style - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, marker_color, IMPLOT3D_AUTO, marker_color); + // ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, marker_color, IMPLOT3D_AUTO, marker_color); // Plot mesh if (mesh_id == 0) @@ -794,7 +794,7 @@ void DemoLegendOptions() { void DemoMarkersAndText() { static float mk_size = ImPlot3D::GetStyle().MarkerSize; - static float mk_weight = ImPlot3D::GetStyle().MarkerWeight; + static float mk_weight = ImPlot3D::GetStyle().LineWeight; ImGui::DragFloat("Marker Size", &mk_size, 0.1f, 2.0f, 10.0f, "%.2f px"); ImGui::DragFloat("Marker Weight", &mk_weight, 0.05f, 0.5f, 3.0f, "%.2f px"); @@ -1759,7 +1759,6 @@ void ShowStyleEditor(ImPlot3DStyle* ref) { ImGui::Text("Item Styling"); ImGui::SliderFloat("LineWeight", &style.LineWeight, 0.0f, 5.0f, "%.1f"); ImGui::SliderFloat("MarkerSize", &style.MarkerSize, 2.0f, 10.0f, "%.1f"); - ImGui::SliderFloat("MarkerWeight", &style.MarkerWeight, 0.0f, 5.0f, "%.1f"); ImGui::SliderFloat("FillAlpha", &style.FillAlpha, 0.0f, 1.0f, "%.2f"); ImGui::Text("Plot Styling"); ImGui::SliderFloat2("PlotDefaultSize", (float*)&style.PlotDefaultSize, 0.0f, 1000, "%.0f"); @@ -2076,10 +2075,6 @@ void StyleSeaborn() { ImPlot3DStyle& style = ImPlot3D::GetStyle(); ImVec4* colors = style.Colors; - colors[ImPlot3DCol_Line] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_Fill] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerOutline] = IMPLOT3D_AUTO_COL; - colors[ImPlot3DCol_MarkerFill] = IMPLOT3D_AUTO_COL; colors[ImPlot3DCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImPlot3DCol_PlotBg] = ImVec4(0.92f, 0.92f, 0.95f, 1.00f); colors[ImPlot3DCol_PlotBorder] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); @@ -2094,7 +2089,6 @@ void StyleSeaborn() { style.LineWeight = 1.5; style.Marker = ImPlot3DMarker_None; style.MarkerSize = 4; - style.MarkerWeight = 1; style.FillAlpha = 1.0f; style.PlotPadding = ImVec2(12, 12); style.LabelPadding = ImVec2(5, 5); diff --git a/implot3d_internal.h b/implot3d_internal.h index d1d22152..b2980174 100644 --- a/implot3d_internal.h +++ b/implot3d_internal.h @@ -177,12 +177,7 @@ struct ImDrawList3D { }; struct ImPlot3DNextItemData { - ImVec4 Colors[4]; // ImPlot3DCol_Line, ImPlot3DCol_Fill, ImPlot3DCol_MarkerOutline, ImPlot3DCol_MarkerFill, - float LineWeight; - ImPlot3DMarker Marker; - float MarkerSize; - float MarkerWeight; - float FillAlpha; + ImPlot3DSpec Spec; bool RenderLine; bool RenderFill; bool RenderMarkerLine; @@ -194,13 +189,7 @@ struct ImPlot3DNextItemData { ImPlot3DNextItemData() { Reset(); } void Reset() { - for (int i = 0; i < 4; i++) - Colors[i] = IMPLOT3D_AUTO_COL; - LineWeight = IMPLOT3D_AUTO; - Marker = IMPLOT3D_AUTO; - MarkerSize = IMPLOT3D_AUTO; - MarkerWeight = IMPLOT3D_AUTO; - FillAlpha = IMPLOT3D_AUTO; + Spec = ImPlot3DSpec(); RenderLine = false; RenderFill = false; RenderMarkerLine = true; diff --git a/implot3d_items.cpp b/implot3d_items.cpp index cb433150..a7bd2c54 100644 --- a/implot3d_items.cpp +++ b/implot3d_items.cpp @@ -138,7 +138,7 @@ namespace ImPlot3D { static const float ITEM_HIGHLIGHT_LINE_SCALE = 2.0f; static const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f; -bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolor_from) { +bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, const ImVec4& item_col) { ImPlot3DContext& gp = *GImPlot3D; IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotX() needs to be called between BeginPlot() and EndPlot()!"); @@ -147,6 +147,7 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolo ImPlot3DStyle& style = gp.Style; ImPlot3DNextItemData& n = gp.NextItemData; + ImPlot3DSpec& s = n.Spec; // Register item bool just_created; @@ -155,52 +156,33 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolo gp.CurrentItem = item; // Set/override item color - if (recolor_from != -1) { - if (!IsColorAuto(n.Colors[recolor_from])) - item->Color = ImGui::ColorConvertFloat4ToU32(n.Colors[recolor_from]); - else if (!IsColorAuto(gp.Style.Colors[recolor_from])) - item->Color = ImGui::ColorConvertFloat4ToU32(gp.Style.Colors[recolor_from]); - else if (just_created) - item->Color = NextColormapColorU32(); + if (!IsColorAuto(item_col)) { + item->Color = ImGui::ColorConvertFloat4ToU32(item_col); } else if (just_created) { item->Color = NextColormapColorU32(); } // Set next item color ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color); - n.IsAutoLine = IsColorAuto(n.Colors[ImPlot3DCol_Line]) && IsColorAuto(ImPlot3DCol_Line); - n.IsAutoFill = IsColorAuto(n.Colors[ImPlot3DCol_Fill]) && IsColorAuto(ImPlot3DCol_Fill); - n.Colors[ImPlot3DCol_Line] = IsColorAuto(n.Colors[ImPlot3DCol_Line]) - ? (IsColorAuto(ImPlot3DCol_Line) ? item_color : gp.Style.Colors[ImPlot3DCol_Line]) - : n.Colors[ImPlot3DCol_Line]; - n.Colors[ImPlot3DCol_Fill] = IsColorAuto(n.Colors[ImPlot3DCol_Fill]) - ? (IsColorAuto(ImPlot3DCol_Fill) ? item_color : gp.Style.Colors[ImPlot3DCol_Fill]) - : n.Colors[ImPlot3DCol_Fill]; - n.Colors[ImPlot3DCol_MarkerOutline] = - IsColorAuto(n.Colors[ImPlot3DCol_MarkerOutline]) - ? (IsColorAuto(ImPlot3DCol_MarkerOutline) ? n.Colors[ImPlot3DCol_Line] : gp.Style.Colors[ImPlot3DCol_MarkerOutline]) - : n.Colors[ImPlot3DCol_MarkerOutline]; - n.Colors[ImPlot3DCol_MarkerFill] = - IsColorAuto(n.Colors[ImPlot3DCol_MarkerFill]) - ? (IsColorAuto(ImPlot3DCol_MarkerFill) ? n.Colors[ImPlot3DCol_Line] : gp.Style.Colors[ImPlot3DCol_MarkerFill]) - : n.Colors[ImPlot3DCol_MarkerFill]; + n.IsAutoLine = IsColorAuto(s.LineColor); + n.IsAutoFill = IsColorAuto(s.FillColor); + s.LineColor = IsColorAuto(s.LineColor) ? item_color : s.LineColor; + s.FillColor = IsColorAuto(s.FillColor) ? s.LineColor : s.FillColor; // Set size & weight - n.LineWeight = n.LineWeight < 0.0f ? style.LineWeight : n.LineWeight; - n.Marker = n.Marker < 0 ? style.Marker : n.Marker; - n.MarkerSize = n.MarkerSize < 0.0f ? style.MarkerSize : n.MarkerSize; - n.MarkerWeight = n.MarkerWeight < 0.0f ? style.MarkerWeight : n.MarkerWeight; - n.FillAlpha = n.FillAlpha < 0 ? gp.Style.FillAlpha : n.FillAlpha; + s.LineWeight = s.LineWeight < 0.0f ? style.LineWeight : s.LineWeight; + s.Marker = s.Marker < 0 ? style.Marker : s.Marker; + s.Size = s.Size < 0.0f ? style.MarkerSize : s.Size; + s.FillAlpha = s.FillAlpha < 0 ? gp.Style.FillAlpha : s.FillAlpha; // Apply alpha modifiers - n.Colors[ImPlot3DCol_Fill].w *= n.FillAlpha; - n.Colors[ImPlot3DCol_MarkerFill].w *= n.FillAlpha; + s.FillColor.w *= s.FillAlpha; // Set render flags - n.RenderLine = n.Colors[ImPlot3DCol_Line].w > 0 && n.LineWeight > 0; - n.RenderFill = n.Colors[ImPlot3DCol_Fill].w > 0; - n.RenderMarkerFill = n.Colors[ImPlot3DCol_MarkerFill].w > 0; - n.RenderMarkerLine = n.Colors[ImPlot3DCol_MarkerOutline].w > 0 && n.MarkerWeight > 0; + n.RenderLine = s.LineColor.w > 0 && s.LineWeight > 0; + n.RenderFill = s.FillColor.w > 0; + n.RenderMarkerLine = s.LineColor.w > 0 && s.LineWeight > 0; + n.RenderMarkerFill = s.FillColor.w > 0; // Don't render if item is hidden if (!item->Show) { @@ -210,9 +192,8 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolo // Legend hover highlight if (item->LegendHovered) { if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlot3DLegendFlags_NoHighlightItem)) { - n.LineWeight *= ITEM_HIGHLIGHT_LINE_SCALE; - n.MarkerSize *= ITEM_HIGHLIGHT_MARK_SCALE; - n.MarkerWeight *= ITEM_HIGHLIGHT_LINE_SCALE; + s.LineWeight *= ITEM_HIGHLIGHT_LINE_SCALE; + s.Size *= ITEM_HIGHLIGHT_MARK_SCALE; } } } @@ -221,8 +202,8 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, ImPlot3DCol recolo } template -bool BeginItemEx(const char* label_id, const _Getter& getter, ImPlot3DItemFlags flags = 0, ImPlot3DCol recolor_from = IMPLOT3D_AUTO) { - if (BeginItem(label_id, flags, recolor_from)) { +bool BeginItemEx(const char* label_id, const _Getter& getter, ImPlot3DItemFlags flags = 0, const ImVec4& color = IMPLOT3D_AUTO_COL) { + if (BeginItem(label_id, flags, color)) { ImPlot3DContext& gp = *GImPlot3D; ImPlot3DPlot& plot = *gp.CurrentPlot; if (plot.FitThisFrame && !ImHasFlag(flags, ImPlot3DItemFlags_NoFit)) { @@ -280,25 +261,28 @@ void BustItemCache() { void SetNextLineStyle(const ImVec4& col, float weight) { ImPlot3DContext& gp = *GImPlot3D; ImPlot3DNextItemData& n = gp.NextItemData; - n.Colors[ImPlot3DCol_Line] = col; - n.LineWeight = weight; + ImPlot3DSpec& spec = n.Spec; + spec.LineColor = col; + spec.LineWeight = weight; } void SetNextFillStyle(const ImVec4& col, float alpha) { ImPlot3DContext& gp = *GImPlot3D; ImPlot3DNextItemData& n = gp.NextItemData; - n.Colors[ImPlot3DCol_Fill] = col; - n.FillAlpha = alpha; + ImPlot3DSpec& spec = n.Spec; + spec.FillColor = col; + spec.FillAlpha = alpha; } void SetNextMarkerStyle(ImPlot3DMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) { ImPlot3DContext& gp = *GImPlot3D; ImPlot3DNextItemData& n = gp.NextItemData; - n.Marker = marker; - n.Colors[ImPlot3DCol_MarkerFill] = fill; - n.MarkerSize = size; - n.Colors[ImPlot3DCol_MarkerOutline] = outline; - n.MarkerWeight = weight; + ImPlot3DSpec& spec = n.Spec; + spec.Marker = marker; + spec.FillColor = fill; + spec.Size = size; + spec.LineColor = outline; + spec.LineWeight = weight; } //----------------------------------------------------------------------------- @@ -814,7 +798,7 @@ template struct RendererSurfaceFill : RendererBase { ImU32 cols[4] = {Col, Col, Col, Col}; const ImPlot3DNextItemData& n = GetItemData(); if (n.IsAutoFill) { - float alpha = GImPlot3D->NextItemData.FillAlpha; + float alpha = GImPlot3D->NextItemData.Spec.FillAlpha; double min = Min; double max = Max; if (ScaleMin != 0.0 || ScaleMax != 0.0) { @@ -1154,13 +1138,14 @@ template void RenderMarkers(const _Getter& getter, ImPlot3DMa //----------------------------------------------------------------------------- template void PlotScatterEx(const char* label_id, const Getter& getter, ImPlot3DScatterFlags flags) { - if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_MarkerOutline)) { - const ImPlot3DNextItemData& n = GetItemData(); - ImPlot3DMarker marker = n.Marker == ImPlot3DMarker_None ? ImPlot3DMarker_Circle : n.Marker; - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]); - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]); + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItemEx(label_id, getter, flags, s.LineColor)) { + ImPlot3DMarker marker = s.Marker == ImPlot3DMarker_None ? ImPlot3DMarker_Circle : s.Marker; + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); if (marker != ImPlot3DMarker_None) - RenderMarkers(getter, marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight); + RenderMarkers(getter, marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); EndItem(); } } @@ -1185,30 +1170,31 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() //----------------------------------------------------------------------------- template void PlotLineEx(const char* label_id, const _Getter& getter, ImPlot3DLineFlags flags) { - if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Line)) { - const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItemEx(label_id, getter, flags, s.LineColor)) { if (getter.Count >= 2 && n.RenderLine) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]); + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); if (ImHasFlag(flags, ImPlot3DLineFlags_Segments)) { - RenderPrimitives(getter, col_line, n.LineWeight); + RenderPrimitives(getter, col_line, s.LineWeight); } else if (ImHasFlag(flags, ImPlot3DLineFlags_Loop)) { if (ImHasFlag(flags, ImPlot3DLineFlags_SkipNaN)) - RenderPrimitives(GetterLoop<_Getter>(getter), col_line, n.LineWeight); + RenderPrimitives(GetterLoop<_Getter>(getter), col_line, s.LineWeight); else - RenderPrimitives(GetterLoop<_Getter>(getter), col_line, n.LineWeight); + RenderPrimitives(GetterLoop<_Getter>(getter), col_line, s.LineWeight); } else { if (ImHasFlag(flags, ImPlot3DLineFlags_SkipNaN)) - RenderPrimitives(getter, col_line, n.LineWeight); + RenderPrimitives(getter, col_line, s.LineWeight); else - RenderPrimitives(getter, col_line, n.LineWeight); + RenderPrimitives(getter, col_line, s.LineWeight); } } // Render markers - if (n.Marker != ImPlot3DMarker_None) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]); - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]); - RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight); + if (s.Marker != ImPlot3DMarker_None) { + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); } @@ -1233,26 +1219,26 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() //----------------------------------------------------------------------------- template void PlotTriangleEx(const char* label_id, const _Getter& getter, ImPlot3DTriangleFlags flags) { - if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) { - const ImPlot3DNextItemData& n = GetItemData(); - + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItemEx(label_id, getter, flags, s.FillColor)) { // Render fill if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoFill)) { - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter, col_fill); } // Render lines if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoLines)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]); - RenderPrimitives(GetterTriangleLines<_Getter>(getter), col_line, n.LineWeight); + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + RenderPrimitives(GetterTriangleLines<_Getter>(getter), col_line, s.LineWeight); } // Render markers - if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]); - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]); - RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight); + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoMarkers)) { + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1279,26 +1265,26 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() //----------------------------------------------------------------------------- template void PlotQuadEx(const char* label_id, const _Getter& getter, ImPlot3DQuadFlags flags) { - if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) { - const ImPlot3DNextItemData& n = GetItemData(); - + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItemEx(label_id, getter, flags, s.FillColor)) { // Render fill if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(flags, ImPlot3DQuadFlags_NoFill)) { - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter, col_fill); } // Render lines if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DQuadFlags_NoLines)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]); - RenderPrimitives(GetterQuadLines<_Getter>(getter), col_line, n.LineWeight); + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + RenderPrimitives(GetterQuadLines<_Getter>(getter), col_line, s.LineWeight); } // Render markers - if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DQuadFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]); - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]); - RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight); + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DQuadFlags_NoMarkers)) { + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1325,26 +1311,26 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() template void PlotSurfaceEx(const char* label_id, const _Getter& getter, int x_count, int y_count, double scale_min, double scale_max, ImPlot3DSurfaceFlags flags) { - if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) { - const ImPlot3DNextItemData& n = GetItemData(); - + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItemEx(label_id, getter, flags, s.FillColor)) { // Render fill if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoFill)) { - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter, x_count, y_count, col_fill, scale_min, scale_max); } // Render lines if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoLines)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]); - RenderPrimitives(GetterSurfaceLines<_Getter>(getter, x_count, y_count), col_line, n.LineWeight); + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + RenderPrimitives(GetterSurfaceLines<_Getter>(getter, x_count, y_count), col_line, s.LineWeight); } // Render markers - if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]); - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]); - RenderMarkers<_Getter>(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight); + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoMarkers)) { + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1374,26 +1360,28 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, ImPlot3DMeshFlags flags) { Getter3DPoints getter(vtx, vtx_count); // Get vertices GetterMeshTriangles getter_triangles(vtx, idx, idx_count); // Get triangle vertices - if (BeginItemEx(label_id, getter, flags, ImPlot3DCol_Fill)) { - const ImPlot3DNextItemData& n = GetItemData(); + + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItemEx(label_id, getter, flags, s.FillColor)) { // Render fill if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(flags, ImPlot3DMeshFlags_NoFill)) { - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Fill]); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter_triangles, col_fill); } // Render lines if (getter.Count >= 2 && n.RenderLine && !n.IsAutoLine && !ImHasFlag(flags, ImPlot3DMeshFlags_NoLines)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_Line]); - RenderPrimitives(GetterTriangleLines(getter_triangles), col_line, n.LineWeight); + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + RenderPrimitives(GetterTriangleLines(getter_triangles), col_line, s.LineWeight); } // Render markers - if (n.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DMeshFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerOutline]); - const ImU32 col_fill = ImGui::GetColorU32(n.Colors[ImPlot3DCol_MarkerFill]); - RenderMarkers(getter, n.Marker, n.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, n.MarkerWeight); + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DMeshFlags_NoMarkers)) { + const ImU32 col_line = ImGui::GetColorU32(s.LineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + RenderMarkers(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1479,7 +1467,9 @@ void PlotText(const char* text, double x, double y, double z, double angle, cons } void PlotDummy(const char* label_id, ImPlot3DDummyFlags flags) { - if (BeginItem(label_id, flags, ImPlot3DCol_Line)) + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (BeginItem(label_id, flags, s.LineColor)) EndItem(); } From 6f3bdf52c8058eca1f30879ed9015d3b4eece97d Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Tue, 3 Feb 2026 14:45:47 +0100 Subject: [PATCH 03/10] feat!: update public API to use ImPlot3DSpec --- implot3d.cpp | 52 +++++++++++ implot3d.h | 34 +++---- implot3d_demo.cpp | 154 +++++++++++++++++-------------- implot3d_internal.h | 22 ++++- implot3d_items.cpp | 218 +++++++++++++++++++++----------------------- 5 files changed, 275 insertions(+), 205 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index 680c1607..01dcdfda 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -48,6 +48,50 @@ Below is a change-log of API breaking changes only. If you are using one of the When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot3d files. You can read releases logs https://github.com/brenocq/implot3d/releases for more details. +- 2026/02/03 (0.4) - ImPlotSpec was made the default and _only_ way of styling plot items. The SetNextXXXStyle functions have been removed. + - SetNextLineStyle has been removed, styling should be set via ImPlot3DSpec. + - Before: + ``` + ImPlot3D::SetNextLineStyle(line_color, line_weight); + ImPlot3D::PlotLine(xs, ys, zs, count); + ``` + - After + ``` + ImPlot3DSpec spec; + spec.LineColor = line_color; + spec.LineWeight = line_weight; + ImPlot3D::PlotLine(xs, ys, zs, count, spec); + ``` + - SetNextFillStyle has been removed, styling should be set via ImPlot3DSpec. + - Before: + ``` + ImPlot3D::SetNextFillStyle(fill_color, fill_alpha); + ImPlot3D::PlotTriangle(xs, ys, zs, count); + ``` + - After + ``` + ImPlot3DSpec spec; + spec.FillColor = fill_color; + spec.FillAlpha = fill_alpha; + ImPlot3D::PlotLine(xs, ys, zs, count, spec); + ``` + - SetNextMarkerStyle has been removed, styling should be set via ImPlot3DSpec. + - Before: + ``` + ImPlot3D::SetNextMarkerStyle(marker, marker_size, fill_color, line_weight, marker_outline_color); + ImPlot3D::PlotScatter(xs, ys, zs, count); + ``` + - After + ``` + ImPlot3DSpec spec; + spec.Marker = marker; + spec.Size = marker_size; + spec.FillColor = fill_color; + spec.LineWeight = line_weight; + spec.LineColor = marker_outline_color; + ImPlot3D::PlotLine(xs, ys, zs, count, spec); + ``` + - Flags, Offset and Stride should also be set via ImPlot3DSpec now. - 2026/02/02 (0.4) - Item colors removed from ImPlot3DCol_, it's no longer possible to push/pop individual item colors. - 2026/02/02 (0.4) - ImPlot3DStyle::MarkerWeight was removed. The marker line weight is now controlled by ImPlot3DStyle::LineWeight. @@ -2956,6 +3000,14 @@ ImVec4 GetStyleColorVec4(ImPlot3DCol idx) { return IsColorAuto(idx) ? GetAutoCol ImU32 GetStyleColorU32(ImPlot3DCol idx) { return ImGui::ColorConvertFloat4ToU32(ImPlot3D::GetStyleColorVec4(idx)); } +ImPlot3DMarker NextMarker() { + ImPlot3DContext& gp = *GImPlot3D; + IM_ASSERT_USER_ERROR(gp.CurrentItems != nullptr, "NextMarker() needs to be called between BeginPlot() and EndPlot()!"); + const int idx = gp.CurrentItems->MarkerIdx % ImPlot3DMarker_COUNT; + ++gp.CurrentItems->MarkerIdx; + return idx; +} + //------------------------------------------------------------------------------ // [SECTION] Colormaps //------------------------------------------------------------------------------ diff --git a/implot3d.h b/implot3d.h index 46587e48..91698c6d 100644 --- a/implot3d.h +++ b/implot3d.h @@ -592,30 +592,26 @@ IMPLOT3D_API void SetupLegend(ImPlot3DLocation location, ImPlot3DLegendFlags fla // if you try plotting extremely large 64-bit integral types. Proceed with caution! // Plots a scatter plot in 3D. Points are rendered as markers at the specified coordinates -IMPLOT3D_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags = 0, int offset = 0, - int stride = sizeof(T)); +IMPLOT3D_TMP void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots a line in 3D. Consecutive points are connected with line segments -IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags = 0, int offset = 0, - int stride = sizeof(T)); +IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots triangles in 3D. Every 3 consecutive points define a triangle -IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags = 0, - int offset = 0, int stride = sizeof(T)); +IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots quads in 3D. Every 4 consecutive points define a quadrilateral -IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags = 0, int offset = 0, - int stride = sizeof(T)); +IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plot the surface defined by a grid of vertices. The grid is defined by the x and y arrays, and the z array contains the height of each vertex. A // total of x_count * y_count vertices are expected for each array. Leave #scale_min and #scale_max both at 0 for automatic color scaling, or set them // to a predefined range IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min = 0.0, - double scale_max = 0.0, ImPlot3DSurfaceFlags flags = 0, int offset = 0, int stride = sizeof(T)); + double scale_max = 0.0, const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots a 3D mesh given vertex positions and indices. Triangles are defined by the index buffer (every 3 indices form a triangle) IMPLOT3D_API void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, - ImPlot3DMeshFlags flags = 0); + const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots a rectangular image in 3D defined by its center and two direction vectors (axes). // #center is the center of the rectangle in plot coordinates. @@ -625,7 +621,7 @@ IMPLOT3D_API void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const // #tint_col can be used to tint the image. IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& center, const ImPlot3DPoint& axis_u, const ImPlot3DPoint& axis_v, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), - const ImVec4& tint_col = ImVec4(1, 1, 1, 1), ImPlot3DImageFlags flags = 0); + const ImVec4& tint_col = ImVec4(1, 1, 1, 1), const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots an image using four arbitrary 3D points that define a quad in space. // Each corner (p0 to p3) corresponds to a corner in the image, and #uv0 to #uv3 are the texture coordinates for each. @@ -635,13 +631,13 @@ IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const Im IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& p0, const ImPlot3DPoint& p1, const ImPlot3DPoint& p2, const ImPlot3DPoint& p3, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 0), const ImVec2& uv2 = ImVec2(1, 1), const ImVec2& uv3 = ImVec2(0, 1), const ImVec4& tint_col = ImVec4(1, 1, 1, 1), - ImPlot3DImageFlags flags = 0); + const ImPlot3DSpec& spec = ImPlot3DSpec()); // Plots a centered text label at point x,y,z with optional rotation angle (in radians) and pixel offset IMPLOT3D_API void PlotText(const char* text, double x, double y, double z, double angle = 0.0, const ImVec2& pix_offset = ImVec2(0, 0)); // Plots a dummy item (can be used to modify legend entry appearance when called after plotting an item, or add a dummy legend entry) -IMPLOT3D_API void PlotDummy(const char* label_id, ImPlot3DDummyFlags flags = 0); +IMPLOT3D_API void PlotDummy(const char* label_id, const ImPlot3DSpec& spec = ImPlot3DSpec()); //----------------------------------------------------------------------------- // [SECTION] Plot Utils @@ -702,18 +698,13 @@ IMPLOT3D_API void PushStyleVar(ImPlot3DStyleVar idx, const ImVec2& val); // Undo temporary style variable modification(s). Undo multiple pushes at once by increasing count IMPLOT3D_API void PopStyleVar(int count = 1); -// Set the line color and weight for the next item only -IMPLOT3D_API void SetNextLineStyle(const ImVec4& col = IMPLOT3D_AUTO_COL, float weight = IMPLOT3D_AUTO); -// Set the fill color for the next item only -IMPLOT3D_API void SetNextFillStyle(const ImVec4& col = IMPLOT3D_AUTO_COL, float alpha_mod = IMPLOT3D_AUTO); -// Set the marker style for the next item only -IMPLOT3D_API void SetNextMarkerStyle(ImPlot3DMarker marker = IMPLOT3D_AUTO, float size = IMPLOT3D_AUTO, const ImVec4& fill = IMPLOT3D_AUTO_COL, - float weight = IMPLOT3D_AUTO, const ImVec4& outline = IMPLOT3D_AUTO_COL); - // Get color IMPLOT3D_API ImVec4 GetStyleColorVec4(ImPlot3DCol idx); IMPLOT3D_API ImU32 GetStyleColorU32(ImPlot3DCol idx); +// Returns the next marker and advances the marker for the current plot. You need to call this between Begin/EndPlot! +IMPLOT3D_API ImPlot3DMarker NextMarker(); + //----------------------------------------------------------------------------- // [SECTION] Colormaps //----------------------------------------------------------------------------- @@ -725,7 +716,6 @@ IMPLOT3D_API ImU32 GetStyleColorU32(ImPlot3DCol idx); // Colormap data will be ignored and a custom color will be used if you have done one of the following: // 1) Modified an item style color in your ImPlot3DStyle to anything other than IMPLOT3D_AUTO_COL. -// 3) Set the next item style with a SetNextXXXStyle function. // Add a new colormap. The color data will be copied. The colormap can be used by pushing either the returned index or the // string name with PushColormap. The colormap name must be unique and the size must be greater than 1. You will receive diff --git a/implot3d_demo.cpp b/implot3d_demo.cpp index 851b6e79..b2c99058 100644 --- a/implot3d_demo.cpp +++ b/implot3d_demo.cpp @@ -121,8 +121,7 @@ void DemoLinePlots() { if (ImPlot3D::BeginPlot("Line Plots")) { ImPlot3D::SetupAxes("x", "y", "z"); ImPlot3D::PlotLine("f(x)", xs1, ys1, zs1, 1001); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Circle); - ImPlot3D::PlotLine("g(x)", xs2, ys2, zs2, 20, ImPlot3DLineFlags_Segments); + ImPlot3D::PlotLine("g(x)", xs2, ys2, zs2, 20, {ImPlot3DProp_Marker, ImPlot3DMarker_Circle, ImPlot3DProp_Flags, ImPlot3DLineFlags_Segments}); ImPlot3D::EndPlot(); } } @@ -144,10 +143,13 @@ void DemoScatterPlots() { if (ImPlot3D::BeginPlot("Scatter Plots")) { ImPlot3D::PlotScatter("Data 1", xs1, ys1, zs1, 100); - ImPlot3D::PushStyleVar(ImPlot3DStyleVar_FillAlpha, 0.25f); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 6, ImPlot3D::GetColormapColor(1), IMPLOT3D_AUTO, ImPlot3D::GetColormapColor(1)); - ImPlot3D::PlotScatter("Data 2", xs2, ys2, zs2, 50); - ImPlot3D::PopStyleVar(); + ImPlot3DSpec spec; + spec.Marker = ImPlot3DMarker_Square; + spec.Size = 6; + spec.LineColor = ImPlot3D::GetColormapColor(1); + spec.FillColor = ImPlot3D::GetColormapColor(1); + spec.FillAlpha = 0.25f; + ImPlot3D::PlotScatter("Data 2", xs2, ys2, zs2, 50, spec); ImPlot3D::EndPlot(); } } @@ -224,12 +226,15 @@ void DemoTrianglePlots() { ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -0.5, 1.5); // Setup pyramid colors - ImPlot3D::SetNextFillStyle(ImPlot3D::GetColormapColor(0)); - ImPlot3D::SetNextLineStyle(ImPlot3D::GetColormapColor(1), 2); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, ImPlot3D::GetColormapColor(2), IMPLOT3D_AUTO, ImPlot3D::GetColormapColor(2)); + ImPlot3DSpec spec; + spec.FillColor = ImPlot3D::GetColormapColor(0); + spec.LineColor = ImPlot3D::GetColormapColor(1); + spec.Marker = ImPlot3DMarker_Square; + spec.Size = 3; + spec.Flags = flags; // Plot pyramid - ImPlot3D::PlotTriangle("Pyramid", xs, ys, zs, 6 * 3, flags); // 6 triangles, 3 vertices each = 18 + ImPlot3D::PlotTriangle("Pyramid", xs, ys, zs, 6 * 3, spec); // 6 triangles, 3 vertices each = 18 ImPlot3D::EndPlot(); } } @@ -287,26 +292,28 @@ void DemoQuadPlots() { if (ImPlot3D::BeginPlot("Quad Plots")) { ImPlot3D::SetupAxesLimits(-1.5, 1.5, -1.5, 1.5, -1.5, 1.5); + ImPlot3DSpec spec; + spec.Marker = ImPlot3DMarker_Square; + spec.Size = 3; + spec.Flags = flags; + // Render +x and -x faces static ImVec4 colorX(0.8f, 0.2f, 0.2f, 0.8f); // Red - ImPlot3D::SetNextFillStyle(colorX); - ImPlot3D::SetNextLineStyle(colorX, 2); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorX, IMPLOT3D_AUTO, colorX); - ImPlot3D::PlotQuad("X", &xs[0], &ys[0], &zs[0], 8, flags); + spec.FillColor = colorX; + spec.LineColor = colorX; + ImPlot3D::PlotQuad("X", &xs[0], &ys[0], &zs[0], 8, spec); // Render +y and -y faces static ImVec4 colorY(0.2f, 0.8f, 0.2f, 0.8f); // Green - ImPlot3D::SetNextFillStyle(colorY); - ImPlot3D::SetNextLineStyle(colorY, 2); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorY, IMPLOT3D_AUTO, colorY); - ImPlot3D::PlotQuad("Y", &xs[8], &ys[8], &zs[8], 8, flags); + spec.FillColor = colorY; + spec.LineColor = colorY; + ImPlot3D::PlotQuad("Y", &xs[8], &ys[8], &zs[8], 8, spec); // Render +z and -z faces static ImVec4 colorZ(0.2f, 0.2f, 0.8f, 0.8f); // Blue - ImPlot3D::SetNextFillStyle(colorZ); - ImPlot3D::SetNextLineStyle(colorZ, 2); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, colorZ, IMPLOT3D_AUTO, colorZ); - ImPlot3D::PlotQuad("Z", &xs[16], &ys[16], &zs[16], 8, flags); + spec.FillColor = colorZ; + spec.LineColor = colorZ; + ImPlot3D::PlotQuad("Z", &xs[16], &ys[16], &zs[16], 8, spec); ImPlot3D::EndPlot(); } @@ -388,25 +395,21 @@ void DemoSurfacePlots() { if (ImPlot3D::BeginPlot("Surface Plots", ImVec2(-1, 0), ImPlot3DFlags_NoClip)) { ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1.5, 1.5); - // Set fill style - ImPlot3D::PushStyleVar(ImPlot3DStyleVar_FillAlpha, 0.8f); + ImPlot3DSpec spec; + spec.FillAlpha = 0.8f; + spec.Flags = flags; + spec.Marker = ImPlot3DMarker_Square; + spec.LineColor = ImPlot3D::GetColormapColor(1); if (selected_fill == 0) - ImPlot3D::SetNextFillStyle(solid_color); - - // Set line style - ImPlot3D::SetNextLineStyle(ImPlot3D::GetColormapColor(1)); - - // Set marker style - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, IMPLOT3D_AUTO, ImPlot3D::GetColormapColor(2)); + spec.FillColor = solid_color; // Plot the surface if (custom_range) - ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, (double)range_min, (double)range_max, flags); + ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, (double)range_min, (double)range_max, spec); else - ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, 0.0, 0.0, flags); + ImPlot3D::PlotSurface("Wave Surface", xs, ys, zs, N, N, 0.0, 0.0, spec); // End the plot - ImPlot3D::PopStyleVar(); ImPlot3D::EndPlot(); } if (selected_fill == 1) @@ -438,22 +441,23 @@ void DemoMeshPlots() { if (ImPlot3D::BeginPlot("Mesh Plots")) { ImPlot3D::SetupAxesLimits(-1, 1, -1, 1, -1, 1); + ImPlot3DSpec spec; + spec.Flags = flags; // Set fill style - ImPlot3D::SetNextFillStyle(fill_color); - + spec.FillColor = fill_color; // Set line style - ImPlot3D::SetNextLineStyle(line_color); - + spec.LineColor = line_color; // Set marker style - // ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square, 3, marker_color, IMPLOT3D_AUTO, marker_color); + spec.Marker = ImPlot3DMarker_Square; + spec.Size = 3.0f; // Plot mesh if (mesh_id == 0) - ImPlot3D::PlotMesh("Duck", duck_vtx, duck_idx, DUCK_VTX_COUNT, DUCK_IDX_COUNT, flags); + ImPlot3D::PlotMesh("Duck", duck_vtx, duck_idx, DUCK_VTX_COUNT, DUCK_IDX_COUNT, spec); else if (mesh_id == 1) - ImPlot3D::PlotMesh("Sphere", sphere_vtx, sphere_idx, SPHERE_VTX_COUNT, SPHERE_IDX_COUNT, flags); + ImPlot3D::PlotMesh("Sphere", sphere_vtx, sphere_idx, SPHERE_VTX_COUNT, SPHERE_IDX_COUNT, spec); else if (mesh_id == 2) - ImPlot3D::PlotMesh("Cube", cube_vtx, cube_idx, CUBE_VTX_COUNT, CUBE_IDX_COUNT, flags); + ImPlot3D::PlotMesh("Cube", cube_vtx, cube_idx, CUBE_VTX_COUNT, CUBE_IDX_COUNT, spec); ImPlot3D::EndPlot(); } @@ -576,7 +580,8 @@ void DemoRealtimePlots() { ImPlot3D::SetupAxisLimits(ImAxis3D_X, t - 10.0, t, ImPlot3DCond_Always); ImPlot3D::SetupAxisLimits(ImAxis3D_Y, -400, 400, ImPlot3DCond_Once); ImPlot3D::SetupAxisLimits(ImAxis3D_Z, -400, 400, ImPlot3DCond_Once); - ImPlot3D::PlotLine("Mouse", &sdata1.Data[0], &sdata2.Data[0], &sdata3.Data[0], sdata1.Data.size(), 0, sdata1.Offset, sizeof(float)); + ImPlot3D::PlotLine("Mouse", &sdata1.Data[0], &sdata2.Data[0], &sdata3.Data[0], sdata1.Data.size(), + {ImPlot3DProp_Offset, sdata1.Offset, ImPlot3DProp_Stride, sizeof(float)}); ImPlot3D::EndPlot(); } } @@ -710,8 +715,10 @@ void DemoOffsetAndStride() { char buff[32]; for (int s = 0; s < k_spirals; ++s) { snprintf(buff, sizeof(buff), "Spiral %d", s); - ImPlot3D::PlotLine(buff, &interleaved_data[s * 3 + 0], &interleaved_data[s * 3 + 1], &interleaved_data[s * 3 + 2], k_points_per, 0, - offset, 3 * k_spirals * sizeof(double)); + ImPlot3DSpec spec; + spec.Offset = offset; + spec.Stride = 3 * k_spirals * sizeof(double); + ImPlot3D::PlotLine(buff, &interleaved_data[s * 3 + 0], &interleaved_data[s * 3 + 1], &interleaved_data[s * 3 + 2], k_points_per, spec); } ImPlot3D::EndPlot(); ImPlot3D::PopColormap(); @@ -814,8 +821,7 @@ void DemoMarkersAndText() { ys[1] = ys[0] + ImSin(zs[0] / float(ImPlot3DMarker_COUNT) * 2 * IM_PI) * 0.5f; ImGui::PushID(m); - ImPlot3D::SetNextMarkerStyle(m, mk_size, IMPLOT3D_AUTO_COL, mk_weight); - ImPlot3D::PlotLine("##Filled", xs, ys, zs, 2); + ImPlot3D::PlotLine("##Filled", xs, ys, zs, 2, {ImPlot3DProp_Marker, m, ImPlot3DProp_Size, mk_size, ImPlot3DProp_LineWeight, mk_weight}); ImGui::PopID(); zs[0]--; zs[1]--; @@ -832,8 +838,9 @@ void DemoMarkersAndText() { ys[1] = ys[0] - ImSin(zs[0] / float(ImPlot3DMarker_COUNT) * 2 * IM_PI) * 0.5f; ImGui::PushID(m); - ImPlot3D::SetNextMarkerStyle(m, mk_size, ImVec4(0, 0, 0, 0), mk_weight); - ImPlot3D::PlotLine("##Open", xs, ys, zs, 2); + ImPlot3D::PlotLine( + "##Open", xs, ys, zs, 2, + {ImPlot3DProp_Marker, m, ImPlot3DProp_Size, mk_size, ImPlot3DProp_LineWeight, mk_weight, ImPlot3DProp_FillColor, ImVec4(0, 0, 0, 0)}); ImGui::PopID(); zs[0]--; zs[1]--; @@ -866,8 +873,7 @@ void DemoNaNValues() { ImGui::CheckboxFlags("Skip NaN", (unsigned int*)&flags, ImPlot3DLineFlags_SkipNaN); if (ImPlot3D::BeginPlot("##NaNValues")) { - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Square); - ImPlot3D::PlotLine("Line", data1, data2, data3, 5, flags); + ImPlot3D::PlotLine("Line", data1, data2, data3, 5, {ImPlot3DProp_Flags, flags, ImPlot3DProp_Marker, ImPlot3DMarker_Square}); ImPlot3D::EndPlot(); } } @@ -931,12 +937,9 @@ void DemoBoxRotation() { ImPlot3D::SetupBoxRotation(elevation, azimuth, animate, ImPlot3DCond_Always); // Plot axis lines - ImPlot3D::SetNextLineStyle(ImVec4(0.8f, 0.2f, 0.2f, 1)); - ImPlot3D::PlotLine("X-Axis", axis, origin, origin, 2); - ImPlot3D::SetNextLineStyle(ImVec4(0.2f, 0.8f, 0.2f, 1)); - ImPlot3D::PlotLine("Y-Axis", origin, axis, origin, 2); - ImPlot3D::SetNextLineStyle(ImVec4(0.2f, 0.2f, 0.8f, 1)); - ImPlot3D::PlotLine("Z-Axis", origin, origin, axis, 2); + ImPlot3D::PlotLine("X-Axis", axis, origin, origin, 2, {ImPlot3DProp_LineColor, ImVec4(0.8f, 0.2f, 0.2f, 1)}); + ImPlot3D::PlotLine("Y-Axis", origin, axis, origin, 2, {ImPlot3DProp_LineColor, ImVec4(0.2f, 0.8f, 0.2f, 1)}); + ImPlot3D::PlotLine("Z-Axis", origin, origin, axis, 2, {ImPlot3DProp_LineColor, ImVec4(0.2f, 0.2f, 0.8f, 1)}); ImPlot3D::EndPlot(); } @@ -1144,8 +1147,11 @@ void DemoMousePicking() { // Show intersection point if (ImGui::IsItemHovered() && !point.IsNaN()) { - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Circle, 5, ImVec4(1, 1, 0, 1)); - ImPlot3D::PlotScatter("##Intersection", &point.x, &point.y, &point.z, 1); + ImPlot3DSpec spec; + spec.Marker = ImPlot3DMarker_Circle; + spec.Size = 5; + spec.FillColor = ImVec4(1, 1, 0, 1); + ImPlot3D::PlotScatter("##Intersection", &point.x, &point.y, &point.z, 1, spec); } // Add point/ray on click @@ -1156,10 +1162,12 @@ void DemoMousePicking() { // Draw all placed points if (!points.empty()) { - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Circle, 3); // Plot points - ImPlot3D::PlotScatter("Placed Points", &points[0].x, &points[0].y, &points[0].z, (int)points.Size, ImPlot3DScatterFlags_None, 0, - sizeof(ImPlot3DPoint)); + ImPlot3DSpec spec; + spec.Marker = ImPlot3DMarker_Circle; + spec.Size = 3; + spec.Stride = sizeof(ImPlot3DPoint); + ImPlot3D::PlotScatter("Placed Points", &points[0].x, &points[0].y, &points[0].z, (int)points.Size, spec); } // Draw all placed rays @@ -1172,8 +1180,11 @@ void DemoMousePicking() { ray_points.push_back(p1); ray_points.push_back(p2); } - ImPlot3D::PlotLine("Placed Rays", &ray_points[0].x, &ray_points[0].y, &ray_points[0].z, (int)rays.Size * 2, ImPlot3DLineFlags_Segments, 0, - sizeof(ImPlot3DPoint)); + ImPlot3DSpec spec; + spec.Flags = ImPlot3DLineFlags_Segments; + spec.Offset = 0; + spec.Stride = sizeof(ImPlot3DPoint); + ImPlot3D::PlotLine("Placed Rays", &ray_points[0].x, &ray_points[0].y, &ray_points[0].z, (int)rays.Size * 2, spec); } ImPlot3D::EndPlot(); @@ -1351,7 +1362,7 @@ void DemoCustomOverlay() { void DemoCustomPerPointStyle() { ImGui::BulletText("Demonstrates per-point coloring using colormap sampling."); - ImGui::BulletText("Each point calls SetNextMarkerStyle with a sampled color."); + ImGui::BulletText("A different color is sampled for each point."); ImGui::BulletText("All points share the same label for a single legend entry."); static float marker_size = 4.0f; @@ -1432,6 +1443,10 @@ void DemoCustomPerPointStyle() { ImVec4(0.0f, 0.0f, 1.0f, 1.0f) // Blue }; + ImPlot3DSpec spec; + spec.Marker = ImPlot3DMarker_Circle; + spec.Size = marker_size; + for (int torus = 0; torus < 3; torus++) { const int point_count = 400; for (int i = 0; i < point_count; i++) { @@ -1442,12 +1457,13 @@ void DemoCustomPerPointStyle() { // Sample colormap and set marker style ImVec4 color = ImPlot3D::SampleColormap(t, cmap); - ImPlot3D::SetNextMarkerStyle(ImPlot3DMarker_Circle, marker_size, color, IMPLOT3D_AUTO, color); - ImPlot3D::PlotScatter(labels[torus], &x, &y, &z, 1); + spec.FillColor = color; + spec.LineColor = color; + ImPlot3D::PlotScatter(labels[torus], &x, &y, &z, 1, spec); } // Override legend color with PlotDummy - ImPlot3D::SetNextLineStyle(legend_colors[torus]); - ImPlot3D::PlotDummy(labels[torus]); + spec.LineColor = legend_colors[torus]; + ImPlot3D::PlotDummy(labels[torus], spec); } ImPlot3D::EndPlot(); diff --git a/implot3d_internal.h b/implot3d_internal.h index b2980174..42ff7e1c 100644 --- a/implot3d_internal.h +++ b/implot3d_internal.h @@ -12,6 +12,7 @@ // Table of Contents: // [SECTION] Constants // [SECTION] Generic Helpers +// [SECTION] Internal Enumerations // [SECTION] Forward Declarations // [SECTION] Callbacks // [SECTION] Structs @@ -113,6 +114,14 @@ template void FillRange(ImVector& buffer, int n, T vmin, T vmax) } // namespace ImPlot3D +//----------------------------------------------------------------------------- +// [SECTION] Internal Enumerations +//----------------------------------------------------------------------------- + +enum ImPlot3DMarkerInternal_ { + ImPlot3DMarker_Invalid = -3, +}; + //----------------------------------------------------------------------------- // [SECTION] Forward Declarations //----------------------------------------------------------------------------- @@ -311,6 +320,7 @@ struct ImPlot3DColormapData { struct ImPlot3DItem { ImGuiID ID; ImU32 Color; + ImPlot3DMarker Marker; int NameOffset; bool Show; bool LegendHovered; @@ -319,6 +329,7 @@ struct ImPlot3DItem { ImPlot3DItem() { ID = 0; Color = IM_COL32_WHITE; + Marker = ImPlot3DMarker_None; NameOffset = -1; Show = true; LegendHovered = false; @@ -356,8 +367,12 @@ struct ImPlot3DItemGroup { ImPool ItemPool; ImPlot3DLegend Legend; int ColormapIdx; + ImPlot3DMarker MarkerIdx; - ImPlot3DItemGroup() { ColormapIdx = 0; } + ImPlot3DItemGroup() { + ColormapIdx = 0; + MarkerIdx = 0; + } int GetItemCount() const { return ItemPool.GetBufSize(); } ImGuiID GetItemID(const char* label_id) { return ImGui::GetID(label_id); } @@ -373,6 +388,7 @@ struct ImPlot3DItemGroup { ItemPool.Clear(); Legend.Reset(); ColormapIdx = 0; + MarkerIdx = 0; } }; @@ -837,7 +853,9 @@ IMPLOT3D_API void RenderColorBar(const ImU32* colors, int size, ImDrawList& Draw // [SECTION] Item Utils //----------------------------------------------------------------------------- -IMPLOT3D_API bool BeginItem(const char* label_id, ImPlot3DItemFlags flags = 0, ImPlot3DCol recolor_from = IMPLOT3D_AUTO); +// Begins a new item. Returns false if the item should not be plotted +IMPLOT3D_API bool BeginItem(const char* label_id, const ImPlot3DSpec& spec = ImPlot3DSpec(), const ImVec4& item_col = IMPLOT3D_AUTO_COL, + ImPlot3DMarker item_mkr = ImPlot3DMarker_Invalid); IMPLOT3D_API void EndItem(); // Register or get an existing item from the current plot diff --git a/implot3d_items.cpp b/implot3d_items.cpp index a7bd2c54..a230e335 100644 --- a/implot3d_items.cpp +++ b/implot3d_items.cpp @@ -138,20 +138,24 @@ namespace ImPlot3D { static const float ITEM_HIGHLIGHT_LINE_SCALE = 2.0f; static const float ITEM_HIGHLIGHT_MARK_SCALE = 1.25f; -bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, const ImVec4& item_col) { +template int Stride(const ImPlot3DSpec& spec) { return spec.Stride == IMPLOT3D_AUTO ? sizeof(T) : spec.Stride; } + +bool BeginItem(const char* label_id, const ImPlot3DSpec& spec, const ImVec4& item_col, ImPlot3DMarker item_mkr) { ImPlot3DContext& gp = *GImPlot3D; IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotX() needs to be called between BeginPlot() and EndPlot()!"); // Lock setup SetupLock(); + // Override next data with spec ImPlot3DStyle& style = gp.Style; ImPlot3DNextItemData& n = gp.NextItemData; ImPlot3DSpec& s = n.Spec; + s = spec; // Register item bool just_created; - ImPlot3DItem* item = RegisterOrGetItem(label_id, flags, &just_created); + ImPlot3DItem* item = RegisterOrGetItem(label_id, spec.Flags, &just_created); // Set current item gp.CurrentItem = item; @@ -162,6 +166,17 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, const ImVec4& item item->Color = NextColormapColorU32(); } + // Set/override item marker + if (item_mkr != ImPlot3DMarker_Invalid) { + if (item_mkr != ImPlot3DMarker_Auto) { + item->Marker = item_mkr; + } else if (just_created && item_mkr == ImPlot3DMarker_Auto) { + item->Marker = NextMarker(); + } else if (item_mkr == ImPlot3DMarker_Auto && item->Marker == ImPlot3DMarker_None) { + item->Marker = NextMarker(); + } + } + // Set next item color ImVec4 item_color = ImGui::ColorConvertU32ToFloat4(item->Color); n.IsAutoLine = IsColorAuto(s.LineColor); @@ -201,12 +216,12 @@ bool BeginItem(const char* label_id, ImPlot3DItemFlags flags, const ImVec4& item return true; } -template -bool BeginItemEx(const char* label_id, const _Getter& getter, ImPlot3DItemFlags flags = 0, const ImVec4& color = IMPLOT3D_AUTO_COL) { - if (BeginItem(label_id, flags, color)) { +template bool BeginItemEx(const char* label_id, const _Getter& getter, const ImPlot3DSpec& spec, + const ImVec4& item_col = IMPLOT3D_AUTO_COL, ImPlot3DMarker item_mkr = ImPlot3DMarker_Invalid) { + if (BeginItem(label_id, spec, item_col, item_mkr)) { ImPlot3DContext& gp = *GImPlot3D; ImPlot3DPlot& plot = *gp.CurrentPlot; - if (plot.FitThisFrame && !ImHasFlag(flags, ImPlot3DItemFlags_NoFit)) { + if (plot.FitThisFrame && !ImHasFlag(spec.Flags, ImPlot3DItemFlags_NoFit)) { for (int i = 0; i < getter.Count; i++) plot.ExtendFit(getter(i)); } @@ -258,33 +273,6 @@ void BustItemCache() { } } -void SetNextLineStyle(const ImVec4& col, float weight) { - ImPlot3DContext& gp = *GImPlot3D; - ImPlot3DNextItemData& n = gp.NextItemData; - ImPlot3DSpec& spec = n.Spec; - spec.LineColor = col; - spec.LineWeight = weight; -} - -void SetNextFillStyle(const ImVec4& col, float alpha) { - ImPlot3DContext& gp = *GImPlot3D; - ImPlot3DNextItemData& n = gp.NextItemData; - ImPlot3DSpec& spec = n.Spec; - spec.FillColor = col; - spec.FillAlpha = alpha; -} - -void SetNextMarkerStyle(ImPlot3DMarker marker, float size, const ImVec4& fill, float weight, const ImVec4& outline) { - ImPlot3DContext& gp = *GImPlot3D; - ImPlot3DNextItemData& n = gp.NextItemData; - ImPlot3DSpec& spec = n.Spec; - spec.Marker = marker; - spec.FillColor = fill; - spec.Size = size; - spec.LineColor = outline; - spec.LineWeight = weight; -} - //----------------------------------------------------------------------------- // [SECTION] Draw Utils //----------------------------------------------------------------------------- @@ -1137,10 +1125,10 @@ template void RenderMarkers(const _Getter& getter, ImPlot3DMa // [SECTION] PlotScatter //----------------------------------------------------------------------------- -template void PlotScatterEx(const char* label_id, const Getter& getter, ImPlot3DScatterFlags flags) { - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItemEx(label_id, getter, flags, s.LineColor)) { +template void PlotScatterEx(const char* label_id, const Getter& getter, const ImPlot3DSpec& spec) { + if (BeginItemEx(label_id, getter, spec, spec.LineColor, spec.Marker)) { + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; ImPlot3DMarker marker = s.Marker == ImPlot3DMarker_None ? ImPlot3DMarker_Circle : s.Marker; const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); @@ -1150,18 +1138,18 @@ template void PlotScatterEx(const char* label_id, const Getter } } -template -void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags, int offset, int stride) { +template void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec) { if (count < 1) return; - GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, offset, stride), IndexerIdx(ys, count, offset, stride), - IndexerIdx(zs, count, offset, stride), count); - return PlotScatterEx(label_id, getter, flags); + int stride = Stride(spec); + GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, spec.Offset, stride), + IndexerIdx(ys, count, spec.Offset, stride), + IndexerIdx(zs, count, spec.Offset, stride), count); + return PlotScatterEx(label_id, getter, spec); } #define INSTANTIATE_MACRO(T) \ - template IMPLOT3D_API void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DScatterFlags flags, \ - int offset, int stride); + template IMPLOT3D_API void PlotScatter(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec); CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO @@ -1169,21 +1157,22 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() // [SECTION] PlotLine //----------------------------------------------------------------------------- -template void PlotLineEx(const char* label_id, const _Getter& getter, ImPlot3DLineFlags flags) { - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItemEx(label_id, getter, flags, s.LineColor)) { +template void PlotLineEx(const char* label_id, const _Getter& getter, const ImPlot3DSpec& spec) { + if (BeginItemEx(label_id, getter, spec, spec.LineColor, spec.Marker)) { + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + if (getter.Count >= 2 && n.RenderLine) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - if (ImHasFlag(flags, ImPlot3DLineFlags_Segments)) { + if (ImHasFlag(spec.Flags, ImPlot3DLineFlags_Segments)) { RenderPrimitives(getter, col_line, s.LineWeight); - } else if (ImHasFlag(flags, ImPlot3DLineFlags_Loop)) { - if (ImHasFlag(flags, ImPlot3DLineFlags_SkipNaN)) + } else if (ImHasFlag(spec.Flags, ImPlot3DLineFlags_Loop)) { + if (ImHasFlag(spec.Flags, ImPlot3DLineFlags_SkipNaN)) RenderPrimitives(GetterLoop<_Getter>(getter), col_line, s.LineWeight); else RenderPrimitives(GetterLoop<_Getter>(getter), col_line, s.LineWeight); } else { - if (ImHasFlag(flags, ImPlot3DLineFlags_SkipNaN)) + if (ImHasFlag(spec.Flags, ImPlot3DLineFlags_SkipNaN)) RenderPrimitives(getter, col_line, s.LineWeight); else RenderPrimitives(getter, col_line, s.LineWeight); @@ -1200,17 +1189,18 @@ template void PlotLineEx(const char* label_id, const _Getter& } } -IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags, int offset, int stride) { +IMPLOT3D_TMP void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec) { if (count < 2) return; - GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, offset, stride), IndexerIdx(ys, count, offset, stride), - IndexerIdx(zs, count, offset, stride), count); - return PlotLineEx(label_id, getter, flags); + int stride = Stride(spec); + GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, spec.Offset, stride), + IndexerIdx(ys, count, spec.Offset, stride), + IndexerIdx(zs, count, spec.Offset, stride), count); + return PlotLineEx(label_id, getter, spec); } #define INSTANTIATE_MACRO(T) \ - template IMPLOT3D_API void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DLineFlags flags, \ - int offset, int stride); + template IMPLOT3D_API void PlotLine(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec); CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO @@ -1218,24 +1208,25 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() // [SECTION] PlotTriangle //----------------------------------------------------------------------------- -template void PlotTriangleEx(const char* label_id, const _Getter& getter, ImPlot3DTriangleFlags flags) { - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItemEx(label_id, getter, flags, s.FillColor)) { +template void PlotTriangleEx(const char* label_id, const _Getter& getter, const ImPlot3DSpec& spec) { + if (BeginItemEx(label_id, getter, spec, spec.LineColor, spec.Marker)) { + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + // Render fill - if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoFill)) { + if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(spec.Flags, ImPlot3DTriangleFlags_NoFill)) { const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter, col_fill); } // Render lines - if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoLines)) { + if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(spec.Flags, ImPlot3DTriangleFlags_NoLines)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); RenderPrimitives(GetterTriangleLines<_Getter>(getter), col_line, s.LineWeight); } // Render markers - if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DTriangleFlags_NoMarkers)) { + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DTriangleFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); @@ -1245,18 +1236,18 @@ template void PlotTriangleEx(const char* label_id, const _Get } } -IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags, int offset, - int stride) { +IMPLOT3D_TMP void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec) { if (count < 3) return; - GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, offset, stride), IndexerIdx(ys, count, offset, stride), - IndexerIdx(zs, count, offset, stride), count); - return PlotTriangleEx(label_id, getter, flags); + int stride = Stride(spec); + GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, spec.Offset, stride), + IndexerIdx(ys, count, spec.Offset, stride), + IndexerIdx(zs, count, spec.Offset, stride), count); + return PlotTriangleEx(label_id, getter, spec); } #define INSTANTIATE_MACRO(T) \ - template IMPLOT3D_API void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DTriangleFlags flags, \ - int offset, int stride); + template IMPLOT3D_API void PlotTriangle(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec); CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO @@ -1264,24 +1255,25 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() // [SECTION] PlotQuad //----------------------------------------------------------------------------- -template void PlotQuadEx(const char* label_id, const _Getter& getter, ImPlot3DQuadFlags flags) { - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItemEx(label_id, getter, flags, s.FillColor)) { +template void PlotQuadEx(const char* label_id, const _Getter& getter, const ImPlot3DSpec& spec) { + if (BeginItemEx(label_id, getter, spec, spec.FillColor, spec.Marker)) { + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + // Render fill - if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(flags, ImPlot3DQuadFlags_NoFill)) { + if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(spec.Flags, ImPlot3DQuadFlags_NoFill)) { const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter, col_fill); } // Render lines - if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DQuadFlags_NoLines)) { + if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(spec.Flags, ImPlot3DQuadFlags_NoLines)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); RenderPrimitives(GetterQuadLines<_Getter>(getter), col_line, s.LineWeight); } // Render markers - if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DQuadFlags_NoMarkers)) { + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DQuadFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); @@ -1291,17 +1283,18 @@ template void PlotQuadEx(const char* label_id, const _Getter& } } -IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags, int offset, int stride) { +IMPLOT3D_TMP void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec) { if (count < 3) return; - GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, offset, stride), IndexerIdx(ys, count, offset, stride), - IndexerIdx(zs, count, offset, stride), count); - return PlotQuadEx(label_id, getter, flags); + int stride = Stride(spec); + GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, spec.Offset, stride), + IndexerIdx(ys, count, spec.Offset, stride), + IndexerIdx(zs, count, spec.Offset, stride), count); + return PlotQuadEx(label_id, getter, spec); } #define INSTANTIATE_MACRO(T) \ - template IMPLOT3D_API void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, ImPlot3DQuadFlags flags, \ - int offset, int stride); + template IMPLOT3D_API void PlotQuad(const char* label_id, const T* xs, const T* ys, const T* zs, int count, const ImPlot3DSpec& spec); CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO @@ -1310,24 +1303,25 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() //----------------------------------------------------------------------------- template void PlotSurfaceEx(const char* label_id, const _Getter& getter, int x_count, int y_count, double scale_min, - double scale_max, ImPlot3DSurfaceFlags flags) { - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItemEx(label_id, getter, flags, s.FillColor)) { + double scale_max, const ImPlot3DSpec& spec) { + if (BeginItemEx(label_id, getter, spec, spec.FillColor, spec.Marker)) { + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; + // Render fill - if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoFill)) { + if (getter.Count >= 4 && n.RenderFill && !ImHasFlag(spec.Flags, ImPlot3DSurfaceFlags_NoFill)) { const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter, x_count, y_count, col_fill, scale_min, scale_max); } // Render lines - if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoLines)) { + if (getter.Count >= 2 && n.RenderLine && !ImHasFlag(spec.Flags, ImPlot3DSurfaceFlags_NoLines)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); RenderPrimitives(GetterSurfaceLines<_Getter>(getter, x_count, y_count), col_line, s.LineWeight); } // Render markers - if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DSurfaceFlags_NoMarkers)) { + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DSurfaceFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); @@ -1338,18 +1332,20 @@ template void PlotSurfaceEx(const char* label_id, const _Gett } IMPLOT3D_TMP void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, double scale_min, - double scale_max, ImPlot3DSurfaceFlags flags, int offset, int stride) { + double scale_max, const ImPlot3DSpec& spec) { int count = x_count * y_count; if (count < 4) return; - GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, offset, stride), IndexerIdx(ys, count, offset, stride), - IndexerIdx(zs, count, offset, stride), count); - return PlotSurfaceEx(label_id, getter, x_count, y_count, scale_min, scale_max, flags); + int stride = Stride(spec); + GetterXYZ, IndexerIdx, IndexerIdx> getter(IndexerIdx(xs, count, spec.Offset, stride), + IndexerIdx(ys, count, spec.Offset, stride), + IndexerIdx(zs, count, spec.Offset, stride), count); + return PlotSurfaceEx(label_id, getter, x_count, y_count, scale_min, scale_max, spec); } #define INSTANTIATE_MACRO(T) \ template IMPLOT3D_API void PlotSurface(const char* label_id, const T* xs, const T* ys, const T* zs, int x_count, int y_count, \ - double scale_min, double scale_max, ImPlot3DSurfaceFlags flags, int offset, int stride); + double scale_min, double scale_max, const ImPlot3DSpec& spec); CALL_INSTANTIATE_FOR_NUMERIC_TYPES() #undef INSTANTIATE_MACRO @@ -1357,28 +1353,28 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() // [SECTION] PlotMesh //----------------------------------------------------------------------------- -void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, ImPlot3DMeshFlags flags) { +void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int* idx, int vtx_count, int idx_count, const ImPlot3DSpec& spec) { Getter3DPoints getter(vtx, vtx_count); // Get vertices GetterMeshTriangles getter_triangles(vtx, idx, idx_count); // Get triangle vertices - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItemEx(label_id, getter, flags, s.FillColor)) { + if (BeginItemEx(label_id, getter, spec, spec.FillColor, spec.Marker)) { + const ImPlot3DNextItemData& n = GetItemData(); + const ImPlot3DSpec& s = n.Spec; // Render fill - if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(flags, ImPlot3DMeshFlags_NoFill)) { + if (getter.Count >= 3 && n.RenderFill && !ImHasFlag(spec.Flags, ImPlot3DMeshFlags_NoFill)) { const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderPrimitives(getter_triangles, col_fill); } // Render lines - if (getter.Count >= 2 && n.RenderLine && !n.IsAutoLine && !ImHasFlag(flags, ImPlot3DMeshFlags_NoLines)) { + if (getter.Count >= 2 && n.RenderLine && !n.IsAutoLine && !ImHasFlag(spec.Flags, ImPlot3DMeshFlags_NoLines)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); RenderPrimitives(GetterTriangleLines(getter_triangles), col_line, s.LineWeight); } // Render markers - if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(flags, ImPlot3DMeshFlags_NoMarkers)) { + if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DMeshFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); RenderMarkers(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); @@ -1393,7 +1389,7 @@ void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int //----------------------------------------------------------------------------- IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& center, const ImPlot3DPoint& axis_u, - const ImPlot3DPoint& axis_v, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, ImPlot3DImageFlags flags) { + const ImPlot3DPoint& axis_v, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImPlot3DSpec& spec) { // Compute corners from center and axes ImPlot3DPoint p0 = center - axis_u - axis_v; // Bottom-left ImPlot3DPoint p1 = center + axis_u - axis_v; // Bottom-right @@ -1407,12 +1403,12 @@ IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const Im ImVec2 uv_3 = ImVec2(uv0.x, uv1.y); // Delegate to full quad version - PlotImage(label_id, tex_ref, p0, p1, p2, p3, uv_0, uv_1, uv_2, uv_3, tint_col, flags); + PlotImage(label_id, tex_ref, p0, p1, p2, p3, uv_0, uv_1, uv_2, uv_3, tint_col, spec); } IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const ImPlot3DPoint& p0, const ImPlot3DPoint& p1, const ImPlot3DPoint& p2, const ImPlot3DPoint& p3, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& uv2, const ImVec2& uv3, - const ImVec4& tint_col, ImPlot3DImageFlags flags) { + const ImVec4& tint_col, const ImPlot3DSpec& spec) { ImPlot3DContext& gp = *GImPlot3D; IM_ASSERT_USER_ERROR(gp.CurrentPlot != nullptr, "PlotImage() needs to be called between BeginPlot() and EndPlot()!"); SetupLock(); @@ -1426,7 +1422,7 @@ IMPLOT3D_API void PlotImage(const char* label_id, ImTextureRef tex_ref, const Im ImVec2 uv_2 = ImVec2(uv2.x, 1 - uv2.y); ImVec2 uv_3 = ImVec2(uv3.x, 1 - uv3.y); - if (BeginItemEx(label_id, getter, flags)) { + if (BeginItemEx(label_id, getter, spec, tint_col, spec.Marker)) { ImU32 tint_col32 = ImGui::ColorConvertFloat4ToU32(tint_col); GetCurrentItem()->Color = tint_col32; @@ -1466,10 +1462,8 @@ void PlotText(const char* text, double x, double y, double z, double angle, cons AddTextRotated(GetPlotDrawList(), p, (float)angle, GetStyleColorU32(ImPlot3DCol_InlayText), text); } -void PlotDummy(const char* label_id, ImPlot3DDummyFlags flags) { - const ImPlot3DNextItemData& n = GetItemData(); - const ImPlot3DSpec& s = n.Spec; - if (BeginItem(label_id, flags, s.LineColor)) +void PlotDummy(const char* label_id, const ImPlot3DSpec& spec) { + if (BeginItem(label_id, spec, spec.LineColor, spec.Marker)) EndItem(); } From 4ab791aee52f43b84a1c6b74de32ee7d7670a01a Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Tue, 3 Feb 2026 16:38:34 +0100 Subject: [PATCH 04/10] refactor: rename ImPlot3DProp_Size to ImPlot3DProp_MarkerSize --- implot3d.cpp | 2 +- implot3d.h | 6 +++--- implot3d_demo.cpp | 23 ++++++++++++----------- implot3d_items.cpp | 16 ++++++++-------- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index 01dcdfda..c504a786 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -85,7 +85,7 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r ``` ImPlot3DSpec spec; spec.Marker = marker; - spec.Size = marker_size; + spec.MarkerSize = marker_size; spec.FillColor = fill_color; spec.LineWeight = line_weight; spec.LineColor = marker_outline_color; diff --git a/implot3d.h b/implot3d.h index 91698c6d..6f04691a 100644 --- a/implot3d.h +++ b/implot3d.h @@ -341,7 +341,7 @@ enum ImPlot3DProp_ { ImPlot3DProp_FillColor, // Fill color (applies to shaded regions, marker faces); IMPLOT3D_AUTO_COL will use next Colormap color ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor) ImPlot3DProp_Marker, // Marker type - ImPlot3DProp_Size, // Size of markers (radius) + ImPlot3DProp_MarkerSize, // Size of markers (radius) ImPlot3DProp_Offset, // Data index offset ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags @@ -377,7 +377,7 @@ struct ImPlot3DSpec { ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions, marker faces); IMPLOT_AUTO_COL will use next Colormap color float FillAlpha = IMPLOT3D_AUTO; // Alpha multiplier (applies to FillColor) ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type; specify ImPlot3DMarker_Auto to use the next unused marker - float Size = IMPLOT3D_AUTO; // Size of markers (radius) *in pixels* + float MarkerSize = IMPLOT3D_AUTO; // Size of markers (radius) *in pixels* int Offset = 0; // Data index offset int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX ImPlot3DItemFlags Flags = @@ -408,7 +408,7 @@ struct ImPlot3DSpec { case ImPlot3DProp_FillColor: FillColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; case ImPlot3DProp_FillAlpha: FillAlpha = (float)v; return; case ImPlot3DProp_Marker: Marker = (ImPlot3DMarker)v; return; - case ImPlot3DProp_Size: Size = (float)v; return; + case ImPlot3DProp_MarkerSize: MarkerSize = (float)v; return; case ImPlot3DProp_Offset: Offset = (int)v; return; case ImPlot3DProp_Stride: Stride = (int)v; return; case ImPlot3DProp_Flags: Flags = (ImPlot3DItemFlags)v; return; diff --git a/implot3d_demo.cpp b/implot3d_demo.cpp index b2c99058..4bc5c117 100644 --- a/implot3d_demo.cpp +++ b/implot3d_demo.cpp @@ -145,7 +145,7 @@ void DemoScatterPlots() { ImPlot3D::PlotScatter("Data 1", xs1, ys1, zs1, 100); ImPlot3DSpec spec; spec.Marker = ImPlot3DMarker_Square; - spec.Size = 6; + spec.MarkerSize = 6; spec.LineColor = ImPlot3D::GetColormapColor(1); spec.FillColor = ImPlot3D::GetColormapColor(1); spec.FillAlpha = 0.25f; @@ -230,7 +230,7 @@ void DemoTrianglePlots() { spec.FillColor = ImPlot3D::GetColormapColor(0); spec.LineColor = ImPlot3D::GetColormapColor(1); spec.Marker = ImPlot3DMarker_Square; - spec.Size = 3; + spec.MarkerSize = 3; spec.Flags = flags; // Plot pyramid @@ -294,7 +294,7 @@ void DemoQuadPlots() { ImPlot3DSpec spec; spec.Marker = ImPlot3DMarker_Square; - spec.Size = 3; + spec.MarkerSize = 3; spec.Flags = flags; // Render +x and -x faces @@ -449,7 +449,7 @@ void DemoMeshPlots() { spec.LineColor = line_color; // Set marker style spec.Marker = ImPlot3DMarker_Square; - spec.Size = 3.0f; + spec.MarkerSize = 3.0f; // Plot mesh if (mesh_id == 0) @@ -821,7 +821,8 @@ void DemoMarkersAndText() { ys[1] = ys[0] + ImSin(zs[0] / float(ImPlot3DMarker_COUNT) * 2 * IM_PI) * 0.5f; ImGui::PushID(m); - ImPlot3D::PlotLine("##Filled", xs, ys, zs, 2, {ImPlot3DProp_Marker, m, ImPlot3DProp_Size, mk_size, ImPlot3DProp_LineWeight, mk_weight}); + ImPlot3D::PlotLine("##Filled", xs, ys, zs, 2, + {ImPlot3DProp_Marker, m, ImPlot3DProp_MarkerSize, mk_size, ImPlot3DProp_LineWeight, mk_weight}); ImGui::PopID(); zs[0]--; zs[1]--; @@ -838,9 +839,9 @@ void DemoMarkersAndText() { ys[1] = ys[0] - ImSin(zs[0] / float(ImPlot3DMarker_COUNT) * 2 * IM_PI) * 0.5f; ImGui::PushID(m); - ImPlot3D::PlotLine( - "##Open", xs, ys, zs, 2, - {ImPlot3DProp_Marker, m, ImPlot3DProp_Size, mk_size, ImPlot3DProp_LineWeight, mk_weight, ImPlot3DProp_FillColor, ImVec4(0, 0, 0, 0)}); + ImPlot3D::PlotLine("##Open", xs, ys, zs, 2, + {ImPlot3DProp_Marker, m, ImPlot3DProp_MarkerSize, mk_size, ImPlot3DProp_LineWeight, mk_weight, ImPlot3DProp_FillColor, + ImVec4(0, 0, 0, 0)}); ImGui::PopID(); zs[0]--; zs[1]--; @@ -1149,7 +1150,7 @@ void DemoMousePicking() { if (ImGui::IsItemHovered() && !point.IsNaN()) { ImPlot3DSpec spec; spec.Marker = ImPlot3DMarker_Circle; - spec.Size = 5; + spec.MarkerSize = 5; spec.FillColor = ImVec4(1, 1, 0, 1); ImPlot3D::PlotScatter("##Intersection", &point.x, &point.y, &point.z, 1, spec); } @@ -1165,7 +1166,7 @@ void DemoMousePicking() { // Plot points ImPlot3DSpec spec; spec.Marker = ImPlot3DMarker_Circle; - spec.Size = 3; + spec.MarkerSize = 3; spec.Stride = sizeof(ImPlot3DPoint); ImPlot3D::PlotScatter("Placed Points", &points[0].x, &points[0].y, &points[0].z, (int)points.Size, spec); } @@ -1445,7 +1446,7 @@ void DemoCustomPerPointStyle() { ImPlot3DSpec spec; spec.Marker = ImPlot3DMarker_Circle; - spec.Size = marker_size; + spec.MarkerSize = marker_size; for (int torus = 0; torus < 3; torus++) { const int point_count = 400; diff --git a/implot3d_items.cpp b/implot3d_items.cpp index a230e335..01968ebc 100644 --- a/implot3d_items.cpp +++ b/implot3d_items.cpp @@ -187,7 +187,7 @@ bool BeginItem(const char* label_id, const ImPlot3DSpec& spec, const ImVec4& ite // Set size & weight s.LineWeight = s.LineWeight < 0.0f ? style.LineWeight : s.LineWeight; s.Marker = s.Marker < 0 ? style.Marker : s.Marker; - s.Size = s.Size < 0.0f ? style.MarkerSize : s.Size; + s.MarkerSize = s.MarkerSize < 0.0f ? style.MarkerSize : s.MarkerSize; s.FillAlpha = s.FillAlpha < 0 ? gp.Style.FillAlpha : s.FillAlpha; // Apply alpha modifiers @@ -208,7 +208,7 @@ bool BeginItem(const char* label_id, const ImPlot3DSpec& spec, const ImVec4& ite if (item->LegendHovered) { if (!ImHasFlag(gp.CurrentItems->Legend.Flags, ImPlot3DLegendFlags_NoHighlightItem)) { s.LineWeight *= ITEM_HIGHLIGHT_LINE_SCALE; - s.Size *= ITEM_HIGHLIGHT_MARK_SCALE; + s.MarkerSize *= ITEM_HIGHLIGHT_MARK_SCALE; } } } @@ -1133,7 +1133,7 @@ template void PlotScatterEx(const char* label_id, const Getter const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); if (marker != ImPlot3DMarker_None) - RenderMarkers(getter, marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); + RenderMarkers(getter, marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); EndItem(); } } @@ -1183,7 +1183,7 @@ template void PlotLineEx(const char* label_id, const _Getter& if (s.Marker != ImPlot3DMarker_None) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); - RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); + RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); } @@ -1229,7 +1229,7 @@ template void PlotTriangleEx(const char* label_id, const _Get if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DTriangleFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); - RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); + RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1276,7 +1276,7 @@ template void PlotQuadEx(const char* label_id, const _Getter& if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DQuadFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); - RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); + RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1324,7 +1324,7 @@ template void PlotSurfaceEx(const char* label_id, const _Gett if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DSurfaceFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); - RenderMarkers<_Getter>(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); + RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1377,7 +1377,7 @@ void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DMeshFlags_NoMarkers)) { const ImU32 col_line = ImGui::GetColorU32(s.LineColor); const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); - RenderMarkers(getter, s.Marker, s.Size, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); + RenderMarkers(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); From 410ea11e9e87948d19f369c7974e360fc8d6c21a Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Tue, 3 Feb 2026 17:03:03 +0100 Subject: [PATCH 05/10] feat: add MarkerLineColor and MarkerFillColor properties --- implot3d.cpp | 6 +++--- implot3d.h | 38 +++++++++++++++++++++++--------------- implot3d_demo.cpp | 10 ++++++---- implot3d_items.cpp | 31 +++++++++++++++++-------------- 4 files changed, 49 insertions(+), 36 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index c504a786..30964ca2 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -84,11 +84,11 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r - After ``` ImPlot3DSpec spec; + spec.LineWeight = line_weight; spec.Marker = marker; spec.MarkerSize = marker_size; - spec.FillColor = fill_color; - spec.LineWeight = line_weight; - spec.LineColor = marker_outline_color; + spec.MarkerLineColor = marker_outline_color; + spec.MarkerFillColor = fill_color; ImPlot3D::PlotLine(xs, ys, zs, count, spec); ``` - Flags, Offset and Stride should also be set via ImPlot3DSpec now. diff --git a/implot3d.h b/implot3d.h index 6f04691a..234655bc 100644 --- a/implot3d.h +++ b/implot3d.h @@ -336,15 +336,17 @@ enum ImPlot3DColormap_ { // Plotting properties. These provide syntactic sugar for creating ImPlot3DSpec from (ImPlot3DProp,value) pairs enum ImPlot3DProp_ { - ImPlot3DProp_LineColor, // Line color (applies to lines, marker edges); IMPLOT3D_AUTO_COL will use next Colormap color - ImPlot3DProp_LineWeight, // Line weight in pixels (applies to lines, marker edges) - ImPlot3DProp_FillColor, // Fill color (applies to shaded regions, marker faces); IMPLOT3D_AUTO_COL will use next Colormap color - ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor) - ImPlot3DProp_Marker, // Marker type - ImPlot3DProp_MarkerSize, // Size of markers (radius) - ImPlot3DProp_Offset, // Data index offset - ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX - ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags + ImPlot3DProp_LineColor, // Line color; IMPLOT3D_AUTO_COL will use next Colormap color + ImPlot3DProp_LineWeight, // Line weight in pixels + ImPlot3DProp_FillColor, // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color + ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor and MarkerFillColor) + ImPlot3DProp_Marker, // Marker type + ImPlot3DProp_MarkerSize, // Size of markers (radius) *in pixels* + ImPlot3DProp_MarkerLineColor, // Marker outline color; IMPLOT3D_AUTO_COL will use next LineColor + ImPlot3DProp_MarkerFillColor, // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor + ImPlot3DProp_Offset, // Data index offset + ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX + ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags }; //----------------------------------------------------------------------------- @@ -372,14 +374,16 @@ enum ImPlot3DProp_ { // ImPlot3DProp_Flags, ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments // }); struct ImPlot3DSpec { - ImVec4 LineColor = IMPLOT3D_AUTO_COL; // Line color (applies to lines, marker edges); IMPLOT_AUTO_COL will use next Colormap color - float LineWeight = 1.0f; // Line weight in pixels (applies to lines, marker edges) - ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions, marker faces); IMPLOT_AUTO_COL will use next Colormap color - float FillAlpha = IMPLOT3D_AUTO; // Alpha multiplier (applies to FillColor) - ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type; specify ImPlot3DMarker_Auto to use the next unused marker + ImVec4 LineColor = IMPLOT3D_AUTO_COL; // Line color; IMPLOT3D_AUTO_COL will use next Colormap color + float LineWeight = 1.0f; // Line weight in pixels + ImVec4 FillColor = IMPLOT3D_AUTO_COL; // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color + float FillAlpha = IMPLOT3D_AUTO; // Alpha multiplier (applies to FillColor and MarkerFillColor) + ImPlot3DMarker Marker = ImPlot3DMarker_Auto; // Marker type float MarkerSize = IMPLOT3D_AUTO; // Size of markers (radius) *in pixels* + ImVec4 MarkerLineColor = IMPLOT3D_AUTO_COL; // Marker outline color; IMPLOT3D_AUTO_COL will use LineColor + ImVec4 MarkerFillColor = IMPLOT3D_AUTO_COL; // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor int Offset = 0; // Data index offset - int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT_AUTO will result in sizeof(T) where T is the type passed to PlotX + int Stride = IMPLOT3D_AUTO; // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX ImPlot3DItemFlags Flags = ImPlot3DItemFlags_None; // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags @@ -409,6 +413,8 @@ struct ImPlot3DSpec { case ImPlot3DProp_FillAlpha: FillAlpha = (float)v; return; case ImPlot3DProp_Marker: Marker = (ImPlot3DMarker)v; return; case ImPlot3DProp_MarkerSize: MarkerSize = (float)v; return; + case ImPlot3DProp_MarkerLineColor: MarkerLineColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; + case ImPlot3DProp_MarkerFillColor: MarkerFillColor = ImGui::ColorConvertU32ToFloat4((ImU32)v); return; case ImPlot3DProp_Offset: Offset = (int)v; return; case ImPlot3DProp_Stride: Stride = (int)v; return; case ImPlot3DProp_Flags: Flags = (ImPlot3DItemFlags)v; return; @@ -422,6 +428,8 @@ struct ImPlot3DSpec { switch (prop) { case ImPlot3DProp_LineColor: LineColor = v; return; case ImPlot3DProp_FillColor: FillColor = v; return; + case ImPlot3DProp_MarkerLineColor: MarkerLineColor = v; return; + case ImPlot3DProp_MarkerFillColor: MarkerFillColor = v; return; default: break; } IM_ASSERT(0 && "User provided an ImPlot3DProp which cannot be set from ImVec4 value!"); diff --git a/implot3d_demo.cpp b/implot3d_demo.cpp index 4bc5c117..f763770f 100644 --- a/implot3d_demo.cpp +++ b/implot3d_demo.cpp @@ -146,8 +146,8 @@ void DemoScatterPlots() { ImPlot3DSpec spec; spec.Marker = ImPlot3DMarker_Square; spec.MarkerSize = 6; - spec.LineColor = ImPlot3D::GetColormapColor(1); - spec.FillColor = ImPlot3D::GetColormapColor(1); + spec.MarkerLineColor = ImPlot3D::GetColormapColor(1); + spec.MarkerFillColor = ImPlot3D::GetColormapColor(2); spec.FillAlpha = 0.25f; ImPlot3D::PlotScatter("Data 2", xs2, ys2, zs2, 50, spec); ImPlot3D::EndPlot(); @@ -429,8 +429,8 @@ void DemoMeshPlots() { ImGui::ColorEdit4("Fill Color##Mesh", (float*)&fill_color); // Choose marker color - // static ImVec4 marker_color = ImVec4(0.5f, 0.5f, 0.2f, 0.6f); - // ImGui::ColorEdit4("Marker Color##Mesh", (float*)&marker_color); + static ImVec4 marker_color = ImVec4(0.5f, 0.5f, 0.2f, 0.6f); + ImGui::ColorEdit4("Marker Color##Mesh", (float*)&marker_color); // Mesh flags static ImPlot3DMeshFlags flags = ImPlot3DMeshFlags_NoMarkers; @@ -450,6 +450,8 @@ void DemoMeshPlots() { // Set marker style spec.Marker = ImPlot3DMarker_Square; spec.MarkerSize = 3.0f; + spec.MarkerLineColor = marker_color; + spec.MarkerFillColor = marker_color; // Plot mesh if (mesh_id == 0) diff --git a/implot3d_items.cpp b/implot3d_items.cpp index 01968ebc..3790676c 100644 --- a/implot3d_items.cpp +++ b/implot3d_items.cpp @@ -183,6 +183,8 @@ bool BeginItem(const char* label_id, const ImPlot3DSpec& spec, const ImVec4& ite n.IsAutoFill = IsColorAuto(s.FillColor); s.LineColor = IsColorAuto(s.LineColor) ? item_color : s.LineColor; s.FillColor = IsColorAuto(s.FillColor) ? s.LineColor : s.FillColor; + s.MarkerLineColor = IsColorAuto(s.MarkerLineColor) ? s.LineColor : s.MarkerLineColor; + s.MarkerFillColor = IsColorAuto(s.MarkerFillColor) ? s.LineColor : s.MarkerFillColor; // Set size & weight s.LineWeight = s.LineWeight < 0.0f ? style.LineWeight : s.LineWeight; @@ -192,6 +194,7 @@ bool BeginItem(const char* label_id, const ImPlot3DSpec& spec, const ImVec4& ite // Apply alpha modifiers s.FillColor.w *= s.FillAlpha; + s.MarkerFillColor.w *= s.FillAlpha; // Set render flags n.RenderLine = s.LineColor.w > 0 && s.LineWeight > 0; @@ -1126,12 +1129,12 @@ template void RenderMarkers(const _Getter& getter, ImPlot3DMa //----------------------------------------------------------------------------- template void PlotScatterEx(const char* label_id, const Getter& getter, const ImPlot3DSpec& spec) { - if (BeginItemEx(label_id, getter, spec, spec.LineColor, spec.Marker)) { + if (BeginItemEx(label_id, getter, spec, spec.MarkerLineColor, spec.Marker)) { const ImPlot3DNextItemData& n = GetItemData(); const ImPlot3DSpec& s = n.Spec; ImPlot3DMarker marker = s.Marker == ImPlot3DMarker_None ? ImPlot3DMarker_Circle : s.Marker; - const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + const ImU32 col_line = ImGui::GetColorU32(s.MarkerLineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.MarkerFillColor); if (marker != ImPlot3DMarker_None) RenderMarkers(getter, marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); EndItem(); @@ -1181,8 +1184,8 @@ template void PlotLineEx(const char* label_id, const _Getter& // Render markers if (s.Marker != ImPlot3DMarker_None) { - const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + const ImU32 col_line = ImGui::GetColorU32(s.MarkerLineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.MarkerFillColor); RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } EndItem(); @@ -1209,7 +1212,7 @@ CALL_INSTANTIATE_FOR_NUMERIC_TYPES() //----------------------------------------------------------------------------- template void PlotTriangleEx(const char* label_id, const _Getter& getter, const ImPlot3DSpec& spec) { - if (BeginItemEx(label_id, getter, spec, spec.LineColor, spec.Marker)) { + if (BeginItemEx(label_id, getter, spec, spec.FillColor, spec.Marker)) { const ImPlot3DNextItemData& n = GetItemData(); const ImPlot3DSpec& s = n.Spec; @@ -1227,8 +1230,8 @@ template void PlotTriangleEx(const char* label_id, const _Get // Render markers if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DTriangleFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + const ImU32 col_line = ImGui::GetColorU32(s.MarkerLineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.MarkerFillColor); RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } @@ -1274,8 +1277,8 @@ template void PlotQuadEx(const char* label_id, const _Getter& // Render markers if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DQuadFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + const ImU32 col_line = ImGui::GetColorU32(s.MarkerLineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.MarkerFillColor); RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } @@ -1322,8 +1325,8 @@ template void PlotSurfaceEx(const char* label_id, const _Gett // Render markers if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DSurfaceFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + const ImU32 col_line = ImGui::GetColorU32(s.MarkerLineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.MarkerFillColor); RenderMarkers<_Getter>(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } @@ -1375,8 +1378,8 @@ void PlotMesh(const char* label_id, const ImPlot3DPoint* vtx, const unsigned int // Render markers if (s.Marker != ImPlot3DMarker_None && !ImHasFlag(spec.Flags, ImPlot3DMeshFlags_NoMarkers)) { - const ImU32 col_line = ImGui::GetColorU32(s.LineColor); - const ImU32 col_fill = ImGui::GetColorU32(s.FillColor); + const ImU32 col_line = ImGui::GetColorU32(s.MarkerLineColor); + const ImU32 col_fill = ImGui::GetColorU32(s.MarkerFillColor); RenderMarkers(getter, s.Marker, s.MarkerSize, n.RenderMarkerFill, col_fill, n.RenderMarkerLine, col_line, s.LineWeight); } From 9a6f16650efeaba0371bc3e17ea8174189304cdd Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Thu, 12 Feb 2026 07:41:29 +0100 Subject: [PATCH 06/10] docs: add SetNextXXX to obsolete API section --- implot3d.cpp | 4 ++-- implot3d.h | 39 +++++++++++++++++++++++---------------- implot3d_demo.cpp | 2 +- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index 30964ca2..1d210f8e 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -73,7 +73,7 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r ImPlot3DSpec spec; spec.FillColor = fill_color; spec.FillAlpha = fill_alpha; - ImPlot3D::PlotLine(xs, ys, zs, count, spec); + ImPlot3D::PlotTriangle(xs, ys, zs, count, spec); ``` - SetNextMarkerStyle has been removed, styling should be set via ImPlot3DSpec. - Before: @@ -89,7 +89,7 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r spec.MarkerSize = marker_size; spec.MarkerLineColor = marker_outline_color; spec.MarkerFillColor = fill_color; - ImPlot3D::PlotLine(xs, ys, zs, count, spec); + ImPlot3D::PlotScatter(xs, ys, zs, count, spec); ``` - Flags, Offset and Stride should also be set via ImPlot3DSpec now. - 2026/02/02 (0.4) - Item colors removed from ImPlot3DCol_, it's no longer possible to push/pop individual item colors. diff --git a/implot3d.h b/implot3d.h index 234655bc..454a7d7d 100644 --- a/implot3d.h +++ b/implot3d.h @@ -46,7 +46,7 @@ #endif #define IMPLOT3D_VERSION "0.4 WIP" // ImPlot3D version -#define IMPLOT3D_VERSION_NUM 400 // Integer encoded version +#define IMPLOT3D_VERSION_NUM 401 // Integer encoded version #define IMPLOT3D_AUTO -1 // Deduce variable automatically #define IMPLOT3D_AUTO_COL ImVec4(0, 0, 0, -1) // Deduce color automatically #define IMPLOT3D_TMP template IMPLOT3D_API @@ -101,6 +101,21 @@ typedef ImTextureID ImTextureRef; // [SECTION] Flags & Enumerations //----------------------------------------------------------------------------- +// Plotting properties. These provide syntactic sugar for creating ImPlot3DSpec from (ImPlot3DProp,value) pairs +enum ImPlot3DProp_ { + ImPlot3DProp_LineColor, // Line color; IMPLOT3D_AUTO_COL will use next Colormap color + ImPlot3DProp_LineWeight, // Line weight in pixels + ImPlot3DProp_FillColor, // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color + ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor and MarkerFillColor) + ImPlot3DProp_Marker, // Marker type + ImPlot3DProp_MarkerSize, // Size of markers (radius) *in pixels* + ImPlot3DProp_MarkerLineColor, // Marker outline color; IMPLOT3D_AUTO_COL will use next LineColor + ImPlot3DProp_MarkerFillColor, // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor + ImPlot3DProp_Offset, // Data index offset + ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX + ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags +}; + // Flags for ImPlot3D::BeginPlot() enum ImPlot3DFlags_ { ImPlot3DFlags_None = 0, // Default @@ -334,21 +349,6 @@ enum ImPlot3DColormap_ { ImPlot3DColormap_Greys = 15, // White/black }; -// Plotting properties. These provide syntactic sugar for creating ImPlot3DSpec from (ImPlot3DProp,value) pairs -enum ImPlot3DProp_ { - ImPlot3DProp_LineColor, // Line color; IMPLOT3D_AUTO_COL will use next Colormap color - ImPlot3DProp_LineWeight, // Line weight in pixels - ImPlot3DProp_FillColor, // Fill color (applies to shaded regions); IMPLOT3D_AUTO_COL will use next Colormap color - ImPlot3DProp_FillAlpha, // Alpha multiplier (applies to FillColor and MarkerFillColor) - ImPlot3DProp_Marker, // Marker type - ImPlot3DProp_MarkerSize, // Size of markers (radius) *in pixels* - ImPlot3DProp_MarkerLineColor, // Marker outline color; IMPLOT3D_AUTO_COL will use next LineColor - ImPlot3DProp_MarkerFillColor, // Marker fill color; IMPLOT3D_AUTO_COL will use LineColor - ImPlot3DProp_Offset, // Data index offset - ImPlot3DProp_Stride, // Data stride in bytes; IMPLOT3D_AUTO will result in sizeof(T) where T is the type passed to PlotX - ImPlot3DProp_Flags // Optional item flags; can be composed from common ImPlot3DItemFlags and/or specialized ImPlot3DXFlags -}; - //----------------------------------------------------------------------------- // [SECTION] Specs API //----------------------------------------------------------------------------- @@ -1063,6 +1063,13 @@ extern unsigned int duck_idx[DUCK_IDX_COUNT]; // Duck indices namespace ImPlot3D { +// OBSOLETED in v0.4 (from February 2026) +// IMPLOT_API void SetNextLineStyle(const ImVec4& col = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO); // OBSOLETED IN v0.4 // Set ImPlotSpec.LineColor/LineWeight or construct ImPlotSpec with { ImPlotSpec_LineColor, color, ImPlotSpec_LineWeight, weight }. + +// IMPLOT_API void SetNextFillStyle(const ImVec4& col = IMPLOT_AUTO_COL, float alpha_mod = IMPLOT_AUTO);// OBSOLETED IN v0.4 // Set ImPlotSpec.FillColor/FillAlpha or construct ImPlotSpec with { ImPlotSpec_FillColor, color, ImPlotSpec_FillAlpha, alpha }. + +// IMPLOT_API void SetNextMarkerStyle(ImPlotMarker marker = IMPLOT_AUTO, float size = IMPLOT_AUTO, const ImVec4& fill = IMPLOT_AUTO_COL, float weight = IMPLOT_AUTO, const ImVec4& outline = IMPLOT_AUTO_COL); // OBSOLETED IN v0.4 // Set ImPlotSpec.Marker/MarkerSize/MarkerFillColor/LineWeight/MarkerLineColor or construct ImPlotSpec with { ImPlotSpec_Marker, marker, ImPlotSpec_MarkerSize, size, ImPlotSpec_MarkerFillColor, fill_color, ImPlotSpec_LineWeight, weight, ImPlotSpec_MarkerLineColor, outline }. + // OBSOLETED in v0.3 -> PLANNED REMOVAL in v1.0 IMPLOT3D_DEPRECATED(IMPLOT3D_API ImVec2 GetPlotPos()); // Renamed to GetPlotRectPos() IMPLOT3D_DEPRECATED(IMPLOT3D_API ImVec2 GetPlotSize()); // Renamed to GetPlotRectSize() diff --git a/implot3d_demo.cpp b/implot3d_demo.cpp index f763770f..3f80c9a0 100644 --- a/implot3d_demo.cpp +++ b/implot3d_demo.cpp @@ -147,7 +147,7 @@ void DemoScatterPlots() { spec.Marker = ImPlot3DMarker_Square; spec.MarkerSize = 6; spec.MarkerLineColor = ImPlot3D::GetColormapColor(1); - spec.MarkerFillColor = ImPlot3D::GetColormapColor(2); + spec.MarkerFillColor = ImPlot3D::GetColormapColor(1); spec.FillAlpha = 0.25f; ImPlot3D::PlotScatter("Data 2", xs2, ys2, zs2, 50, spec); ImPlot3D::EndPlot(); From 1fdcdb063fbc3e75bdedb137bc22886dd2f6d2d3 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Thu, 12 Feb 2026 07:58:00 +0100 Subject: [PATCH 07/10] style: fix ImProp typo --- implot3d.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implot3d.h b/implot3d.h index 454a7d7d..9fbd9cfc 100644 --- a/implot3d.h +++ b/implot3d.h @@ -365,7 +365,7 @@ enum ImPlot3DColormap_ { // spec.Flags = ImPlot3DItemFlags_NoLegend | ImPlot3DLineFlags_Segments; // ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, spec); // -// 2. Inline using ImProp,value pairs (order does NOT matter): +// 2. Inline using ImPlot3DProp,value pairs (order does NOT matter): // // ImPlot3D::PlotLine("MyLine", xs, ys, zs, 100, { // ImPlot3DProp_LineColor, ImVec4(1,0,0,1), From b190770aaf59e568878c7a3f021d198df50e9189 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Thu, 12 Feb 2026 08:14:23 +0100 Subject: [PATCH 08/10] docs: fix code in SetNextXXX migration guide --- implot3d.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index 1d210f8e..a0787267 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -53,33 +53,33 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r - Before: ``` ImPlot3D::SetNextLineStyle(line_color, line_weight); - ImPlot3D::PlotLine(xs, ys, zs, count); + ImPlot3D::PlotLine("Line", xs, ys, zs, count); ``` - After ``` ImPlot3DSpec spec; spec.LineColor = line_color; spec.LineWeight = line_weight; - ImPlot3D::PlotLine(xs, ys, zs, count, spec); + ImPlot3D::PlotLine("Line", xs, ys, zs, count, spec); ``` - SetNextFillStyle has been removed, styling should be set via ImPlot3DSpec. - Before: ``` ImPlot3D::SetNextFillStyle(fill_color, fill_alpha); - ImPlot3D::PlotTriangle(xs, ys, zs, count); + ImPlot3D::PlotTriangle("Triangle", xs, ys, zs, count); ``` - After ``` ImPlot3DSpec spec; spec.FillColor = fill_color; spec.FillAlpha = fill_alpha; - ImPlot3D::PlotTriangle(xs, ys, zs, count, spec); + ImPlot3D::PlotTriangle("Triangle", xs, ys, zs, count, spec); ``` - SetNextMarkerStyle has been removed, styling should be set via ImPlot3DSpec. - Before: ``` ImPlot3D::SetNextMarkerStyle(marker, marker_size, fill_color, line_weight, marker_outline_color); - ImPlot3D::PlotScatter(xs, ys, zs, count); + ImPlot3D::PlotScatter("Scatter", xs, ys, zs, count); ``` - After ``` @@ -89,7 +89,7 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r spec.MarkerSize = marker_size; spec.MarkerLineColor = marker_outline_color; spec.MarkerFillColor = fill_color; - ImPlot3D::PlotScatter(xs, ys, zs, count, spec); + ImPlot3D::PlotScatter("Scatter", xs, ys, zs, count, spec); ``` - Flags, Offset and Stride should also be set via ImPlot3DSpec now. - 2026/02/02 (0.4) - Item colors removed from ImPlot3DCol_, it's no longer possible to push/pop individual item colors. From 0bc3c7138a5e989e7926805cd422cb18f35f5443 Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Thu, 12 Feb 2026 08:17:46 +0100 Subject: [PATCH 09/10] docs: update code block in SetNextXXX migration guide --- implot3d.cpp | 77 +++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/implot3d.cpp b/implot3d.cpp index a0787267..ce4e8ca7 100644 --- a/implot3d.cpp +++ b/implot3d.cpp @@ -50,48 +50,45 @@ implot3d files. You can read releases logs https://github.com/brenocq/implot3d/r - 2026/02/03 (0.4) - ImPlotSpec was made the default and _only_ way of styling plot items. The SetNextXXXStyle functions have been removed. - SetNextLineStyle has been removed, styling should be set via ImPlot3DSpec. - - Before: - ``` - ImPlot3D::SetNextLineStyle(line_color, line_weight); - ImPlot3D::PlotLine("Line", xs, ys, zs, count); - ``` - - After - ``` - ImPlot3DSpec spec; - spec.LineColor = line_color; - spec.LineWeight = line_weight; - ImPlot3D::PlotLine("Line", xs, ys, zs, count, spec); - ``` + ```cpp + // Before + ImPlot3D::SetNextLineStyle(line_color, line_weight); + ImPlot3D::PlotLine("Line", xs, ys, zs, count); + + // After + ImPlot3DSpec spec; + spec.LineColor = line_color; + spec.LineWeight = line_weight; + ImPlot3D::PlotLine("Line", xs, ys, zs, count, spec); + ``` - SetNextFillStyle has been removed, styling should be set via ImPlot3DSpec. - - Before: - ``` - ImPlot3D::SetNextFillStyle(fill_color, fill_alpha); - ImPlot3D::PlotTriangle("Triangle", xs, ys, zs, count); - ``` - - After - ``` - ImPlot3DSpec spec; - spec.FillColor = fill_color; - spec.FillAlpha = fill_alpha; - ImPlot3D::PlotTriangle("Triangle", xs, ys, zs, count, spec); - ``` + ```cpp + // Before + ImPlot3D::SetNextFillStyle(fill_color, fill_alpha); + ImPlot3D::PlotTriangle("Triangle", xs, ys, zs, count); + + // After + ImPlot3DSpec spec; + spec.FillColor = fill_color; + spec.FillAlpha = fill_alpha; + ImPlot3D::PlotTriangle("Triangle", xs, ys, zs, count, spec); + ``` - SetNextMarkerStyle has been removed, styling should be set via ImPlot3DSpec. - - Before: - ``` - ImPlot3D::SetNextMarkerStyle(marker, marker_size, fill_color, line_weight, marker_outline_color); - ImPlot3D::PlotScatter("Scatter", xs, ys, zs, count); - ``` - - After - ``` - ImPlot3DSpec spec; - spec.LineWeight = line_weight; - spec.Marker = marker; - spec.MarkerSize = marker_size; - spec.MarkerLineColor = marker_outline_color; - spec.MarkerFillColor = fill_color; - ImPlot3D::PlotScatter("Scatter", xs, ys, zs, count, spec); - ``` - - Flags, Offset and Stride should also be set via ImPlot3DSpec now. + ```cpp + // Before: + ImPlot3D::SetNextMarkerStyle(marker, marker_size, fill_color, line_weight, marker_outline_color); + ImPlot3D::PlotScatter("Scatter", xs, ys, zs, count); + + // After + ImPlot3DSpec spec; + spec.LineWeight = line_weight; + spec.Marker = marker; + spec.MarkerSize = marker_size; + spec.MarkerLineColor = marker_outline_color; + spec.MarkerFillColor = fill_color; + ImPlot3D::PlotScatter("Scatter", xs, ys, zs, count, spec); + ``` + - Flags, Offset and Stride should also be set via ImPlot3DSpec now. - 2026/02/02 (0.4) - Item colors removed from ImPlot3DCol_, it's no longer possible to push/pop individual item colors. - 2026/02/02 (0.4) - ImPlot3DStyle::MarkerWeight was removed. The marker line weight is now controlled by ImPlot3DStyle::LineWeight. From a75926509447d6b41800f3ffbb505ffb9d3d0fca Mon Sep 17 00:00:00 2001 From: Breno Cunha Queiroz Date: Sat, 14 Feb 2026 07:16:58 +0100 Subject: [PATCH 10/10] fix: auto FillColor --- implot3d_items.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implot3d_items.cpp b/implot3d_items.cpp index 758dbad6..7367822e 100644 --- a/implot3d_items.cpp +++ b/implot3d_items.cpp @@ -182,7 +182,7 @@ bool BeginItem(const char* label_id, const ImPlot3DSpec& spec, const ImVec4& ite n.IsAutoLine = IsColorAuto(s.LineColor); n.IsAutoFill = IsColorAuto(s.FillColor); s.LineColor = IsColorAuto(s.LineColor) ? item_color : s.LineColor; - s.FillColor = IsColorAuto(s.FillColor) ? s.LineColor : s.FillColor; + s.FillColor = IsColorAuto(s.FillColor) ? item_color : s.FillColor; s.MarkerLineColor = IsColorAuto(s.MarkerLineColor) ? s.LineColor : s.MarkerLineColor; s.MarkerFillColor = IsColorAuto(s.MarkerFillColor) ? s.LineColor : s.MarkerFillColor;