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)?
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.
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."
- The scribble version used is 6.0.14a. It's the final version of Scribble 6 and should be reasonably stable. Scribble 7 changes some things in major ways so I probably won't update it soon, until it's been out for long enough to be mostly stable and well-documented.
- Alternatively, you can get it on the GameMaker Marketplace here.
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.
Click download now to get access to the following files:
- A few new features, minor bugs, and user questions24 days ago
- Another minor bug fix64 days ago
- Update and bug fixesMar 13, 2021
- Updated Scribble (6.0.14a)Dec 18, 2020
- Fixed some bugs and made the code nicerOct 16, 2020
- Color values, more Sam puns, and related thingsSep 29, 2020
- Text wrapping in UI elementsAug 17, 2020
- New GMS 2.3 update, fixes bugs with callbacks and methodsJul 02, 2020
Log in with itch.io to leave a comment.
Very nice! Does it work with HTML5? The font loading seems to fail...
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.
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.
I am meaning to test the game on a LG G6 to see how performance is on an older phone but I haven't yet gotten Gamemaker to recognize it as a target device.
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! I've only been working on my project for a week or so, and in that time those two changes for mobile are the only ones I've noticed having to make so far. Though being able to scroll lists by dragging on the list itself rather than having to click and drag on the scroll bar would be a nice addition for a mobile edition.
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 might need a different solution if they have camera movement.
I'll worry more about performance down the line. I don't want to lose Scribble's in-line sprites or its other niceties. If basic optimization doesn't get performance where I want it I'll probably adjust elements (at least EmuText) to draw to a surface and only update the surface when a change is detected.
Anchor points would be cool and yes that is what I mean by a dropdown element! My project is about designing component for tanks and then the tanks themselves. Having drop down elements for selections involving components or materials would look a lot nicer in my mind then using a list element.
How I am thinking of implementing drop down elements is to have a basic box display that, when clicked, will create a surface that gradually expands from 0 height to a set height. Options would then be drawn to that surface with a scroll_offset modifier on the y coordinate. I've done something similar before for displaying cards in a deck but I'm not sure of the best way yet for preventing clicks from occurring on elements hidden behind the drop down list. I think the easiest way to code would be to simply pass interactive elements an array of EmuDropDowns within n pixels above them at creation, then check if any are active before checking for mouse pressed. However, that is inelegant and would add a lot to the baggage of moving, adding, and deleting EmuDropDowns.
As for other changes I've made so far you might be interested in, on EmuButton I added a frame_delay parameter that defaults to 1 frame. A very minor change but it prevents a double-clicking bug that occurs when an EmuButton leads to a new menu page—or creates a dialog pop up—that has another EmuButton overlapping the position of the one that had been clicked, a problem I've had a few times.
I also added an EmuInputOnly element that is simply EmuInput but without the text component. The hard-coded values in EmuInput are not great on a small canvas size with regards to how it handles dividing the width between the input box, blank space, and text display. Definitely something worth looking at if you make a scaling update, though it is possible I might have been using it wrong, I didn't spend much time with them before switching to EmuInputOnly.
Another common problem I've had is with updating variables. This is mostly, at least with the progress bar, a problem for me because a lot of my elements are created dynamically so 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've also had a similar problem with EmuTexts that need to constantly update. Right now I have to save a pointer to such elements and then manually update them each frame from my main controller object. While doable, that solution adds to the baggage associated with adding and removing such elements.
I am about to work on implementing references using this guide, then I'd be able to pass elements a pointer at creation and they'd be able to update themselves and/or know what to update.
Finally I need to do a pass over EmuProgressBar's rendering. It looks good in your demo but not so much in my game. They just look weird, especially the small, darker rectangle in the top-left of each bar. I'm pretty sure I haven't changed anything in how they render though I did need to adjust the mouse detection tolerances as you could select multiple bars at a time if you aimed between them at this game size.
I do really like Emu Overlay and am quite happy to have found it!
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.
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.
EmuOverlay Close Button bug ?
Should be fixed now, check the update I just posted.
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!
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.
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
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!
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:
(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.
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!
EumList double click error
What are you trying to do
188.8.131.52 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.