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
Change color within text / colored text #902
Comments
You'd need to write a custom function that does some sort of mark-down-ish parsing and render as it goes. |
I have a simple one I made for my own use on a project but it's not really fit for use elsewhere. You can grab here but it'd need fixing/reworking/finishing if you want to use it in your own project. |
The difficulty with it as a separate top-level function is that many ImGui functions take text as an argument (e.g. buttons, trees). I think that ImGui needs some kind of standard escape mechanism even if the particulars are left up to the application to interpret the content. |
That's a good point, we could have an escape mecanism for simple stuff (such as color change?), maybe with the possibility of enabling/disabling/setting a custom one. What sort of feature would you want to use and in what sort of context? |
Also worth reminding that text size calculation can be a noticeable bottleneck for large UI and therefore this has to be handled properly to not affect perfs too much. If the marking/escaping mechanism is optional it gives more flexibility there (because we aren't concerned by performances as much anymore). Related because closely related: the shortcut system (#456) will also needs a way to render underscore, probably tagged Windows-style where "&File" will render an underscore under the F, potentially optional (for regular buttons, modern Windows tends to hide the underscore using ALT is held). |
About text size calc maybe worth doing some caching. Most of the strings being rendered will be fixed and be rendered again every frame. |
Would be worth it.
So that's some work and a different feature that discussed here. Something to keep in mind. For now implementing the marking/escaping would go first. |
Note that current text size computation is already fairly lightweight (inner loop pulling from a hot-only dense array of XAdvance values), so replacing it with Hash + Lookup isn't going to be trivial massive win. |
The main one I want has been highlighting a search substring in lists/trees. The escape mechanism feels like it fits in the best with ImGui design because so many entrypoints take strings as parameters. |
Possible features:
And what would be the syntax? Feels like using |
ANSI escape codes cover that feature set so that's one possibility. If some other syntax is used, I'd prefer some non-printable character so that all existing strings continue to work without change. |
Having something similar to BBCode would be amazing. |
Are you suggesting you would want it applied pervasively or as a separate entrypoint? I'd be concerned if something like BBCode/Markdown/HTML were applied at the lowest level of string formatting as escaping source data is a lot more annoying/expensive with an immediate mode API. |
since I am familiar with ANSI escape codes, that one gets my vote |
I am curious. Is there any update about this topic? |
None. Someone may want to get ahead toward a proof of concept. I know it'll take me too much time (several full days) to do it totally properly and with perf/options I'm happy with, so I'm not looking into it at all now. |
Note that #986 is suggesting using a similar feature during text edition.
I don't think the suggested solution would be appropriate, but we can keep in mind and consider how coloring might work in text edition in the future. |
Finally for the moment i use a special buffer who have the same length as the buffer of the text multi line control. and each char corresponding to a color settings in an array in ImGuiStyle.
So i have 254 possibility of coloration. My function analyse the buffer by the callback when i edit some things and format the color of words in the special buffer passed to the multi-line control. and in void ImFont::RenderText, i do that : the buffer is a 'const char* syncol'
It work like a charm. so now i need to write a good syntax coloring func for my needs :) |
In Overgrowth I added the ##FFFFFFFF style coloring like this: https://gist.github.com/David20321/9e349d197b19e4919614652e4c0d175b Doesn't work for editable text, just for display. |
Actually, I was going to implement this myself with my own copy. ;) Perhaps along with embedding icons inside text, but I doubt that would ever be added. |
Your game looks amazing! Would be nice if you could post some shots showcasing your use of imgui in the screenshots threads sometime.
Merging an icon font such as FontAwesome into the main font is very easy and very very useful. Read the documentation in extra_font. I am using https://github.com/juliettef/IconFontCppHeaders as a helper to get |
@ocornut That's possible, but then you can't have icons using multiple colours, can you? But then, I'm not sure why anyone would want full-colour icons outside of development tools. |
@bluebear94 You can't indeed. Give it a try someday, using FontAwesome merged within ImGui default font, it's really super convenient. Considering adding it to the demo app. |
I have a bit of a hack I'm using that works alright for my purposes (a read-only multiline buffer.) Not industrial-grade, but here goes:
Then, use Unicode 0x100rgb to represent your color (0x108000 resets to default color.) |
Hi there! I just wanted to share my simple solution to embed colors in ImGui text. I basically parse the string while accumulating characters and looking for inline color blocks. When found I extract the color, then I simply use The code supports 6-char colors (RGB), and 8-char colors (ARGB). Using an empty color block simply returns to the default color. You can find the code here on PasteBin. Here's how it's used, using "{" and "}" to mark colors:
That's a pretty simple solution that works only for regular text, but that's all we really needed for now. |
I made a simple edit to RenderText to support Quake style color codes. It's rather simple, ^ is used as an escape followed by an index into the color code list.
There's unfortunately some cursor funkiness in my input fields, I'll update the comment when I get around to fixing it. Edit: Here we go, changing InputTextCalcTextSizeW seems to have worked out. If anyone thinks there's a better way I'm all ears.
|
https://gist.github.com/ddovod/be210315f285becc6b0e455b775286e1 |
While this doesn't cancel/replace the need for a low-level, general mechanism to colorize text, I should mention that @juliettef today released an imgui_markdown helper which would probably satisfy the related need of showing less bland chunk of information: https://github.com/juliettef/imgui_markdown I added it to the wiki and this is also a reminder that however humble there is a wiki gathering links. Also from this specific tool, I would like to later expose new text colors in ImGuiStyle, namely to denote "highlight/bold" or "link" colors. This is so whatever color changing mechanism we expose should be able to use generic semantic such as "highlight/bold" instead of refering to hardcoded RGB colors. (Of course hardcoded RGB should still be possible, but we want to maximize the style-portability of common uses). |
I did a very simple extension implementation for a callback based custom tags processing here (there is more than rich text): With this, one call like:
results in this: This requires two callbacks to be implemented by the user, one wich calculates the area to be drawn for some tag, and another that do the drawing itself. The implementation from this sample is here. |
@ddovod I have made a port of this functionality on a fork of |
I wish we could have inline color commands to make the type darker, but that doesn't exist (yet) without custom solutions ocornut/imgui#902
Colorful text. Type the character you have specified for the color you want after the $ sign. Example: static const auto& code = R"($r#include $y<iostream>
$busing namespace $wstd$l; $d// for easy
$bauto $wmain$l() -> $bint $l{
$pif $l($o2 $l+ $o2 $l== $o4$l)
$wcout $l<< $f"Hello, World." $l<< $m'\n'$l;
$preturn $o0$l;
};
)";
static const ImVec4&
white = { 1,1,1,1 },
blue = { 0.000f, 0.703f, 0.917f,1 },
red = { 0.976f, 0.117f, 0.265f ,1 },
grey = { 0.230f, 0.226f, 0.289f,1 },
lgrey = { 0.630f, 0.626f, 0.689f,1 },
green = { 0.000f, 0.386f, 0.265f,1 },
lime = { 0.55f, 0.90f, 0.06f,1 },
yellow = { 0.91f, 1.00f, 0.21f,1 },
purple = { 1,0,1,1 },
orange = { 1.00f, 0.36f, 0.09f,1 };
ColorfulText(code, {
{'w', white},
{'b', blue},
{'d', grey},
{'l', lgrey},
{'f', green},
{'m', lime},
{'y', yellow},
{'p', purple},
{'r', red},
{'o', orange}
}); Souce Codeusing str = std::string;
template <typename T>
using list = std::pmr::vector<T>;
namespace im = ImGui;
void ColorfulText(const str& text, const list<pair<char, ImVec4>>& colors = {}) {
auto p = im::GetCursorScreenPos();
const auto first_px = p.x, first_py = p.y;
auto im_colors = ImGui::GetStyle().Colors;
const auto default_color = im_colors[ImGuiCol_Text];
str temp_str;
struct text_t {
ImVec4 color;
str text;
};
list<text_t> texts;
bool color_time = false;
ImVec4 last_color = default_color;
for (const auto& i : text) {
if (color_time) {
const auto& f = std::find_if(colors.begin(), colors.end(), [i](const auto& v) { return v.first == i; });
if (f != colors.end())
last_color = f->second;
else
temp_str += i;
color_time = false;
continue;
};
switch (i) {
case '$':
color_time = true;
if (!temp_str.empty()) {
texts.push_back({ last_color, temp_str });
temp_str.clear();
};
break;
default:
temp_str += i;
};
};
if (!temp_str.empty()) {
texts.push_back({ last_color, temp_str });
temp_str.clear();
};
float max_x = p.x;
for (const auto& i : texts) {
im_colors[ImGuiCol_Text] = i.color;
list<str> lines;
temp_str.clear();
for (const auto& lc : i.text) {
if (lc == '\n') {
lines.push_back(temp_str += lc);
temp_str.clear();
}
else
temp_str += lc;
};
bool last_is_line = false;
if (!temp_str.empty())
lines.push_back(temp_str);
else
last_is_line = true;
float last_px = 0.f;
for (const auto& j : lines) {
im::RenderText(p, j.c_str());
p.y += 15.f;
last_px = p.x;
max_x = (max_x < last_px) ? last_px : max_x;
p.x = first_px;
};
const auto& last = lines.back();
if (last.back() != '\n')
p.x = last_px;
else
p.x = first_px;
if (!last_is_line)
p.y -= 15.f;
if (i.text.back() != '\n')
p.x += im::CalcTextSize(last.c_str()).x;
};
im_colors[ImGuiCol_Text] = default_color;
im::Dummy({ max_x - p.x, p.y - first_py });
}; |
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 all with 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 |
This currently maps to coloring the text red. When ImGui's ticket ocornut/imgui#902 is resolved, one can look into supporting additional markup. For now, this should be sufficient.
Still seems to be a lot of interest in this. Has support for this been pulled into the official ImGui yet? |
I'm a little puzzled why many people are writing messages on an open pull-request or issues asking if the PR/issue has been solved :) no it hasn't. But I have been recently working on new low-level text functions and I am confident we can make interesting progress on this in the coming quarters (borrowing some ideas from #3130 and #5288 but with a different implementation). |
That's awesome! Personally, I hope that any official support for this can be customized; many people already seem to have this "hacked in" with their own syntax. For example, in my case this would be Additionally, I also implemented text shadow using the |
I don't have answer for this yet A few things that are certain:
Uncertain but obviously desirable:
|
Example of ANSI text rendering:
Maybe use these as an idea for text colours. They are a bit old, so they might be incompatible with recent ImGui versions. |
Hi there, I was wondering if there was any way to change from color while still using the ::Text function, e.g:
ImGui::Text("Please fill in your #FF0000 to #0000FFlogin.");
Thanks.
The text was updated successfully, but these errors were encountered: