Building Custom UI Elements with Lua for GrandMA3 Part 1 - What They Are and When to Use Them

Hey lighting folks! The following is the transcript from my YouTube video, Lua for MA3 Custom UI Elements Pt 1 - What They Are and When to Use Them

This video is part of my Building Custom UI Elements with Lua for GrandMA3 series. Please check out my channel, From Dark To Light, on YouTube, and you can find the code to go along with my tutorials here on GitHub.


What if I told you you could build your own pop-up box for MA3 piece by piece, whatever size, shape, and color you want, and make it easily reusable and customizable for each use case without rewriting the whole thing each time? And you don't even need a computer science degree to do it!


Hello lighting people, welcome back to my YouTube channel. Or if you're new, I'm so glad you found me. Custom UI elements are an exciting and long-awaited topic, and I'm looking forward to talking about them today. This is going to be a short video series, just three videos, and today we're going start by talking about what I mean when I say custom UI element, and how and when you're going to want to use them.


Now I'm sure you do know what a UI element is, or you wouldn't be watching this video, but it might be good to just set a definition so we all know we're on the same page. The user interface refers to the part of a program that a user can physically see and interact with; a UI element is an individual piece of that interface.

Most of the time, if I'm talking about creating UI elements, I'm going to be referring to some type of pop-up to get data from a user. First, I'm going to show you some examples of UI elements MA3 has built-in functions for. An important thing to note is that not all existing MA3 functions are referenced in the user manual. Why? I couldn't tell you.

I can tell you that PopupInput(), for example, I'm pretty sure used to be in the user manual, but it isn't anymore. However, I can absolutely confirm that I'm still using it and it still works. Anyway, these are the three functions that I'm aware of currently.


One is MessageBox(), which I made a whole video talking about before with a whole long example. I have an example here as well. And you can go look at these, you can go watch that video, and there are a lot of options with it. It is super customizable, which is why I dedicated an entire video just to that.

It lets you use different types of inputs like checkboxes, text inputs, radio buttons, swipe selectors, and different commands, as well as, of course, a message and the option to customize the colors of various elements and have it auto close on a timer.


PopupInput() is one that I'm going to show you today. This one's super simple. You just set a key and a value to the returned object. You put in a title and which display to put it on. It's called a caller. And then you put in the items you want to be options. And I will go ahead and actually show you how this looks in MA3. I'm just going to copy and paste because I do have a way to use a macro for this, but since I'm just going to show it to you one time, I don't see a need to do that.

And the way it looks is like this. So it automatically puts in the word “Select,” which is why I just put “an option.” So it says “Select an option,” and then I can select either of these.


And then another one that I did show you over here is the TextInput(), which I absolutely love because it is literally like the simplest thing ever. You just put TextInput(), a title, and some default text, and it'll return the user input. So if I click this, it'll show you. It puts the word “Edit” in before whatever you put for the title, which is why I just put “this text box.” And you can change this. And I'm picky about spelling, but you can change this text and it will return that to your variable, which is right here.

And in this case, obviously, I'm not going to use that. I was just showing you basically what those functions do.


Alright, so these are the basics, but they can be pretty limiting. TextInput() and PopupInput() are simple enough that I can't imagine, if you actually want to use them, having a complaint with them. But message box, although it is versatile, doesn't have as much customization ability as I'd sometimes like. When you make a custom UI element, you can make it look however you want, be whatever size you want, and have whatever elements you want in whatever locations. I haven't gotten too, too complex with them, but take a look at this UI element I created as an example.


We've got checkboxes in two different rows and three columns. We have a message in the middle. And the command button is a different color. There's a cool icon in the corner.

What in the world is going on here? There is no way to do all this with MessageBox(). Actually, you can change the icon. But you can't arrange the checkboxes like this. So that’s pretty cool.


Now, before you get all excited and want to make custom UI elements for everything, keep in mind that you basically have to write out and code all of the details on how every piece of the UI element is designed. Just creating the function for this popup required about 300 lines of code, and I have no clue how many hours I put in to figure all this out and put it together. But it was a lot, and so many headaches as I ran into brick wall after brick wall, I had to figure out how to go around. Of course, I am going to share a lot of what I learned with you, but even with an understanding of the concepts, it's still not going to be easy.


So the question arises. When should you build custom UI elements? The reason I did it was because I needed to have the checkboxes ordered a certain way and with messages in between them.

MessageBox only lets you do one message, which is always placed at the top of the message box, and your checkboxes get ordered alphabetically rather than however you want them. Another good reason to build your own UI element function, at least once, would be just so you understand how MessageBox and other functions are functioning. It definitely helped me be able to use them better and have an idea of what's happening behind the scenes.


Now I'll be honest, I did this the wrong way the first time. I copied a really long function somebody else built, added even more to it to make it easily editable, and used a copy of it for every single checkbox dialog I needed to make. It was well over 600 lines of code in each and every plugin that needed a checklist.

Bad idea. Don't do that. I'm telling you right now, I found a much better way.

I created a function with 297 lines of code, including comments, and I made it so that it accepts a table of arguments similar to MessageBox, and uses those to fill in the information. Now I just call that function from my other plugins, which is way more efficient, easier to edit, and less error-prone. Of course, I'm going to show you how I did that, although not today.


In the next video, I'm going to show you the basic structure necessary to build a UI element and where to find that information. Later on, we'll get to best practices and how to streamline them more. Oh, it's getting fun! I'm very excited. I will see you back next week hopefully, and until then, I hope you have an amazing week and get to program some pretty lights. Bye!



Comments

Popular posts from this blog

Lua for GrandMA3 YouTube Crash Course

Intro to Lua for GrandMA3

How to Make a Reminder Plugin for GrandMA3 Using Lua