-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
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
Text customization to support disable, underline, strikethrough, hili… #5288
base: master
Are you sure you want to change the base?
Conversation
Hello! |
Change color within text / colored text I have enhanced the ImGui::TextUnformated() method to make it support arbitrary text color, underline, strikethrough, highlight, mask I aslo add one demo for this feature. The code for the demo is shown below. The new TextUnformatted signature was changed to support this feature. The wrapped, disabled, and customization are newly added args with default values. So it should be compatible with existing code.
Those text styles are within a text and can be combined as needed. Here is another demo. It allows the user to adjust the ranges to apply a style and see the result. The code is on Text Customization Branch Any comments please let me know. If it is possible I will create a pull request when ready. Thanks. |
Add one more video for this feature. ImGui.Text.Customization.Video_2022-05-04_132237.mp4 |
The demo/result and images are copied here. Hope it be useful for others who need this feature. I may mistakenly close this PR. I do not know how to open it again. |
Seems there are some warnings are treated as errors. Should I fix them and update the PR again? |
imgui.h
Outdated
}; | ||
|
||
// Find the style for given position | ||
Style GetStyleByPositin(const char* char_pos) const |
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.
a typo in "Positin"?
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.
fixed
imgui_draw.cpp
Outdated
@@ -3535,11 +3535,12 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im | |||
float x = IM_FLOOR(pos.x); | |||
float y = IM_FLOOR(pos.y); | |||
draw_list->PrimReserve(6, 4); | |||
draw_list->PrimRectUV(ImVec2(x + glyph->X0 * scale, y + glyph->Y0 * scale), ImVec2(x + glyph->X1 * scale, y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); | |||
draw_list->PrimRectUV(ImVec2(x + glyph->X0 * scale, y + glyph->Y0 * scale), ImVec2(x + glyph->X1 * scale, y + glyph->Y1 * scale), | |||
ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col); |
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.
unnecessary reformat?
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.
fixed
imgui_draw.cpp
Outdated
ImDrawList _draw_list_text(ImGui::GetDrawListSharedData()); | ||
|
||
// Create a dedicated draw list for text. The reson is that the highlight texts must draw before the text. | ||
// The highlight texts is genrated during the glyph drawing process. |
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.
typo "genrated"
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.
fixed
imgui_draw.cpp
Outdated
ImDrawList* draw_list_text = nullptr; | ||
|
||
|
||
ImDrawList _draw_list_text(ImGui::GetDrawListSharedData()); |
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.
result of ImGui::GetDrawListSharedData()
could be put into the if (customization)
scope
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.
The ImGui::GetDrawListSharedData() is moved to if (customization) scope. The cost is to new and delete a ImDrawList when drawing the text with customization.
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.
That mentioned cost + the fact it means draw list buffers will realloc+copy every frame and not be amortized is very largely in the range of unacceptably slow in Dear ImGui world. It makes me worry about the veracity of your other statement about performances.
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.
If the alloc/free is expensive we can revert to the old logic. The old logic creates a draw_list_text on the stack this may save some time for us.
For the copy logic adding text draw list to the main draw_lists is shown as below. The text draw list has to be created anyway, so the creation cost is the same. The additional cost is the copy logic.
- The VtxBuffer is copied with memcpy should be fast.
- The IdxBuffer is copied with a for loop, may cost a few CPU clocks, but it cannot be avoided. If you have good suggestion, please advise.
if (customization)
{
...
// Append draw_list_text to the main draw_lists
{
unsigned int old_inx_buffer_sz = draw_list->IdxBuffer.Size;
unsigned int old_vtx_buffer_sz = draw_list->VtxBuffer.Size;
draw_list->PrimReserve(draw_list_text->IdxBuffer.Size, draw_list_text->VtxBuffer.Size);
// draw_list_text->VtxBuffer buffer can be memcopied, it contains no relative data
memcpy(draw_list->_VtxWritePtr, draw_list_text->VtxBuffer.Data, draw_list_text->VtxBuffer.Size * sizeof(ImDrawVert));
// draw_list_text->IdxBuffer buffer cann't because the index value in the IdxBuffer points to draw_list_text->VtxBuffer. It need aligned to draw_list->VtxBuffer.
for (int i = 0; i < draw_list_text->IdxBuffer.Size; i++)
{
draw_list->IdxBuffer[old_inx_buffer_sz + i] = (ImDrawIdx)(old_vtx_buffer_sz + draw_list_text->IdxBuffer[i]);
}
draw_list->_VtxWritePtr += draw_list_text->VtxBuffer.Size;
draw_list->_IdxWritePtr += draw_list_text->IdxBuffer.Size;
draw_list->_VtxCurrentIdx += vtx_current_idx;
}
...
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.
That mentioned cost + the fact it means draw list buffers will realloc+copy every frame and not be amortized is very largely in the range of unacceptably slow in Dear ImGui world. It makes me worry about the veracity of your other statement about performances.
Is there a performance benchmark for text, it would be a good idea to test it and compare the performance results.
imgui_widgets.cpp
Outdated
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText); | ||
ImGuiContext& g = *GImGui; | ||
bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set | ||
if (need_backup && warpped) |
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.
typo "warpped"?
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.
fixed
Awesome work! (btw I only skimmed through it, it's not a full review) Just a question, do you have any idea about the performance impact when the PR's features are not used? Does it change anything? |
May I ask (cause I am in the process of making use quite bit of the TextColoring mechanisms) if this entire topic is still WIP or safely useable? thanks. |
It is still WIP. Not merged to master branch yet. |
…ght and mask. # Conflicts: # imgui_draw.cpp
b844bb0
to
c592459
Compare
Thanks for reviewing. For the performance impacts:
|
381d66b
to
38e2b0f
Compare
38e2b0f
to
8ddc119
Compare
@ForrestFeng I have a question about this feature: how does it interact with TreeNode? In #728 it shows that it's possible to colour the text by pushing a style: great, but it doesn't work if one wants to have more fancy colouring in the label. |
Just to be super clear on what I mean, here's what we can do today just be setting styles and calling Text without spacing in between: The question is whether this PR will let us do anything about those uncoloured nodes that are currently |
@Fuuzetsu to avoid misunderstanding can you provide a sample code for what you did on the TreeNode labels? So that I can try to recreate it in my way. Thanks for your comments. |
Actually, I had a look at some of the existing applications linked in imgui README and saw that they are doing exactly what I want. I'm using rust bindings so I apologise but it seems I can do something like this: let node = TreeNode::new(&ident)
.label::<&str, &str>(&lbl)
// Don't render arrow unless we're aggregating orders.
.leaf(!is_aggregate);
let open = node.push(ui);
draw_ctx.ui.same_line_with_spacing(0.0, 0.0);
draw_ctx.ui.text_colored(
imgui_utils::srgb_f32!(#7e77c8).as_imcolor32f(),
"XXXXXXXXXXXX",
); to produce "fancy" partially style labels. So feel free to ignore me, I answered my own question and I think the work here doesn't need to worry about |
The newly released imgui_test_engine/ repo in the test suite include performance comparaison tools. In Test Engine UI check the “Perfs” tabs. You can compare multiple branches and use the perf tool to visualize the results of all runs.
Performance should be compared for both optimized and non-optimized builds.
|
This fork has been provided as a PR to ImGui: ocornut/imgui#5288
I will be spending a little time evaluating some of the ideas from #5288 (here) and #3130 (and #902), they are similar in essence and both PR are giving a good amount of ideas and starting points. I think we need to standardize a set of modifiers while being able to:
Thanks for this! |
Change color within text / colored text
Enhanced the ImGui::TextUnformated() method to make it support arbitrary text color, underline, strikethrough, highlight, mask. This makes the imgui text more expressive.
Please check the demo/result