Jump to content

dxGetFontHeight problem


Dzsozi (h03)

Recommended Posts

Hello!

Today I started editing this script: https://community.multitheftauto.com/in ... ls&id=5812

I want to make it look like GTA V top left corner notifications.

maxresdefault.jpg

My only problem is that when wordBreak is being applied to the dxDrawText the dxDrawRectangle keeps going to the right side, but it's not going downside. So the rectangle's size is perfect for one line, but if there's more lines it's messed up.

One line (perfect):

11888562881_www.kepfeltoltes.hu_.png

Two or more lines (messed up):

277403742_www.kepfeltoltes.hu_.png

Part of the code:

  
local x,y = 50 * sx / 1920, 50 * sy / 1080 
local textX,textY = x, y 
local textWidth,textHeight = 363,106 
local hosszusag = dxGetTextWidth (tipBox.string, 1, "default-bold") 
local magassag = dxGetFontHeight(1,"default-bold") 
--dxDrawImage (x,y,width,256,tipBox.path,0,0,0,tocolor(255,255,255),true) 
dxDrawRectangle(x, y, hosszusag+10 * sx / 1920, magassag+10 * sy / 1080, tocolor(0, 0, 0, 185), true) 
dxDrawText (tipBox.string,x+5,y+5,textX+textWidth,textY+textHeight,tocolor(222,222,222),1,"default-bold","left","top",false,true,true) 
  

I hope that somebody could help me!

Thank you!

P.S.: Sorry for the bad English if there was something written wrong, I'm from Hungary!

Link to comment
  • MTA Team

You did the rectangle calculations incorrectly. You were not binding the width and height to the text width and height, which caused it to flow to the right if I understand your calculations correctly.

The way it should work is that you bind the width and height correspondingly to the text bounds.

I was able to render the box properly, though right now I do not recall a way to calculate the height of text, which is why you have to specify the height separately.

local tipBox = { string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut massa eget purus pharetra lobortis. Etiam efficitur pulvinar lorem vel suscipit. Nam vel erat sed arcu tristique tempus. Donec lacinia eleifend lorem, at accumsan nunc hendrerit non. Donec pulvinar lobortis metus, vitae venenatis urna. Nunc id leo velit." } 
local screenWidth, screenHeight = guiGetScreenSize( ) 
local boxX, boxY = 5 * screenWidth / screenWidth, 5 * screenHeight / screenHeight 
local boxPadding = 5 
local textWidth, textHeight = 363, 106 
local boxWidth, boxHeight = textWidth + ( boxPadding * 2 ), textHeight + ( boxPadding * 2 ) 
local textX, textY = boxX + boxPadding, boxY + boxPadding 
  
--dxDrawImage( boxX, boxY, boxWidth, boxHeight, tipBox.path, 0, 0, 0, tocolor( 255, 255, 255, 255 ), true ) 
  
dxDrawRectangle( boxX, boxY, boxWidth, boxHeight, tocolor( 0, 0, 0, 185 ), true ) 
dxDrawText( tipBox.string, textX, textY, textX + textWidth + boxPadding, textY + textHeight + boxPadding, tocolor( 222, 222, 222, 255 ), 1, "default-bold", "left", "top", false, true, true ) 

I did not run this on Multi Theft Auto however, as I do not have Multi Theft Auto installed on this machine, but on my other rendering software I was able to render it fine as supposed to.

You may also try on Lua demo with the code below:

function guiGetScreenSize( )return 1920,1080 end 
  
local tipBox = { string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ut massa eget purus pharetra lobortis. Etiam efficitur pulvinar lorem vel suscipit. Nam vel erat sed arcu tristique tempus. Donec lacinia eleifend lorem, at accumsan nunc hendrerit non. Donec pulvinar lobortis metus, vitae venenatis urna. Nunc id leo velit." } 
local screenWidth, screenHeight = guiGetScreenSize( ) 
local boxX, boxY = 5 * screenWidth / screenWidth, 5 * screenHeight / screenHeight 
local boxPadding = 5 
local textWidth, textHeight = 363, 106 
local boxWidth, boxHeight = textWidth + ( boxPadding * 2 ), textHeight + ( boxPadding * 2 ) 
local textX, textY = boxX + boxPadding, boxY + boxPadding 
  
print( "box x: " .. boxX ) 
print( "box y: " .. boxY ) 
print( "box width: " .. boxWidth ) 
print( "box height: " .. boxHeight ) 
  
print( "text x: " .. textX ) 
print( "text y: " .. textY ) 
print( "text width: " .. textWidth + boxPadding ) 
print( "text height: " .. textHeight + boxPadding ) 

box x: 5 
box y: 5 
box width: 373 
box height: 116 
text x: 10 
text y: 10 
text width: 368 
text height: 111 

Link to comment

Now it looks like this with your code:

proxy_sa_2014-11-24_15-07-34-54_www.kepfeltoltes.hu_.jpg

proxy_sa_2014-11-24_15-07-39-38_www.kepfeltoltes.hu_.jpg

The rectangle always have the same size. I want to change it's size depending on the length and height of the text. I made an example in paint:

N_vtelen4_www.kepfeltoltes.hu_.png

N_vtelen3_www.kepfeltoltes.hu_.png

N_vtelen2_www.kepfeltoltes.hu_.png

I hope you understand. How could I make the rectangle change it's size depending on the text length and height? I bet I'll need these functions:

  
dxGetTextWidth 
dxGetFontHeight 
  
 

Thank you myonlake and thanks in advance for everybody who helps/tries to help!

Link to comment
  • MTA Team

Well, no. The way those two work is they do not understand wordwrapping, because of this you cannot directly use these functions, because they retrieve the length of one line, and height of just the font and not the text itself. This is where you have to calculate the wordwrapping yourself unless someone has made a function for you already. It has been a while I have been scripting on Multi Theft Auto, so I cannot remember if there was one, but it would surprise me if there was not. I recall I had a script that made all this, but cannot remember what it is.

Maybe this may be of help? https://forum.mtasa.com/viewtopic.php?f=91&t=24262

Just make sure you always have a minimum and maximum width and height. With these parameters you are already able to do a lot of the math.

This is why I would simply go for a fixed width, and possibly even height and keep my message length as small as possible. If it is smaller than the minimum height, I can specify that when I render the text. It is a little bit inefficient to work like that, but it is certainly a way that works.

Edited by Guest
Link to comment
  • MTA Team
Okay, well, is there any way to count the lines of a word breaked dxDrawText? Because I have an idea to fix this problem.

You calculate the width of your text, you word wrap it to a certain maximum width and then everything after that will be on a new line, and repeating that until there is no more text going over the bounds. The problem is actually in separating the words. You would have to perform some fancy maths to each word if you wanted a precise measure.

Then obviously get the font height, add some extra pixels to the amount representing the full line height and multiply it by the amount of lines you have. This should get you close to what you want; but it is certainly a pain if it goes wrong.

Link to comment

I can't figure out how to do the rectangle height, somehow I should get the number of lines, but I don't know how to do it. Could you/somebody fix this/write an example for me?

Right now I have these lines inside the script:

  
local boxX, boxY = 50 * sx / sx, 50 * sy / sy 
local boxPadding = 5 
local hosszusag = dxGetTextWidth (tipBox.string, 1, "default-bold") 
local magassag = dxGetFontHeight(1,"default-bold") 
local wordbreak = false 
                 
if hosszusag > 363 then 
    hosszusag = 363 
    wordbreak = true 
end 
                 
local textWidth, textHeight = 363, 106 
local boxWidth, boxHeight = textWidth + ( boxPadding * 2 ), magassag + (boxPadding * 2) --10 + ( boxPadding * 2 ) 
local textX, textY = boxX + boxPadding, boxY + boxPadding 
  
dxDrawRectangle( boxX, boxY, boxWidth, boxHeight, tocolor( 0, 0, 0, 185 ), true ) 
dxDrawText( tipBox.string, textX, textY, textX + textWidth + boxPadding, textY + textHeight + boxPadding, tocolor( 222, 222, 222, 255 ), 1, "default-bold", "left", "top", false, wordbreak, true ) 
  

For the width it's perfect, only part that I'm missing is the height of the rectangle depending on the lines of the text.

Link to comment
  • MTA Team

Well, I decided to script it for you. Here you have it. It is not super accurate, so if the width is like 100 pixels, it will look a little bit odd, but unfortunately I do not want to spend time on this.

Source code

local tipBox = { string = "Text goes in here." } 
local boxX, boxY = 50 * screenWidth / screenWidth, 50 * screenHeight / screenHeight 
local boxPadding = 15 
local lineHeight = dxGetFontHeight( 1, "default-bold" ) 
local minimumWidth = 350 
local offsetWidth = 25 
  
addEventHandler( "onClientRender", root, 
    function( ) 
        local lines = 0 
        local wordbreak = false 
        local lineWidth = dxGetTextWidth( tipBox.string, 1, "default-bold" ) 
         
        while ( lineWidth + offsetWidth > minimumWidth ) do 
            lineWidth = lineWidth - minimumWidth 
            lines = lines + 1 
            wordbreak = true 
        end 
         
        local boxWidth, boxHeight = minimumWidth + ( boxPadding * 3 ), ( lineHeight * ( lines + 1 ) ) + ( boxPadding * 2 ) 
         
        dxDrawRectangle( boxX, boxY, boxWidth, boxHeight, tocolor( 0, 0, 0, 185 ), true ) 
         
        local textX, textY = boxX + boxPadding, boxY + boxPadding 
        local textWidth, textHeight = textX + minimumWidth + boxPadding, textY + lineHeight + boxPadding 
         
        dxDrawText( tipBox.string, textX, textY, textWidth, textHeight, tocolor( 222, 222, 222, 255 ), 1, "default-bold", "left", "top", false, wordbreak, true ) 
    end 
) 

Example script

local loremIpsumWords = { 'lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipiscing', 'elit', 'curabitur', 'vel', 'hendrerit', 'libero', 'eleifend', 'blandit', 'nunc', 'ornare', 'odio', 'ut', 'orci', 'gravida', 'imperdiet', 'nullam', 'purus', 'lacinia', 'a', 'pretium', 'quis', 'congue', 'praesent', 'sagittis', 'laoreet', 'auctor', 'mauris', 'non', 'velit', 'eros', 'dictum', 'proin', 'accumsan', 'sapien', 'nec', 'massa', 'volutpat', 'venenatis', 'sed', 'eu', 'molestie', 'lacus', 'quisque', 'porttitor', 'ligula', 'dui', 'mollis', 'tempus', 'at', 'magna', 'vestibulum', 'turpis', 'ac', 'diam', 'tincidunt', 'id', 'condimentum', 'enim', 'sodales', 'in', 'hac', 'habitasse', 'platea', 'dictumst', 'aenean', 'neque', 'fusce', 'augue', 'leo', 'eget', 'semper', 'mattis', 'tortor', 'scelerisque', 'nulla', 'interdum', 'tellus', 'malesuada', 'rhoncus', 'porta', 'sem', 'aliquet', 'et', 'nam', 'suspendisse', 'potenti', 'vivamus', 'luctus', 'fringilla', 'erat', 'donec', 'justo', 'vehicula', 'ultricies', 'varius', 'ante', 'primis', 'faucibus', 'ultrices', 'posuere', 'cubilia', 'curae', 'etiam', 'cursus', 'aliquam', 'quam', 'dapibus', 'nisl', 'feugiat', 'egestas', 'class', 'aptent', 'taciti', 'sociosqu', 'ad', 'litora', 'torquent', 'per', 'conubia', 'nostra', 'inceptos', 'himenaeos', 'phasellus', 'nibh', 'pulvinar', 'vitae', 'urna', 'iaculis', 'lobortis', 'nisi', 'viverra', 'arcu', 'morbi', 'pellentesque', 'metus', 'commodo', 'ut', 'facilisis', 'felis', 'tristique', 'ullamcorper', 'placerat', 'aenean', 'convallis', 'sollicitudin', 'integer', 'rutrum', 'duis', 'est', 'etiam', 'bibendum', 'donec', 'pharetra', 'vulputate', 'maecenas', 'mi', 'fermentum', 'consequat', 'suscipit', 'aliquam', 'habitant', 'senectus', 'netus', 'fames', 'quisque', 'euismod', 'curabitur', 'lectus', 'elementum', 'tempor', 'risus', 'cras' } 
local tipBox = { string = "" } 
local boxX, boxY = 50 * screenWidth / screenWidth, 50 * screenHeight / screenHeight 
local boxPadding = 15 
local lineHeight = dxGetFontHeight( 1, "default-bold" ) 
local minimumWidth = 350 
local offsetWidth = 25 
  
addEventHandler( "onClientRender", root, 
    function( ) 
        tipBox.string = tipBox.string .. loremIpsumWords[ math.random( #loremIpsumWords ) ] .. " " 
         
        if ( tipBox.string:len( ) > 2000 ) then 
            tipBox.string = "" 
        end 
         
        local lines = 0 
        local wordbreak = false 
        local lineWidth = dxGetTextWidth( tipBox.string, 1, "default-bold" ) 
         
        while ( lineWidth + offsetWidth > minimumWidth ) do 
            lineWidth = lineWidth - minimumWidth 
            lines = lines + 1 
            wordbreak = true 
        end 
         
        local boxWidth, boxHeight = minimumWidth + ( boxPadding * 3 ), ( lineHeight * ( lines + 1 ) ) + ( boxPadding * 2 ) 
         
        dxDrawRectangle( boxX, boxY, boxWidth, boxHeight, tocolor( 0, 0, 0, 185 ), true ) 
         
        local textX, textY = boxX + boxPadding, boxY + boxPadding 
        local textWidth, textHeight = textX + minimumWidth + boxPadding, textY + lineHeight + boxPadding 
         
        dxDrawText( tipBox.string, textX, textY, textWidth, textHeight, tocolor( 222, 222, 222, 255 ), 1, "default-bold", "left", "top", false, wordbreak, true ) 
    end 
) 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...