Post subject: Drawing under the screen in lua?
Joined: 3/18/2017
Posts: 6
For the past week or so, I've been working on a lua script for FF5 Advance that I intend to use in a livestream at some point in the future. I've used client.SetClientExtraPadding to add some space for my own GUI elements below the main game screen. I'm trying to have the script do something like scrolling credits, with text scrolling to from the bottom of my frame to the top. Naturally, when some of the text is drawn above the top of the frame, it starts getting drawn on top of the game instead. Is there any way to have it draw under the game instead of above it, so the text disappears behind the game? (I've tried a few tricks, like using event.onframestart, and drawing on both emu and native surfaces, but nothing I've tried so far works). If not, is there any chance it could be added in the future?
Spikestuff
They/Them
Editor, Publisher, Expert player (2642)
Joined: 10/12/2011
Posts: 6438
Location: The land down under.
Language: lua

client.SetGameExtraPadding(0, 0, 0, 0)
(x1, y1, x2, y2) You want to change the y2 value to whatever you want for what you want.
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.
Joined: 3/18/2017
Posts: 6
Spikestuff wrote:
Language: lua

client.SetGameExtraPadding(0, 0, 0, 0)
(x1, y1, x2, y2) You want to change the y2 value to whatever you want for what you want.
I've tried that instead of SetClientExtraPadding, and it still causes the same problem. Sorry, I don't think I was clear -- let me post a screenshot to show what I mean: My script is basically scrolling the text up (printing the text 1 pixel higher every 2 frames). I have the window at the bottom set up and working, but when I draw the text high enough that it starts to go above the end of the frame, it starts going on top of the game instead. (See the top of the words "Missed Treasures" there.) What I'm trying to do is to draw the text the same way, but have the top of it (above my frame) disappear instead of getting drawn over the game, while the part of the text in my frame still gets drawn as normal. Is this possible?
Editor, Player (175)
Joined: 4/7/2015
Posts: 331
Location: Porto Alegre, RS, Brazil
You can't draw "under" the game, so a workaround would be using a condition to the print:
Language: lua

if y_pos >= 160 then gui.drawText(x_pos, y_pos, "Missed Treasures") end
Use this inside the function you made for the drawing, assuming that "y_pos" (or whatever you called) is the one incremented every 2 frames. Oh and "160" because in the image the uppermost pixel of the bottom window is 320, and the gui.drawText function uses the original game coordinates, which is usually half the resolution the emu is displaying.
Games are basically math with a visual representation of this math, that's why I make the scripts, to re-see games as math. My things: YouTube, GitHub, Pastebin, Twitter
Joined: 3/18/2017
Posts: 6
Thanks! I can work with that. As it is, that workaround would work but not look very pretty (as the text just disappears instead of scrolling off nicely), but I can adjust things to make it work well enough. Is this the right place to make feature requests? In addition to this, it would also be useful if BizHawk had an option to center-justify or right-justify text. I wrote my own lua code to approximate centering text for a few things (not shown in this screenshot), but without measuring out and writing tests for every single character for each font and font size I use (or using fixed-width fonts only), it'll never look quite right. It's not the end of the world or anything, but it would help!
Editor, Player (175)
Joined: 4/7/2015
Posts: 331
Location: Porto Alegre, RS, Brazil
Lenalia wrote:
I wrote my own lua code to approximate centering text for a few things (not shown in this screenshot), but without measuring out and writing tests for every single character for each font and font size I use (or using fixed-width fonts only), it'll never look quite right.
Since there isn't a built-in feature, I see two solutions: 1) Use more monospaced fonts, like Courier New, Consolas, Lucida Console, Lucida Sans Typewriter, Monotxt, OCR A Extended (probably there are more accepted by .NET Framework, but couldn't find doumentation). Then, standardize your work: use certain fonts for certain ends, and define what font sizes you'll use. Finally, make a code to adapt to your use, like:
Language: lua

