You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In case its of any use to anyone
NB there is a bug in this code:
Imgui clips the text before it is rotated. This means text at the edges can have parts missing
(as you can see in this image with the text at the right: epezent/implot#523).
2023-10-14.10-46-41.mp4
To run the example just call from the main imgui render loop drawRotatedText()
//Initial code for this comes from: https://gist.github.com/carasuca/e72aacadcf6cf8139de46f97158f790f
// It doesn't seem to have a license statement, so I'm assuming it's public domain
#include "imgui_internal.h"
//internal bounding boxes
// BB = outermost 'true' bounding box (including bounding box for handles)
// DR = bounding box for drawing
// IN = inner (ie inside bufferzone for boundaries handles
// CE = centron (prob central 10%)
// TL...B = bb for handles for grabbing the various edges/corners
enum bbEnum { BB_BB, BB_DR, BB_IN, BB_CE, BB_TL, BB_TR, BB_BL, BB_BR, BB_L, BB_R, BB_T, BB_B };
int rotation_start_index;
void ImRotateStart()
{
rotation_start_index = ImGui::GetWindowDrawList()->VtxBuffer.Size;
}
ImVec2 ImRotationCenter()
{
ImVec2 l(FLT_MAX, FLT_MAX), u(-FLT_MAX, -FLT_MAX); // bounds
const auto& buf = ImGui::GetWindowDrawList()->VtxBuffer;
for (int i = rotation_start_index; i < buf.Size; i++)
l = ImMin(l, buf[i].pos), u = ImMax(u, buf[i].pos);
return ImVec2((l.x + u.x) / 2, (l.y + u.y) / 2); // or use _ClipRectStack?
}
void ImRotateEnd(float rad, ImVec2 center = ImRotationCenter())
{
// Adjust the angle to match the standard horizontal orientation
rad -= IM_PI / 2.0f; // Subtract 90 degrees (PI/2 radians)
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;
}
void drawRotatedText(std::string textToRotate, float angleToRotate = 0, bbEnum rotationCentre = BB_CE, bool isRads = true)
{
// Calculate rotation angle in radians
float rad = angleToRotate;
if (!isRads)
rad = rad * IM_PI / 180.0f;
ImVec2 textStartPosition = ImGui::GetWindowPos() + ImGui::GetCursorPos(); // ImRotateEnd uses GetWindowDrawList which is based on position of the screen
// Calculate text size to determine bounding box
ImVec2 textSize = ImGui::CalcTextSize(textToRotate.c_str());
ImVec2 rotationCenter;
// Calculate rotation center based on bbEnum value
switch (rotationCentre)
{
case BB_CE:
rotationCenter = ImVec2(textStartPosition.x + textSize.x * 0.5f, textStartPosition.y + textSize.y * 0.5f);
break;
case BB_TL:
rotationCenter = textStartPosition;
break;
case BB_TR:
rotationCenter = ImVec2(textStartPosition.x + textSize.x, textStartPosition.y);
break;
case BB_BL:
rotationCenter = ImVec2(textStartPosition.x, textStartPosition.y + textSize.y);
break;
case BB_BR:
rotationCenter = ImVec2(textStartPosition.x + textSize.x, textStartPosition.y + textSize.y);
break;
case BB_L:
rotationCenter = ImVec2(textStartPosition.x, textStartPosition.y + textSize.y / 2);
break;
case BB_R:
rotationCenter = ImVec2(textStartPosition.x + textSize.x, textStartPosition.y + textSize.y / 2);
break;
case BB_T:
rotationCenter = ImVec2(textStartPosition.x + textSize.x / 2, textStartPosition.y);
break;
case BB_B:
rotationCenter = ImVec2(textStartPosition.x + textSize.x / 2, textStartPosition.y + textSize.y);
break;
default:
std::cout << "ERROR: invalid rotationCentre in drawRotatedText\n";
return;
}
// Start rotation
ImRotateStart();
// Render the text
ImGui::Text(textToRotate.c_str());
// Apply the rotation
ImRotateEnd(rad, rotationCenter);
}
void drawBbEnumExamples(float rotationAngle)
{
// Create a child window
ImGui::BeginChild("BbEnumExamplesChild", ImVec2(500, 500), true);
// Base coordinates for the middle point of our layout area
const float midX = 250.0f;
const float midY = 250.0f;
const float xOffset = 110.0f; // Horizontal distance from center
const float yOffset = 110.0f; // Vertical distance from center
// Calculate starting positions for each enum based on their logical position
ImVec2 positions[12];
positions[BB_TL] = ImVec2(midX - xOffset, midY - yOffset);
positions[BB_T] = ImVec2(midX, midY - yOffset);
positions[BB_TR] = ImVec2(midX + xOffset, midY - yOffset);
positions[BB_L] = ImVec2(midX - xOffset, midY);
positions[BB_CE] = ImVec2(midX, midY);
positions[BB_R] = ImVec2(midX + xOffset, midY);
positions[BB_BL] = ImVec2(midX - xOffset, midY + yOffset);
positions[BB_B] = ImVec2(midX, midY + yOffset);
positions[BB_BR] = ImVec2(midX + xOffset, midY + yOffset);
// Iterate over each bbEnum and display the text and its rotated version
for (int i = 0; i < 12; i++)
{
// Determine the cursor position based on the current index
ImGui::SetCursorPos(positions[i]);
// Get the enum name as a string
std::string enumName = "";
switch ((bbEnum)i)
{
case BB_CE: enumName = "BB_CE"; break;
case BB_TL: enumName = "BB_TL"; break;
case BB_TR: enumName = "BB_TR"; break;
case BB_BL: enumName = "BB_BL"; break;
case BB_BR: enumName = "BB_BR"; break;
case BB_L: enumName = "BB_L"; break;
case BB_R: enumName = "BB_R"; break;
case BB_T: enumName = "BB_T"; break;
case BB_B: enumName = "BB_B"; break;
default: continue;
}
// Adjust cursor position for the rotated text based on text size
ImVec2 textSize = ImGui::CalcTextSize(enumName.c_str());
ImVec2 halftextSize = textSize * 0.5f;
ImVec2 cursorPos = positions[i] - halftextSize;
ImGui::SetCursorPos(cursorPos);
// Draw the unrotated text
ImGui::Text(enumName.c_str());
ImGui::SetCursorPos(cursorPos);
// Draw the rotated version
drawRotatedText(enumName, rotationAngle, (bbEnum)i);
}
ImGui::EndChild();
}
void drawRotatedText() {
ImGui::Begin("Rotated Text Example");
// Create a child window
ImGui::BeginChild("RotatedTextChild", ImVec2(-1, -1));
drawBbEnumExamples(0.0005f * ::GetTickCount());
/*
ImGui::SetCursorPos({ 100, 100 });
ImRotateStart();
ImGui::Text(__FUNCTION__);
ImRotateEnd(0.0005f * ::GetTickCount());
ImRotateStart();
ImGui::SameLine();
ImGui::Text("Freeze On Hover");
static float rot = 0;
if (!ImGui::IsItemHovered()) {
rot = 0.0009f * ::GetTickCount();
}
ImRotateEnd(rot);
ImVec2 winPos = ImGui::GetWindowPos();
ImVec2 mPos = ImGui::GetMousePos();
float halfWidth = ImGui::CalcTextSize("mouse Rotation Test").x / 2;
ImVec2 cPos = mPos - winPos;
cPos.x -= halfWidth;
//cPos.y += halfWidth;
ImGui::SetCursorPos(cPos);
ImRotateStart();
ImGui::Text("mouse Rotation Test");
ImRotateEnd(0.002f * ::GetTickCount());
*/
ImGui::EndChild();
ImGui::End();
}
The text was updated successfully, but these errors were encountered:
In case its of any use to anyone
NB there is a bug in this code:
Imgui clips the text before it is rotated. This means text at the edges can have parts missing
(as you can see in this image with the text at the right: epezent/implot#523).
2023-10-14.10-46-41.mp4
To run the example just call from the main imgui render loop
drawRotatedText()
The text was updated successfully, but these errors were encountered: