Dzsozi (h03) Posted November 23, 2014 Share Posted November 23, 2014 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. 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): Two or more lines (messed up): 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
myonlake Posted November 24, 2014 Share Posted November 24, 2014 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
Dzsozi (h03) Posted November 24, 2014 Author Share Posted November 24, 2014 Now it looks like this with your code: 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: 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
myonlake Posted November 24, 2014 Share Posted November 24, 2014 (edited) 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.multitheftauto.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 November 24, 2014 by Guest Link to comment
Dzsozi (h03) Posted November 24, 2014 Author Share Posted November 24, 2014 Okay, well, is there any way to count the lines of a word breaked dxDrawText? Because I have an idea to fix this problem. Link to comment
myonlake Posted November 24, 2014 Share Posted November 24, 2014 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
Dzsozi (h03) Posted November 24, 2014 Author Share Posted November 24, 2014 Okay, thank you, I'll try something, if there's a problem I'll reply to this post again. Thank you again! Link to comment
myonlake Posted November 24, 2014 Share Posted November 24, 2014 Okay, thank you, I'll try something, if there's a problem I'll reply to this post again. Thank you again! You are welcome, and good luck! Link to comment
Dzsozi (h03) Posted November 24, 2014 Author Share Posted November 24, 2014 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
myonlake Posted November 24, 2014 Share Posted November 24, 2014 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
Dzsozi (h03) Posted November 24, 2014 Author Share Posted November 24, 2014 Thank you very much, I fixed the problem by just removing the boxPadding from textWidth and textHeight. So now it looks perfect with long and short texts, thank you again very much! Three screenshots of the perfect notification box: Thank you again! Link to comment
myonlake Posted November 24, 2014 Share Posted November 24, 2014 You are most welcome. Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now