-
Notifications
You must be signed in to change notification settings - Fork 539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ImPlotSpec and remove existing plot item styling mechanisms #519
base: master
Are you sure you want to change the base?
Conversation
…ext, PushStyle, etc.)
…itGap to DigitalSpacing
@PeterJohnson, @sergeyn, @sonoro1234, @rokups, @marcizhu , @ocornut, @bear24rw, @ozlb -- I would appreciate some eyes on this. Please feel free to leave comments or critiques. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the new API. Just wanted to provide some code comments.
Thanks for considering me! I’m using Usage Option 1 |
I'm not equipped to provide overall feedback, but some small bits:
|
Somehow I missed that on my first read-through. That's a problem for me as well, as it sounds like this means it's no longer possible to arbitrarily vertically position individual digital plots on a per-line basis? Or is there a "new" way to do this? |
Yea, I was torn on this one for the same reasons. I leaned more toward Relatedly, I experimented with compile time conversion of string literal to ImProp, such that this was possible: ImPlot::PlotLine("Line 2", &data2[0].x, &data2[0].y, 20, {
"LineColor", ImVec4(0,1,1,1),
"LineWeight", 1.0f,
"FillColor", ImVec4(0,0,1,1),
"FillAlpha", 0.5f,
"Marker", ImPlotMarker_Diamond,
"Size", 6,
"Stride", sizeof(ImVec2),
"Flags", ImPlotItemFlags_NoLegend | ImPlotLineFlags_Shaded
}); I like it because it feels more like other plotting libraries (MATLAB/matplotlib), but I dislike it because it's unlike anything else in ImGui. Anyway, I abandoned it because also couldn't find a way to guarantee compile time evaluation in all scenarios. Could spend more time on it if folks like it. Thoughts?
With the default struct method, I think we are fine? @sonoro1234 what do you make of this?
It's a C++20 feature, unfortunately.
It's still possible to change the padding from the bottom and the spacing between digital plots with |
Yes, I guess that with default struct method is ok. |
I'm fine with a slightly longer name to avoid potential naming conflicts.
I personally wouldn't use either the string or pairs approach, as I'm using C++20. Strings sound not particularly performant. Speaking of performance, one thing to note about large structs initialized through a default arguments (or via designated initializers) is that with many compilers this actually causes codegen to occur at each call site to fill out the struct, even though it's actually constant (the compiler won't generate a common constant struct in .rodata and just pass a pointer). It looks like ImPlotSpec could get quite large and be passed as a default lots of places, so that may cause a surprising amount of codegen. There's a complex reason for this (https://reddit.com/r/cpp/s/ezrziiv9NM has some discussion), but the workaround I found was to declare a
As long as it's still possible to set separately for each series via PushStyle, that works for me. |
Struct approach is good, this is what i would use as well. With variadic args approach and enums for parameters we still do not get hints about what type such parameter accepts unless we compile. With strings we do not get autocompletion for parameters too. Simplest approach is the best and that would be structs, with designated initializers, whenever we graduate to appropriately high standard. |
Probably both |
There’s ImGuiAxis in the main codebase you could use that or decide its more consistent for users to see ImPlotAxis |
It might make sense to create a ImPlotDigitalSpec struct to hold digital-specific settings (it could even be derived from ImPlotSpec so there's still only a single parameter to PlotDigital)? The digital padding/spacing/height thing is kind of an oddity right now in that it affects behavior across multiple series and is done in pixel coordinates. I think spacing is really only useful if you're doing a lot of digital signals in one plot, and even then, the user could relatively easily compute this themselves? It might be less confusing to just remove the padding feature entirely and just have a ImPlotDigitalSpec struct with a Y-axis start value? This could also be a good time to think about whether pixel coordinates make sense for the start and height, or whether changing to something like % of plot height would be better. A more generic solution overall could be #321 (comment) (in which case digital plots could always be full scale), but that major of a change is probably better done as a separate development effort. |
First of all, thanks for having me into consideration! And sorry for the super late reply, I've been meaning to reply to this for ages, but I haven't had the time until now. I think the most important points have been raised already, but just to touch on a few things I'd like to point out that the second API feels more natural (kind of like what MATLAB, Python or other languages do, as you mentioned) while the first option is probably more performant, due to not having to iterate over the initializer list. Also, I haven't looked at the implementation for the first API, but if it takes in an rvalue reference it'd allow to use designated initializers, just like @ocornut mentioned, which is a big plus for people using C++20 and newer. About the naming convention, I too would prefer Another topic I see mentioned quite a few times is the digital plot and its style spec. Since the digital plot is completely different to a line/bar/pie chart, maybe it does make sense to have its style in a different struct. However, I have no strong opinions on this, so if this remains as-is it's fine by me. I still remember some conversations a while ago about doing some rework on the digital plot (issue #321 iirc) so I guess this change could also be made as part of that enhancement, since it would probably add tons of new styling options which might better justify having on its own struct. That's pretty much all I wanted to say. Congrats on this PR! I think it's a nice step forward, and I'm very happy to see progress still being made on this awesome project! 😄 |
First, I'd like to thank @epezent for his ongoing work and dedication, which has made ImPlot so successful. Option 1, using the pure struct approach, is the most straightforward approach to the problem. I would refactor it slightly to exclude data access parameters and flags to represent the pure styling parameters. I would approach the problem by having the user supply a styling struct upon invoking the plot procedure, then, in the callback, supply a reference to the style struct to be modified by the user if the user wants. This way, any relevant parameter such as color, size, or marker could be altered without having a combinatorial explosion of potential Getters.
And a use case example:
In this design, passing the style parameter as const ImPlotStyle& makes sense, which is set to {} by default. |
I'd really love to know @epezent's take on whether more time has provided clarity on which direction to go, and where #332 fits into this. Styling lines and scatters with different sizes and colors would be a really excellent and powerful feature, especially for something like ImPlot/ImGui and its robust support for realtime interactivity. I just finished merging the changes from the #332 PR into a local branch of mine so that I can go ahead and use this functionality, but I would really love to contribute functionality to ImPlot in any way I can. Unfortunately, without clear guidance from maintainers such as @epezent / @ocornut, I'm a little apprehensive to go too far down the wrong path only to have a different solution/direction adopted by the main repository. My main goal is to use this feature to color one line based on the value of another. The approach from #332 has worked so far, coloring the line in the upper right panel based on the distance between the white and red lines in the upper left plot. This is in an effort to write a portable, interactive viewer for weather data used by the NOAA Storm Prediction Center. If in my efforts to write this application, I can provide testing, source code contributions, and ideas, I'd really like to help push this forward if possible -- just point me in the right direction! |
@keltonhalbert Thank you for reaching out. I commented on the status of ImPlot recently in #585 (comment) and the situation remains the same -- I am not actively contributing or addressing PRs at this time, but I am openly welcoming any serious contributors/maintainers to take lead. If you are interested in discussing this, please do not hesitate to reach out via email -- Evan |
Thanks Evan! I'll absolutely be reaching out to you... I've only been spinning myself up on ImGui/ImPlot over the last few months, but I am very interested and invested in seeing this library continue to progress forward. |
This PR implements the new item styling proposal in #330, i.e. using structs passed to
ImPlot::PlotX
functions:ImPlotSpec
1. New enum and structs:
2. Usage Option 1 -- By declaring and defining a struct instance:
3. Usage Option 2 -- Inline using ImProp,value pairs (order does NOT matter):
4. Result:
Other API Changes
SetNextLineStyle
,SetNextFillStyle
,SetNextMarkerStyle
, andSetNextErrorBarStyle
have been removed; pass styling variables directly toPlotX
functions now withImPlotSpec
ImPlotCol_Line
,ImPlotCol_Fill
,ImPlotCol_MarkerOutline
,ImPlotCol_MarkerFill
,ImPlotCol_ErrorBar
have been removed and thus are no longer supported byPushStyleColor
. You can use a commonImPlotSpec
instance across multiple PlotX calls to emulate PushStyleColor behavior.ImPlotStyleVar_LineWeight
,ImPlotStyleVar_Marker
,ImPlotStyleVar_MarkerSize
,ImPlotStyleVar_MarkerWeight
,ImPlotStyleVar_FillAlpha
,ImPlotStyleVar_ErrorBarSize
, andImPlotStyleVar_ErrorBarWeight
have been removed and thus are no longer supported byPushStyleVar
. You can use a commonImPlotSpec
instance across multiplePlotX
calls to emulatePushStyleVar
behavior.ImPlotStyle::/ImPlotStyleVar_ DigitalBitGap
as renamed toDigitalSpacing
;DigitalBitHeight
was removed (useImPlotSpec::Size
);DigitalPadding
was added for padding from bottom.PlotX
offset, stride, and flags parameters are now incorporated intoImPlotSpec
; specify these variables in theImPlotSpec
passed toPlotX
.ImPlotSpec
collapses styling parameters what were previously distinct, i.e.LineWeight
applies to lines, markers, and bar edge size;FillColor
applies to marker fills, shaded regions, bar faces; etc. This means that in some cases the user will not have independent control of e.g. shaded region fill and marker fill (as in the example above). This can be overcome by using multiplePlotX
function calls (e.g. the example above could be aPlotLine
+PlotShaded
+PlotMarkers
for full control). I did this to keep the size ofImPlotSpec
minimal. TBD if this was the right call; willing to consider adding additional variables toImPlotSpec
for finer control sometime in the future (e.g.MarkerFillColor
).These changes will be frustrating to some users, but I cannot reasonably support three different styling paths (
SetNext
,PushStyleVar
, and nowImPlotSpec
).ImPlotSpec
is easier to use, conforms with other plot libraries, and will be simpler to extend in the future.Test Plan
implot_demo.cpp
to use newImPlotSpec
throughout. Confirmed that all demo examples still function and look as before.Future Plans
ImPlotSpec
as was demonstrated in add SetNextColorsData to give per point colors #332 by @niavok