Hello,
I'd like modernize ImGui as much as possible for my own needs. I think it's a shame for ImGui to be stuck on pre-C++11 standards, but I do understand that it's a very widely used library and that a large portion of it's users might not even have a choice in this matter. That's why I also think it's important to maintain backwards compatibility wherever possible.
For that reason, I'd like to ask if it's something you'd consider adding, possibly in the form of #ifdef blocks for more modern functionality, or if I should instead fork the repository?
Amongst the features I want to implement are:
std::string in function parametersenum class in place of enumSorry, but I won't use most this in dear imgui and won't accept #ifdef blocks. Project maintenance is already the main concerns here so making it more complicated won't help. It's not only a concern of compatibility: std::string and heap allocations are slow and unnecessary, would deter a non-negligible fraction of large-game engine programmers, and make wrapping instead different languages more difficult. It'd be seriously against the core value and stance of this library to start using that sort of feature. (PS: Pre-emptively I'd also appreciate if this github issue doesn't turn into a debate about the pros and cons of said features.)
The project may however transition to accept/support C++11 at some point, so enum class isn't out of question in the future.
As a personal heuristic I also need to be wary of please-change-everything-suggestions coming from people who aren't established users of the library. Maybe the library isn't for you, maybe it is. If in a few months you are still a user of dear imgui and built things with it perhaps you'll have another point of view. Maybe you'll still want those changes in and then you'll know more about the library and you'll be able to push them yourself (in a fork etc.). But it's a little odd to come forward on Day 1 suggesting this before you intimately feel what the library does and where it is standing.
A way for users to plug their own types into ImGui (like using glm vectors in place of ImVecs)
There's already a way to define implicit cast operators between your types and ImVec2/ImVec4, check imconfig.h
There's already a way to define implicit cast operators between your types and ImVec2/ImVec4, check
imconfig.h
This slipped past me, thanks!
To be clear, I've been using ImGui in my own and work projects for some time, so this is a cumulation of some frustrations I've had over that time :) I think ImGui is an exceptional library for many uses, but since I've only ever used it as a debugging and/or prototyping library, many of the things I've mentioned are big friction points for me, though I do understand why they're advantages for other kinds of use.
However, I do understand all of the concerns you expressed, that's why I've opened this issue -- to see what your stance on the issue is :)
I think it's more than reasonable to try and keep imgui as lightweight and nimble as possible. However, it seems to me that there's two big groups to imgui users -- big hitters and serious developers, and light users who are just prototyping and/or want a dead simple gui for a demo they're making.
With that in mind, would you be okay with me forking imgui and shaping it into a more simplistic, ready-to-go library for quick prototyping?
With that in mind, would you be okay with me forking imgui and shaping it into a more simplistic, ready-to-go library for quick prototyping?
Why not just build a C++11/C++14/C++17 wrapper on top of imgui and publish that? :-)
You wouldn't get any speed benefits since the underlying layer is still imgui, but if done right there wouldn't be any costs either, while it would be much easier to code it.
Thanks for understanding.
If you wish to clarify why those are big friction points for you I am interested in hearing details and see if we can address some.
Where it is what you need to use strings?
Where do you ever need use lambdas? If the lambdas are to use the awful Combo/ListBox api, they are being fixed as we speak (there is a BeginCombo api now and you can submit your stuff in however format you need, and manage your selection state without indices).
With that in mind, would you be okay with me forking imgui and shaping it into a more simplistic, ready-to-go library for quick prototyping?
Sure! But I'd appreciate if you made it clear in the readme that you forked around version X date X, and maybe give it a name that suggest it is a modified version. Forks of that nature are really difficult to maintain so clarifying that ahead is useful if it ends up unmaintained.
A helper/wrapper lib makes more sense to me too. Also you'd probably want to use string_view not string to avoid the heap allocs. Allocating tons of strings per frame will destroy perf.
I agree that a wrapper library is probably the best way to go here. It will be much easier to maintain than a fork. If I could make it work as an extra header, that could be included after imgui.h, it might be the best way to go. I'll think it over a bit more.
Where it is what you need to use strings?
The main issue here is that I love to use fmtlib (which allows a python-like formatting string syntax) to format stuff, and I can't just pass strings created through fmtlib to ImGui, because they get deallocated if I don't store them.
ImGui::Text(fmt::format("{}: {}", foo, bar).c_str()); // Segfaults
That could be mitigated if the ImGui API also had overloads for const std::string&, because that prolongs the lifetime as necessary if I'm correct.
Where do you ever need use lambdas?
I'm glad to hear that the ComboBox API is being worked on! One of the main ideas I wanted to try out is using lambdas to automatically manage Begin-End blocks, like windows and so on. There's a trick I saw in a talk at CppCon, which uses a clever trick to introduce a trailing block syntax to C++, which could be a really intuitive way to improve some of the ImGui API. See below for an example.
namespace ImGui {
struct _windowHelper {
_windowHelper(const char* n)
: name { n }
{ }
template <typename F>
void operator+(F&& f) {
ImGui::Begin(name.c_st());
f();
ImGui::End();
}
std::string name;
};
}
#define Window(X) _windowHelper(X) + [&]
// Usage:
ImGui::Window("Hello") {
ImGui::Text("Hello, world!");
};
Now this is mostly a hack and probably shouldn't be used in any public-facing code, but for rapid prototyping, it could solve a lot of "oh, I forgot ImGui::End/ImGui::Pop" aborts.
ImGui::Text(fmt::format("{}: {}", foo, bar).c_str()); // Segfaults
I use those patterns all the time with my own string class, unless I am mistaken (and maybe I am) I don鈥檛 think your temporary rvalue should be destructed before the return of the Text() function?
As for the other thing as you pointed out you can do it as an extra header/layer on your side without modifying imgui.
Tho I think eventually we should provide helper for stylevar and color setter than would pop themselves during destruction.
I use those patterns all the time with my own string class
I just tried and it works fine. I don't know where I got the idea that this doesn't work, but I remember having issues with it. I'll see if I can find anything reproducible :)
One thing came up today while working on some of the wrapper functions -- some of the function signatures could have better types on their parameters. For example ImGui::PlotLines (or any similar function) takes values_count as an int, whereas it should probably be size_t?
The code moved to int in 2015 because it largely reduced the amount of warnings and casting involved. For this case of user-facing sizes in the API (which are not so common: essentially Plot, Combo, ListBox) possibly size_t would make more sense. May change their signature altogether at some point.
The main reason for this are the warnings generated when using std::vector::data and std::vector::size, which returns size_t. Moreover, this doesn't the users to pass more than std::numeric_limits<int>::max() values to the functions (albeit that's probably the edgiest of edge cases 馃槃 )
Moreover, this doesn't the users to pass more than std::numeric_limits
::max() values to the functions
That's perfectly acceptable!
Closing this topic now as it seems all the topics have been mentioned. Soon I will also rework ListBox the same way Combo was reworked, though the old ListBoxHeader is essentially equivalent to BeginCombo etc.
I am taking notes and want to reconsider changing some arguments to size_t but this at minimum won't happen until a major spring-cleanup of the api (2.0)
As for the begin/end stack helpers you mentioned, someone sent this to me a few days ago:
https://hastebin.com/ugiresenih.cpp
Also attaching a copy here:
imgui_cpp_helpers.zip
Selected extracts to get the gist of it:
struct _Window {
bool res = false;
_Window(const char* name, bool* open = nullptr, ImGuiWindowFlags flags = 0) { res = Begin(name, open, flags); }
template<typename F> bool operator+(F&& f) { f(); End(); return res; }
};
#define Window(...) _Window(__VA_ARGS__) + [&]
struct _WithStyleColor {
_WithStyleColor(ImGuiCol idx, ImU32 col) { PushStyleColor(idx, col); }
_WithStyleColor(ImGuiCol idx, const ImVec4& col) { PushStyleColor(idx, col); }
template<typename F> void operator+(F&& f) { f(); PopStyleColor(); }
};
#define WithStyleColor(...) _WithStyleColor(__VA_ARGS__) + [&]
So that's using the same technique you referred above.
Using preprocessor defines with such short and unqualified names is problematic IMHO, but some people could tweak it and build on the idea.
Most helpful comment
Sorry, but I won't use most this in dear imgui and won't accept
#ifdefblocks. Project maintenance is already the main concerns here so making it more complicated won't help. It's not only a concern of compatibility:std::stringand heap allocations are slow and unnecessary, would deter a non-negligible fraction of large-game engine programmers, and make wrapping instead different languages more difficult. It'd be seriously against the core value and stance of this library to start using that sort of feature. (PS: Pre-emptively I'd also appreciate if this github issue doesn't turn into a debate about the pros and cons of said features.)The project may however transition to accept/support C++11 at some point, so
enum classisn't out of question in the future.As a personal heuristic I also need to be wary of please-change-everything-suggestions coming from people who aren't established users of the library. Maybe the library isn't for you, maybe it is. If in a few months you are still a user of dear imgui and built things with it perhaps you'll have another point of view. Maybe you'll still want those changes in and then you'll know more about the library and you'll be able to push them yourself (in a fork etc.). But it's a little odd to come forward on Day 1 suggesting this before you intimately feel what the library does and where it is standing.
There's already a way to define implicit cast operators between your types and ImVec2/ImVec4, check
imconfig.h