• How do I draw text rotated?
    10 replies, posted
I've been all over the wiki looking at every method with "Text" in its name. I want to draw a DLabel in a gui with the text rotated so that it is vertically up one side of the DPanel it lives in. I haven't found any method on DLabel that would let me draw it rotated. So I considered overriding the panel's Paint and manually drawing rotated text there. However I haven't found any args for any methods that would let me draw the text rotated. Am I missing something? If I'm not, what's the best workaround to do what I'm trying to do?
How to rotate text in gmod?
Thank you! I'd found that and I'd also came up with the idea of creating a texture, drawing the text to that, and then drawing that via DrawTexturedRectRotated. I was hoping that there might be a more straight forward approach than either of these, something that I missed.
I'm going to ignore this solution. It does not work in DPanels due to the rotation occurring about the origin, which is offset when rendering inside a DPanel.
I ran into this problem as well. The solution I found was enclosing the draw functions in a cam.StartOrthoView like so: [code]        local angle = 180;         local sx, sy = self:LocalToScreen(x, y); --this is where you put the position of the text         cam.StartOrthoView(0, 0, ScrW(), ScrH())             cam.Start2D()                 local matrix = Matrix();                 matrix:SetTranslation(Vector(sx, sy, 0));                 matrix:SetAngles(Angle(0, angle, 0));                                                  render.PushFilterMag(TEXFILTER.ANISOTROPIC);                 render.PushFilterMin(TEXFILTER.ANISOTROPIC);                     cam.PushModelMatrix(matrix)                         DisableClipping(true);                             draw.SimpleText("Example", "Default", 0 + 1, 0 + 1, Color(0, 0, 0, 180), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER);                             draw.SimpleText("Example", "Default", 0, 0, Color(255, 255, 255, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER);                         DisableClipping(false);                     cam.PopModelMatrix();                 render.PopFilterMag();                 render.PopFilterMin();             cam.End2D();         cam.EndOrthoView(); [/code]
Jeez, what a ten ton hammer for a simple problem. I hacked together a solution similar to that, which you've just aided by pointing out the existence of LocalToScreen for panels. I really appreciate that. I'm still going to try your full solution because it looks like it'll be much simpler. The observation I made was that a 90 degree rotation of a point can be accomplished by transforming (x,y) -> (-y,x). I got the screen position by looping while self:GetParent(), summing up their offsets (this is the part LocalToScreen helps with), and then drawing the text at -y+x, x+y. Adding together the intended point and its rotated position to cancel it.
Give this ago, used it in something I made ages ago. Not sure how it works with two layers of parenting though function PANEL:DrawRotatedText(text, x, y, color, font, ang) render.PushFilterMag(TEXFILTER.ANISOTROPIC) render.PushFilterMin(TEXFILTER.ANISOTROPIC) surface.SetFont(font) local textWidth, textHeight = surface.GetTextSize(text) local cx, cy = self:LocalToScreen(0, 0) surface.SetTextColor(color) surface.SetTextPos(-textWidth / 2, -textHeight / 2) local m = Matrix() -- Negate the panel's translation m:Translate(Vector(cx + y, cy + x, 0)) m:SetAngles(Angle(0, ang, 0)) m:Translate(Vector(-cx, -cy, 0)) cam.PushModelMatrix(m) surface.DrawText(text) cam.PopModelMatrix() render.PopFilterMag() render.PopFilterMin() end
Of course, life interferes immediately after asking this question. I've decided to go with the code inside Duckfine's answer, then recenter it by putting something like this in to the Paint function of the panel: local x, y = self:LocalToScreen() drawSpecialText("Some Text", -y+x, x+y, 1, 1, -90) There's still some centering I need to do (due to this rotating about a corner of the text bounding box) but, because I just want fancy, vertical headers for some GUI sections, this works just fine. I plan on investigating the answers provided by zamboni and tobiasxzz at a later point, due to the hardcoded nature of my solution. Having said that, I'm sure a clever observer will see that sine and cosine can be used to adjust the offset.
Possibly final update, unless someone knows a solution to my latest problem. tobiasxzz, your technique works great for canceling out the weird offset. zamboni, likewise, looks very close to what I already have, only doing some of the transformations in the matrix rather than after the fact. Unfortunately, none of these work with the fact that the VGUI's culling works based on the original, unrotated vector, and so you get things like this: https://imgur.com/a/OEUlC2c Ah well! I seriously appreciate the help, everyone. I'm gonna start working on drawing to a texture then drawing that as a quad to do an endrun around all this camera manipulation.
If it's not clipping correctly, try using render.SetScissorRect before you draw the rotated text, and use the absolute screen bounds of the area you want to contain the text in. In this case probably just the bounds of the main panel.
While that does let me constraint it to the window, it still clips the top and bottom of the letters when the text's original, horizontal position scrolls above or below, even if its vertical position should still be visible.
Sorry, you need to Log In to post a reply to this thread.