Closed pixtur closed 1 month ago
imgui_test-engine has a system where you can e.g. query item geometry from an identifier, e.g. ctx->ItemInfo("//MyWindow/MyButton").Rect
which is implemented via hooks in ItemAdd() (IMGUI_TEST_ENGINE_ITEM_ADD(...)
) and hooks in end of widget code (calling IMGUI_TEST_ENGINE_ITEM_INFO()
). But otherwise it is not possible in the main library. And even so the one in test engine is not designed to be called from the UI context as it may be a multi-frame query.
I would annotate your code with a helper:
Button("Test");
RecordItemGeometry();
void RecordItemGeomtry()
{
...
if (GetItemID() == requested_id)
copy GeItemRect() somewhere
}
Thanks a lot! That's already great advice. I know, it's a silly question, but would RecordItemGeometry()
have any chance of inferring the string "Test" (or its Hash) used for the ID of the last item?
but would RecordItemGeometry() have any chance of inferring the string "Test" (or its Hash) used for the ID of the last item?
Not really (unless using test engine which has a more complex machinery). But it's not necessary, since you can do it the other way: infer the hash from the strings and compare hashes.
The ID is the hash, the hash gets calculated with a seed from the current ID stack and therefore doesn't depend on the label alone. It is not possible to retrieve the text given to the previous item unless you copy it out with a custom test engine implementation. But you don't need to infer if you have access to all parameters by way of making wrappers:
namespace ImGuiEx
{
bool Button(const char* label, const ImVec2& size = ImVec2(0, 0))
{
// ...
ImGui::Button(label, size);
// ...
}
}
If you create wrappers for all the items you need to be extended, you can add all the extra logic you need into those wrappers and keep your actual UI code clean.
Thanks for these awesome replies!
The ID is the hash; the hash is calculated with a seed from the current ID stack and therefore doesn't depend on the label alone.
I am aware of how the ID stack works, although I don't know the implementation details. My crazy idea was to look back at the ID stack and somehow use the difference between the last ID and the current (hashed) ID to extract the ID that was generated from the label. This might then be used without the need for wrappers to test with something like a query selector (e.g. find all Buttons with Label "Test"). Obviously, that is crazy.
Wrappers are the way to go. In fact, I already have wrappers for most of the UI components to reverse the label position. So extending these is the better way to implement this without relying too much on guessing and relying on ImGui internals.
I have all the information I need to get started. I will post an update here if I have something going.
Version/Branch of Dear ImGui:
Version 1.87.3, Branch: Master
Back-ends:
Imgui.net
Compiler, OS:
windows 10
Full config/build information:
No response
Details:
My Issue/Question: I want to implement a widget to guide users through an onboarding tour or through manual tests of an ImGui application.
I want to define tour steps with a message and a reference to one or more relevant UI elements like:
A naive approach could be to add callbacks behind all relevant UI elements so the tour widget could register to these and then use
GetLastItemRect()
to add borders to the window foreground drawlist:Obviously, this approach is error-prone, does not scale, and has a severe performance impact.
I wonder if ImGui already has something like a callback mechanism for things like this. Maybe in a first step, use something like a CSS-query selector to "capture" an ID and then have some kind of callback whenever this ID is being drawn.
I imagine the metrics-window element picker does something like this internally.
I know this is neither a real issue nor a feature request. Feel free to close this if you feel it’s too generic.
Screenshots/Video:
A sketch of how the tour/testing widget might look like:
Minimal, Complete and Verifiable Example code:
No response