Emu - UI for GameMaker
A downloadable library
Ever wanted to be able to use common UI elements such as text input, checkboxes, radio buttons, dialog boxes or even tab groups in GameMaker? Look no further!
Over the last year and a half I've been working on a GUI system for GameMaker, and now that 2.3 is out I decided to jump on the opportunity to clean up the code and make it properly object-oriented. It's primarily aimed at people looking to make software applications other than games - see the screenshots - but you can use it for whatever you want.
Look inside the demo project or see the online Github wiki for documentation.
This requires GameMaker Studio 2.3 in order to work. It relies heavily on the new language features.
Price
As usual, the asset is free as-is. I'll fix simple or game-breaking bugs but more involved support requires payment via either Itch or Patreon. I get the final say in what constitutes "game-breaking."
Notes
- The scribble version used is Scribble 8.0.1. It's a fairly old version of Scribble at this point, and if you use Scribble in your own work (which you should) I recommend deleting the version that comes with Emu and going with yours. Anything newer than Scribble 8 should be fine.
- Yes, it makes heavy use of callbacks and looks an awful lot like Javascript. I'm not sorry.
- There's an ancient version of this on the Marketplace but I'm probably not going to be updating it until the Marketplace is fixed because the Marketplace is a pain.
Repository
This time around the code is just plain what you download, but if you want to look through the repository it can be found here.
Credits
Download
Click download now to get access to the following files:
Development log
- Code cleanup, some convenience functions, and misc tasks that I've been procrast...May 23, 2023
- Some new helper functions, bug fixes, and debug drawJun 10, 2022
- Preview of Emu 2Apr 04, 2022
- Starting work on a major updateDec 31, 2021
- A few new features, minor bugs, and user questionsJul 03, 2021
- Another minor bug fixMay 24, 2021
- Update and bug fixesMar 13, 2021
- Updated Scribble (6.0.14a)Dec 18, 2020
Comments
Log in with itch.io to leave a comment.
Hello, is there a way you would recommend creating a scrollable region with misc. controls within a tab? I can imagine some hacks, but I'm wondering if there's a good way I'm missing.
Awesome library by the way, I've been enjoying using it!
Scissor regions (added in 2024.8) would probably be the best option, I want to use those for a bunch of clipping-related things in here at some point but I haven’t had the time yet…
heyo! amazing tool with lots of great stuff, perhaps i'm missing something but I can't find a way for a text to display a value that's not just in local data but instead takes the variable from somewhere else, e.g. Player X: ob_plr.x and refresh data doesn't seem to be changing anything. Would appreciate the help, thanks in advance!
* sorry was able to figure it out! always happens after you ask haha:
for someone like me, use SetTextUpdate() and insert your return function like so
Very interesting! Game Maker is sorely lacking in having built-in interface for your games. I use GameMaker Studio 1.49 for now, but I am bookmarking! :)
Can you dynamically create new tabs? i.e. if I had
group.AddTabs(0, [tab_inv, tab_com, tab_rs]);
then want to create a new tab...
var tab_new = new EmuTab("NewTab");
I can't see how to insert that into the existing list
Should just be able to do group.AddTabs(row, …) again, it appends the new tabs onto the end of the row without clearing existing ones.
Any chance of the extending emu documentation you mention? I want to add a drop-down list and a TreeView |(at least those are the ones that immediately spring to mind)
I definitely need to do drop-down lists, a few people have requested them now. I think you’re the first person I’ve seen mention trees/foldable regions, but I can see those being hugely useful too.
DropDown is simple - combine Edit, Button + List
Trees - yeah, far more complex but allow a familiar (Windows Explorer) way to group things. Structs are ideal for defining the tree + could be load from/save to storage.
I suppose Menu would be cool too - Main + context/Pop-up - again, a tree structure...
Flog it all to Yoyo to save them writing their planned own version :)
The original thing that this is based on actually does have a dropdown menu system in place, but I didn’t carry it over to here (yet) because I’m not really a fan of how it works. A dropdown element would probably honestly look a lot like that, minus the ability to unfold.
Trees could theoretically be done already by combining a bunch of buttons and text labels and whatnot… but have an element dedicated to that would probably be vastly preferable.
Woo - Emu 2 includes Tree + DropDowns I see :)
Hi. I'm really liking Emu so far. However, if I start the Demo in fullscreen mode, the hotspot areas for the tabs, close button and dialog title all seem to be off. I haven't tried any other interactive control yet. When I hover the mouse over about twice the height of the tab above the tab, then the tab will highlight. When I'm in windowed mode, it seems to work fine. Am I doing something wrong? Thanks.
In EmuCore.getMouseHover(), I changed the window_mouse_x() call to device_mouse_x_to_gui(0). I don't know if that is correct but it seems to work.
Same problem for me after resizing window in my program. I've changed window_mouse_x() to just mouse_x.
mouse_x and mouse_y are the mouse’s position relative to the room, so if you make use of views and cameras it may start to conflict (although if it works for you, that’s all that matters).
The device mouse functions are probably the solution that should work in pretty much all cases, since they’re designed to take the GUI layer into account - I’ll play around with that next chance I get; as long as nothing bad happens I might make that the default.
If absolutely necessary I could make the mouse position value a macro that the user could change depending on their needs, although I doubt it would come down to that.
My understanding was that EMU objects were to be placed somewhere in the room. I didn't figured out how to use the GUI layer for drawing them. So, I've placed EMU objects in a specific part of the room, made a specific viewport to show them without scaling and used room coordinates.
Very nice! Does it work with HTML5? The font loading seems to fail...
Are you planning on adding more features? and is there any way to contact you directly (say discord)?
Amazing product!
Thanks! Unfortunately it doesn’t work on HTML5 specifically, the culprit is the text renderer doing some things that don’t work on HTML5. If you need to use it there I could make a version that just uses the normal GameMaker text features, though (or you could replace all the scribble references yourself, if you’re comfortable doing that).
There aren’t any more features in mind that I plan on adding right now, although it’s possible that I might think of something I want to do eventually.
Quite a dilemma, though I don't use scribble has nice features (and its faster?). HTML5 tools have much greater reach tough. I guess something ideal would be auto switch to normal text if html5. Saw some consideration for html5 in scribble code so I thought it might work.
As for features, I also meant integrating other's element (if worthy) Just made a range bar (off the Progress bar) and I'm thinking about dropdown menu & rearrangeable Lists. Wouldnt want to attempt those if you were also planning on it.
I have one more question. Is it suitable for mobile (performance/touch controls)? Is it tested on mobile?
I haven’t tested it on mobile, but it should work. It’s only GML.
Thank you!
tldr: Couple changes needed for Android. Performance isn't spectacular but good enough especially if you don't use a lot of elements.
-----
Overall Emu UI is hands down my favourite UI framework out there for Gamemaker. It looks good. The learning curve isn't bad. Adding new element types is easy. There are a few hardcoded variables you need to change around sizing and padding for a small canvas size like mine (180 x 320) but totally doable. There's also a few functions you need to adjust if you are scaling your game size. If it came with a few extra element types such as a drop-down selection it'd be perfect and as is it is still pretty darn good—especially compared to it's competition on the Gamemaker marketplace, blows everything there out of the water.
You do need to make a couple changes for Android. For example, you need to swap out window_get_mouse_x/y() in the getMouseHover method and a few other places for mouse_x/y or another alternative as the function doesn't work with touch input. Clicking on textboxes also doesn't prompt a keyboard to appear.
Performance is good enough imo. I'm testing it on a Samsung Note 9 and my game, with 0 optimization, gets around 60~ fps with menus/text only going down to 58~ when I draw my sprite-stacked tank.
Performance does steadily drop as you add more elements. I'm not too worried though, with a menu-based game like mine fps doesn't matter too much and I'm probably going to default the game settings to a battery-friendly 30 fps mode anyway on Android. Either way my code has plenty of room for optimization down the line.
For example this EmuDialog: https://imgur.com/rC8y6LG contains 1 EmuButton and 18 EmuText elements (the sprites are being rendered by scribble as part of the EmuTexts' values and are not the fps drop cause) and costs my Note 9 a consistent 5 fps to display. My high-end gaming pc has no issue getting and keeping 144 (fps_real of 500 that drops to 300 with that dialog) while my pretty old non-gaming laptop can touch 144 but drops down to 130~ with that dialog open.
Fair bit of room for optimization though, like I can bring that dialog container down to 4 text elements instead of 18 fairly easily but it does show how performance will degrade with additional elements.
Making a drop-down element is next up on my todo list once I think of how to prevent double-clicking on elements below a list without having to disable any elements.
Okay, wow, that’s in-depth. Glad you seem to like it!
I don’t have the mobile exports so I can’t test it (currently), are there any other changes that need to be made for it to work smoothly besides the window mouse functions and the on-screen keyboard? It may be worth me making a configuration specifically for mobile. Performance-wise it might also help to optionally use the built-in GameMaker text renderer instead of Scribble - Scribble is great on desktop, but the text shader is a bit beefy so it may not be worth it on mobile devices, or laptops with integrated GPUs - as you seem to be seeing.
Drop-down elements might be a good idea (I assume you mean something like these), I might add one next time I get around to implementing new features. Functionally they’d be pretty similar to single-selection lists, except that they’d be collapsible when not active. (The original UI code I wrote that this is based on actually had something like that, but I didn’t think it worked very well so I didn’t include it in here - probably worth redoing at some point.)
I’ve also been (slowly) trying to remove the amount of hard-coding, but as I see you’ve noticed there’s still quite a lot of it left. Adding anchor points and other support for scaling is also something I’ve thought about - I haven’t needed it myself so it’s kind of taken a back seat, but a few people have expressed interest in that sort of thing so I should probably work something out one of these days.
Hey thanks for the response! Anchor points would be a cool addition.
The issue with using scaling and Emu Dialog is just getting the mouse position. With my project I could simply swap out window_mouse_get_x/y() for mouse_x/y everywhere as well as window_width/height for room_width/height in EmuDialog, solving both the Android click detection issue and the mouse position issue. Other's will need a different solution if they have camera movement.
Another common problem I've had is with updating variables for EmuText and progress bars. This is mostly, at least with the progress bar, a problem for me because a lot of my elements are created dynamically my functions can't be fully explicit like in the demo. One of my band-aid solutions was to add an assigned_index value to EmuProgressBar.
I derived an EmuTable and EmuDropDown element from EmuList. EmuTable was straightforward but there were a few hurdles with adding a Drop down selection element. Firstly, ui elements created after the drop down render over it, so I made a one_time_surfaces variable in my obj_camera that will render a surface in the draw end event then delete them. Instead of rendering it's own surface, EmuDropDown just passes its surface to that variable. The second issue was clicking on a drop down option would also activate any element below that selection. This could be avoided by making GetMousePressed/Released check for any surfaces in obj_camera.one_time_surfaces not owned by the calling object.
I do really like Emu Overlay and am quite happy to have found it!
Well, it looks like I’ve got my work cut out for me, lol.
I’ll try to get to the more important issues first (getting the elements to react to touch events rather than the mouse, making lists scroll by clicking and dragging, etc) and then I’ll dive into some of the more specific issues. I’ll try not to keep you waiting too much longer, although there’s some work I want to get done in the next week or so, so I might not get around to it for a few days.
Regarding text elements (and other such elements) that need to continuously update, I usually override their
Render
methods in a way that fetches the updated values before drawing, like:although that may not be the most element solution if you need to do it in a lot of places - so I might at some point add some extra code to account for that sort of thing.
Is scribble already included in the tool, or should I download it too?
It’s included. It’s an older version though (6.0.14), so I should probably update it to scribble 7 at some point as more people start to use the newer versions.
Thank you! I will try it out. If I use it in my project I will make sure you will get paid!
I have been searching for some ready interface for some time now. (Since 2.3) It will help me a lot with making small tools. Thanks You have also been rewarded monitarily as I know how much time this stuff costs.
Thanks! Hope it works out for you!
EmuOverlay Close Button bug ?
Should be fixed now, check the update I just posted.
great job ~ thanks your help , and than YYC can not show everything ?
Hey man, just letting you know I picked this up and gave a donation for you. Much appreciate this asset. I have a lot of programming experience but new to game dev, that's why I started with gamemaker. But quickly came to long for a way to implement OOP. Structs are close enough!
Still wary about callback functions, though. Most of my xp is web dev, and I love Javascript, but I'm wary about doing it with structs atm. *Shrug*. Keep up the great work!
Btw, you have a bug in the dialog buttons in the demo. Needs header_width in EmuDialog. Also, first thing I did was invert the colors as I prefer dark modes, and your list selection is hardcode to c_black in EmuList. I just added another macro for it in emu_init.
Hmm, good idea. I’ve cleaned up the hard-coded color values (plus some other things) to hopefully make applying a dark theme easier - although it sounds like you’ve already made the required changes yourself. There’s also a set of example colors that one might use for a dark mode now, and if you want to make dark mode toggle-able instead you can have the macros point to a global settings variable or something instead.
I like callback design for UI things overall, but the main drawback (that I’ve encountered so far) is that too many of them can have a small bit of performance overhead - which is usually tolerable for a user interface with a few dozen elements, but can start to add up if you have five thousand game objects trying to run at 60 frames per second.
Anyway, thanks!
Thanks for the quick reply! If you don't mind, I have another question for you.
The UI options are awesome, and I know I'll eventually use them, but my first use-case is really just organizing debugging output. I have on-screen debugging for alot of things, just simple draw_text calls in the location where the equivalent debug object is positioned in the room. State variables is one of these. As you can guess, I quickly had 10+ state debugging objects everywhere. So I want use EmuUI tabs and tab groups to organize them, so I can have all states in one window and switch between the ones I'm debugging. Just tabs in a tab group with ALOT of EmuText in each tab getting destroyed/recreated every frame. As you might imagine, this absolutely tanked performance, though I didn't realize how much it would. My test case had 10 tabs, with a dozen or so EmuText lines. I would love any suggestions as to how to do this better. I have the same debugging data being output before, so it's not the computation of the data, it has to be the constant deletion/creation of so many structs constantly. It quickly goes from 400fps to 60 and then drops slowly after that.
But I'm unsure I'm even clearing the content correctly, as a call to Destroy() on the tabs seemed to cause a crash. RemoveContent() seems based on having the struct ids, so I added a RemoveAllContent that just cleared the contents ds_list.
But besides that, one issue I did notice, which is compounded in my project, is there seems to be a small memory leak. I tested with the demo project, adding a frame counter in the create event and then incrementing and setting that to the summary. Here's a link to get the modified obj_emu_demo
https://drive.google.com/file/d/1UfcZQG7oyPpUgDn_mkT0-xOE-LLHPjxM/view?usp=shari...
It's small, but you can notice the mem usage just climb over time, which it doesn't do in the base demo. If you look at the code, though, I'm just removing content (via the variable itself), re-creating, and re-adding. As far as I can tell I'm doing everything I should be doing. I'd much appreciate your insight!
Thanks again!
Will
Let’s see here.
If you want to switch between sets of UI elements (as opposed to creating and destroying them) the fastest way to do that is to probably create them all at the beginning of the game - or as needed - and then saving them somewhere without drawing them. You can also recycle elements by changing some of the variables: the “text” variable, for example, more or less does what you expect it to and is generally safe to change at any point in the code.
Regarding the memory leak, it turns out the list of contents attached to each struct wasn’t actually getting deleted (only cleared) in the Destroy() method, which is probably the cause of what you saw - it would only have been leaking a few bytes per element, but if you created and removed a lot of them it would start to add up over time.
I’m not noticing anything immediately unusual about RemoveContent() that would cause a crash, so later on I’ll poke around and see if I can find it. The only thing in your example file is the obj_emu_demo object, by the way.
Once I’ve done that I’ll post an update. I also kinda want to get rid of as many ds_lists as possible, in favor of things like arrays, since currently losing references to elements in other ways without calling the Destroy method will also cause a memory leak. In the meantime - if you haven’t already - add
ds_list_destroy(contents);
to the destroyContent() method in EmuCore.Sorry for the confusion. I attached only the obj_emu_demo object because it's the only thing I changed from the base demo. I thought having that as the only file would make that clear but re-thinking that logic makes no sense. So yeah, use that obj instead and it should produce the leak.
Yeah I eventually found the text var and just tried updating that directly, but I'm still getting this weird mem leak that makes no sense. Here's another version where I'm updating the text var directly:
https://drive.google.com/file/d/1R_7FbTHdrQh2l97G6tBNuKuNz2Ifb1Ui/view?usp=shari...
(It's only the 1 obj since we've established that's all I changed ;)
I'm just incrementing timers... it's weird. It's only when the summary tab is in focus does the memory just steadily climb.
Maybe you've fixed it in your newer version, though. I haven't had a chance to update anything based on your post. But I'd still be curious for you to check it out. Just for my sanity.
Hello, sorry for the delay, Ludum Dare ate up a lot of time.
Anyway - I loaded in the example demo (both versions of it) and let it run for a few minutes and memory usage stayed at a constant 11.58 mb. Hopefully the leak’s gone, but if it comes back send me the whole project and I’ll look around in it.
Also, 2.3.1 came out in beta this morning, which addresses some issues with the garbage collector - although I doubt that’s what was causing your problem.
Hello , 1080 TO 4K FullScreen can not click ?
This is amazing!! Thank you so much for putting this online!
I was wondering if there's a way to also add text to an 'EmuButtonImage' element? I'd like to show a name on the bottom of the button.
Thanks again!
Usually when I need to do this I just overlay a regular Text element on top of it - but that’s a good idea, I’ll make sure to add this in next time I work on this!
Ah that's a good tip, and awesome! Thanks again!
EumList double click error
What are you trying to do
23.1.1.146 has some issues with function callbacks. I’m waiting to see if the next update fixes it, otherwise I’ll work out an alternate way to do it: https://dragonite.itch.io/emu-ui-for-gamemaker/devlog/155555/gms23-is-now-in-open-beta
Too bad I'm still stuck with GMS 1.4, this looks super cool and I was looking for something exactly like this. Love your projects.
Thanks!