local font_dimensions = { -- I got these values from tests, unfortunately, I'll have to check for every font and size you need ["Courier New 11"] = {width = 7, height = 12}, ["Courier New 12"] = {width = 7.5, height = 13}, ["Courier New 14"] = {width = 9, height = 15}, ["Courier New 16"] = {width = 10, height = 17}, ["Consolas 11"] = {width = 6, height = 12}, ["Consolas 12"] = {width = 7, height = 13}, ["Consolas 14"] = {width = 9, height = 15} --etc } -- Custom text drawing function local function draw_text(x, y, text, colour, bg_colour, size, font, x_offset, y_offset) -- Handling dimensions local font_width = font_dimensions[font .. " " .. tostring(size)].width local font_height = font_dimensions[font .. " " .. tostring(size)].height local text_length = string.len(text)*font_width -- Handling x/y offset, if used if x_offset then x = x - math.floor(text_length*x_offset) end if y_offset then y = y - math.floor(text_height*y_offset) end gui.drawText(x, y, text, colour, bg_colour, size, font) end
So, for example:
Language: lua

-- test gui.drawPixel(120, 0) draw_text(120, 0, "TEST CENTERED TEXT", "white", 0, 12, "Courier New", 0.5) -- this 0.5 makes the text 50% to the left of the x you set
results in: (Notice that I drawed a pixel in the same coordinate of the text, for reference) 2) Use BizHawk's font (a modified Courier New, actually), by using gui.text instead of gui.drawText. There are advantages (size is fixed, no matter how upscaled is the emu) and disadvantages (text doesn't appear when capturing the screen) of using this method of drawing text. Its dimensions are: width = 10 pixels, height = 14 pixels.
Games are basically math with a visual representation of this math, that's why I make the scripts, to re-see games as math. My things: YouTube, GitHub, Pastebin, Twitter
creaothceann
He/Him
Editor
Joined: 4/7/2005
Posts: 1874
Location: Germany
Can you draw the emulator output again without advancing the emulation state? In that case the code would go like this: 1. emulate 1 frame 2. draw outside UI that might get overlapped by the emulator output 3. draw emulator output 4. draw UI that is on top of the emulator output
Amaraticando
It/Its
Editor, Player (159)
Joined: 1/10/2012
Posts: 673
Location: Brazil
If I understood what you want, maybe you have to use: gui.drawImageRegion void gui.drawImageRegion(string path, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, [int? dest_width = null], [int? dest_height = null]) draws a given region of an image file from the given path at the given coordinate, and optionally with the given size Then, use many pictures with the texts you want as the source. Pretty complicated. If you want, I can tell you a trivial solution with lsnes.
Joined: 3/18/2017
Posts: 6
(Mods, feel free to move this message or let me know if it belongs somewhere else.) Because the text centering thing has been driving me crazy (and I like my variable-width fonts, dangit! XD), I started hacking DrawText alignment options into BizHawk. I don't even know the first thing about using git, and haven't even coded in C# until tonight -- I just downloaded a zip of the source code from GitHub and started poking at it. In the version I've been working at tonight, I added two parameters to DrawText. The first is "horizalign" (horizontal alignment), which can be either "left" (default), "center", or "right". The second is "vertalign" (vertical alignment), which can either be "bottom" (default), "middle", or "top". Left at their defaults, DrawText works exactly as it does now. But as an example, I generated this overlay: with this lua script:
Language: lua

while true do gui.drawLine(80,0,80,240,"white") gui.drawText(80,10,"Left-Aligned Text","white","black",10,"Munro","regular") gui.drawText(80,20,"Centered Text","white","black",10,"Munro","regular","center") gui.drawText(80,30,"Right-Aligned Text","white","black",10,"Munro","regular","right") gui.drawLine(0,80,240,80,"white") gui.drawText(0,80,"Top Text","white","black",10,"Munro","regular","left","top") gui.drawText(50,80,"Middle Text","white","black",10,"Munro","regular","left","middle") gui.drawText(120,80,"Bottom Text","white","black",10,"Munro","regular","left") emu.frameadvance() end event.onexit(function () gui.clearGraphics() end)
The alignment isn't quite right yet, because it's depending on the coordinates that draw the text backgrounds, and those also seem to be off. (This has the same behavior in release 1.12.0.) If I fix this so the alignment works properly, I'll upload my changes somewhere so they can hopefully be brought into BizHawk officially, if there'd be any interest in that.
Editor, Player (175)
Joined: 4/7/2015
Posts: 331
Location: Porto Alegre, RS, Brazil
Oh that's nice! I like to see when people code a solution.
Lenalia wrote:
I'll upload my changes somewhere so they can hopefully be brought into BizHawk officially, if there'd be any interest in that.
You can do pull request there in Git, so they can analyze, test and decide if they want to implement this. I highly recommend this!
Games are basically math with a visual representation of this math, that's why I make the scripts, to re-see games as math. My things: YouTube, GitHub, Pastebin, Twitter