imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Rotated text and animated icons

Open carasuca opened this issue 6 years ago • 7 comments

Inspired by Font Awesome Animated Icons I added this little hack. ImRotateDemo

Here's the key part from demo code:

void ImRotateEnd(float rad, ImVec2 center = ImRotationCenter())
{
	float s=sin(rad), c=cos(rad);
	center = ImRotate(center, s, c) - center;

	auto& buf = ImGui::GetWindowDrawList()->VtxBuffer;
	for (int i = rotation_start_index; i < buf.Size; i++)
		buf[i].pos = ImRotate(buf[i].pos, s, c) - center;
}

It affects all scoped vertices, be it chars, shapes, images, windows. Should work for #422 and #847, possibly related to #765, #705.

  • no changes to the internals,
  • clipping remains untouched, therefore
  • not the expected behavior for vertical labels,
  • mouse interaction e.g. slider dragging is broken.

Though a huge fan of dear imgui, I don't yet feel how the draw lists are juggled around and when would it break? Is this a good approach or maybe there's some better way to calculate the center or update clip rect after rotation?

Another idea: since it only affects the drawing output, draw lists could embed a projection matrix stack and move it to the render function - currently only a single screen projection matrix is set per frame in D3D11. Bloat ahead.

carasuca avatar Aug 18 '17 11:08 carasuca

Hello,

Nice work ! I like the idea, but I think I'll derivate it for another usage. e.g. when you draw an annotation (not only a text), it could be extremely usefull to adjust the position using a rotation.

ebachard avatar Aug 28 '17 09:08 ebachard

Thanks for sharing this snippet! I was wondering how hard would it be to change the vertices on the drawlist and this looks really simple :)

franciscod avatar Apr 19 '18 18:04 franciscod

@carasuca Apologies for not answering you on this earlier!

Though a huge fan of dear imgui, I don't yet feel how the draw lists are juggled around and when would it break? Is this a good approach or maybe there's some better way to calculate the center or update clip rect after rotation?

It's not a bad approach!

The clipping issue you are experiencing is due to the CPU-side clipping occurring in ImFont::RenderText(). Right now the only way to bypass it would be to rewrite a custom version of ImDrawList::AddText() - which luckily is a small function, especially as you can remove the cpu_fine_clip_rect bits - and pass an infinite clip rectangle to ImFont::RenderText().

If you look in imgui_internal.h there are 3 functions I've been using internally which are taking the same approach of poking into vertices after the fact:

void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1);
void ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x);
void ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp);

For the use we make of them right now it may be the best approach, as we avoid increasing complexity of the rendering function and the cost of touching that data twice isn't enormous as they are only used very occasionally.

As discussed in https://github.com/ocornut/imgui/issues/1700#issuecomment-377583233 I think down the line (not soon) we may decide to standardize those algorithms a little more so that we will be able to use vertex-less replacements for ImDrawList in the future.

For now it's easy to use that approach to do CPU-side "shading" of vertices, here's a silly example:

text_sine

void ShadeVertsAnimSine(ImDrawVert* vert_start, ImDrawVert* vert_end, float phase, float speed, float amplitude)
{
    for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
        vertex->pos.y += sinf(vertex->pos.x * speed + phase) * amplitude;
}

For this specific use you have of rotating. I think we may introduce rotated text functions. I would like to rewrite some of the text rendering code but it isn't a high priority right now (will probably do at the same time the styling is refactored, and for different purposes, but while doing it rotated text may be a good candidate, or at least allow for vertical text). Until then your function is a good way to do it.

Projection matrix: you can use ImDrawList callback to send information to their renderer, so you could perfectly send matrices there. We will probably add a general purpose ImVector in ImDrawList to ease storage of temporary information (and it won't cost anything when not used).

ocornut avatar Apr 19 '18 20:04 ocornut

How to make an animation of the slide from left to right and determine the point on the x-axis where it ends?

TheLoserOFC avatar Jun 13 '20 12:06 TheLoserOFC

I'm a little confused, so if I were to use this, say I wanted to rotate text 90 deg clockwise, how would I do it (only want to do it once so I can have sideways text).

Stanlyhalo avatar Aug 20 '21 17:08 Stanlyhalo

how can text blink in imgui plz help me anyone

flakervipmod avatar Nov 01 '22 03:11 flakervipmod

Please bring your questions to discussions. It is unrelated to the issue.

thedmd avatar Nov 02 '22 00:11 thedmd