imtui
imtui copied to clipboard
Passing character info to renderer
Currently, imtui uses a modified ImFont::RenderText
function where it inserts the ascii value of the character to be rendered in the alpha channel of the color (ImDrawVert.col
). While this makes imtui possible, it requires a modification to imgui itself achieve, which makes long term maintenance an issue.
Here is a proposed way to pass the character values by using the coordinates in the font texture instead. Proof of concept code below.
std::unordered_map<int, uint8_t> character_lookup; // <-- needs persistence: global, class var, function param, etc.
auto io = ImGui::GetIO();
// tell imgui we have lots of 1x1 custom character glyphs in the texture
int ids[255]; //store the returned id's
for (int i = 1;i<255;i++) {
ids[i] = io.Fonts->AddCustomRectFontGlyph(font, i, 1,1,1);
}
// Build atlas [existing code block]
unsigned char* tex_pixels = NULL;
int tex_w, tex_h;
ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
// store the texture coordinates in a hashmap
for (int i = 1;i<255;i++) {
//lookup the id we got, and get the texture coordinates (in integer pixel values)
const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(ids[i]);
// store the texture index with the character value
character_lookup[rect->X + rect->Y*rect->Width] = i;
}
Then, in the render function, once it's determined this is a textured 1x1 glyph, read the position in the texture to get the character index:
// get the texture scale (could be stored)
ImVec2 font_scale = ImGuiIO().Fonts->TexUvScale;
// uv coords are [0..1], remap to integer values that match the rect we got when storing
int index = uv0.x/font_scale.x+uv0.y/font_scale.y;
auto char_code = character_lookup[index];
cell |= char_code;
I've tested this and it works without issue, with some error handling, etc. Posting here for input and ideas before making a PR.
I believe many of the other changes in the local fork of imgui can be resolved when the work on "style V2" commences. (See, for example, https://github.com/ocornut/imgui/issues/2017)
Ok, that is pretty clever.
I'll let you know if I get some ideas about this, but at the moment your concept seems much better than the existing one.