love
love copied to clipboard
Expose coordinate of a specific glyph in a string
Original report by Landon “Karai” Manning (Bitbucket: karai17, GitHub: karai17).
I am trying to draw an input cursor for an input box. My problem is this: let's say I have the following string within a fixed width where |
represents where I want the cursor to be:
[abc d|ef ghi ]
To get the cursor position, I must loop through the string and measure the size of the sub string to see if I am passing where the mouse clicked:
is "a" > | ?
no
is "ab" > | ?
no
...
is "abc de" > | ?
yes
cursor is at "abc d"
Great, that was easy. But what about if my textbox is aligned to the right? Or heaven forbid, justified? This problem because very tedious at best.
[ abc d|ef ghi]
[abc d|ef ghi]
I propose exposing the coordinate of a particular glyph in a string:
local font = love.graphics.newFont("somefont.ttf")
local index = 9
local text = "Now this is a story all about how my life got flipped turned up-side-down!"
local x = 100
local y = 150
local limit = 300
local align = "right"
love.graphics.setFont(font)
local x, y = love.graphics.getGlyphPosition(index, text, x, y, limit, align)
You will note in my proposition that getGlyphPosition
uses the same arguments as printf preceded by the desired glyph index. This would give you the exact same data that would be drawn to screen via printf, allowing for you to accurately get the coordinates of a particular glyph.
Original comment by Gabe Stilez (Bitbucket: z0r8, ).
If i might add something to this in the form of a question; might it make more sense to implement this as a method to the soon to-be 0.10 text objects, like to:posToCoords() or something instead? Or would this make sense even "outside" of text objects.
Original comment by Sasha Szpakowski (Bitbucket: slime73, GitHub: slime73).
It would most likely be a Font method.
It could work with Text objects too, but it would only make sense for text added to the object with Text:set
, not Text:add
.
Original comment by Gabe Stilez (Bitbucket: z0r8, ).
Okay, one more question, would it make sense for this or a similar function to work with l.g.print as well? (doesn't have alignment nor wrapping, but it does have transformations)
Original comment by Pablo Mayobre (Bitbucket: PabloMayobre, GitHub: PabloMayobre).
You always know the transformations in l.g.print
so you can take the difference of the coordinate minus the transformation and you have the real coordinate, then you would use the font method.
The problem comes with right
and center
alignment, then you would need to specify all the arguments you would pass to l.g.printf
which is kinda ugly
Text
objects are not what I expected so I dont really like them hahaha.
Yet you could store the bounding boxes of each string added
/setted
in the text object, and compare to that first, then use the standard method.
I'm not sure about the API either... specially the alignment part (too many arguments)
Original comment by Sasha Szpakowski (Bitbucket: slime73, GitHub: slime73).
Text objects are not what I expected so I dont really like them hahaha.
What did you expect?
Original comment by Pablo Mayobre (Bitbucket: PabloMayobre, GitHub: PabloMayobre).
Just one text (it wouldnt store more than one string), percharacter format, utf8 functions (string like, not just the ones provided in UTF-8)... Better wrapping, like a printf but waaaaaay more useful and customizable with lot more methods and stuff...
Original comment by Sasha Szpakowski (Bitbucket: slime73, GitHub: slime73).
utf8 functions (string like, not just the ones provided in UTF-8)
That doesn't seem like it should belong in a drawable object...
Original comment by Pablo Mayobre (Bitbucket: PabloMayobre, GitHub: PabloMayobre).
Well you are right there, haha
Anyway the most important feature I wanted would be percharacter format or rich formating, which would imply multiple font and sizes and would make using the font methods really awful (How would you handle a text object with more than one font?) so you would need to have some methods (getWidth, getHeight, getWrap and such plus this ones getCoordinate, getCharacter)...
Original comment by Sasha Szpakowski (Bitbucket: slime73, GitHub: slime73).
I don't think that's a direction that love.graphics text drawing will go in, for the foreseeable future. You can draw multiple individual pieces of text for that kind of thing (which, coincidentally, can now be a lot more efficient if Text objects – even multiple ones – are used.)
Original comment by Pablo Mayobre (Bitbucket: PabloMayobre, GitHub: PabloMayobre).
I though that was the issue you were trying to cover with Text objects but well (It's not like I hate them, they are really nice to have, plus are better than printing something a thousand times to the screen in a couple of seconds)
Coming back to the issue, how would you handle the limit
and alignment
? Would you need to pass them to the method? Also I consider the x
and y
of the text are pointless, you just need to pass the difference as I pointed above, same with translate and scale, the user can handle that I guess so you would assume that the text is drawn at 0,0 and that would reduce the number of arguments needed
Original comment by Pablo Mayobre (Bitbucket: PabloMayobre, GitHub: PabloMayobre).
API proposal
local x, y, width, height = font:getGlyphPosition(index, text, limit, align)
This one returns the x
and y
position of the character at the index
position of the text
which has a limit
and an align
mode. The index
should probably be UTF-8. The width
and height
are optional, but would be nice
local index = font:getPositionGlyph(x, y, text, limit, align)
This one does the opposite, you pass the x
, y
position and it returns the index
of the character under that point, if it is not over any character, returns nil
. Again the index
should probably be UTF-8.
Both of this functions assume that the text is drawn at 0,0 and x
and y
are relative to that.
PS: Not sure about the names hahaha
Original comment by Pablo Mayobre (Bitbucket: PabloMayobre, GitHub: PabloMayobre).
Well after designing many API's with textareas in mind, the above proposal I made more than a year ago still makes sense, would change the names though, they are horrible!