Lua for GrandMA3 Episode 5 - UI Elements and MessageBox
Hey lighting folks! The following is the transcript from my YouTube video, Lua for MA3 Ep 5 - UI Elements and MessageBox
This video is part of my Lua for GrandMA3 Tutorial 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.
Hello lighting people, welcome back to my Lua for GrandMA3 tutorial series. In this episode we're going to talk about what has to be my single favorite thing about Lua – UI elements – and my absolute favorite MA3 function, MessageBox, which quickly and easily makes a UI element. Now in case you don't know, or don't remember, what “UI” means, it just stands for “User Interface;” in other words, a UI element is anything the user can see and interact with rather than something that just happens in the background in 1s and 0s. UI elements allow you to take input from the user and use it to make different things happen based on their choice. This is the basis of all computer programs; think of any game on your phone that gives you multiple choices. Do you want to take this path or that path? Based on your choice, different things happen. In order for that to work you have to have a UI element that gives the user a choice, then your program has to both record their choice and perform predefined actions for whichever choice they made, and we can do that in 3 as well, using Lua. In fact, we've already done it to some extent, using the Confirm function, but there's a lot more intricate stuff still to unlock, so let's talk about it.
Now at some point in the future I will definitely make a video about building custom UI elements, but it's complex and requires a lot of code, so for now we're going to focus on MA3's built-in MessageBox function, which already gives a lot of options with relatively few lines of code. After all, you're just calling an existing function and throwing an argument in there to tell it how to execute. The thing that makes the MessageBox function unique compared to those we've looked at so far is the fact that it actually takes a table as an argument. This table will contain lots of carefully defined data rather than just one or two variables. Good thing you understand how tables work, right? And if you don't understand them too well, don't worry, because it'll make more sense once we actually use them in this episode.
Now in a minute I'm going to show you a fully built out MessageBox with all the possible customization, but first I'm going to start with the bare minimum. You're not going to like it, but here goes. We're going to type out MessageBox like this, and now I'm going to put table constrictors, or braces, in here and hit enter, just for visibility. The only table element that is 100% required to prevent the function from causing an error, which is what would happen if you called it with empty parentheses, is the title, so that looks like this. “title = ...” I'm just going to put “Title.”
I'm going to go run this… As I said, it's not pretty. There isn't even a button to close it! Now don't worry, because you can always hit escape on your keyboard and that will close it, but this isn't very ideal, is it?
Instead, let's flesh it out. So I'm going to go back in here and show you this completely fleshed out, full of all of the information, MessageBox function that I have made. And this one has lots of comments, lots of specifically defined stuff. You'll be able to access this file right here if you're following along in GitHub, and you can refer back to it at any time, but for now since I don't want to actually change this file I'm just going to copy it. I'm going to not copy the main function, I'm just going to copy the rest of it, and I'm going to put it in my file for this episode so that I can change it freely and it won't impact the other one.
Now I'm sure you quickly noticed all the green text on my screen, and I touched on this in the last video, but just in case you missed it I want to quickly explain how comments work. These two dashes at the beginning of a line define it as a comment, so that makes it something that the system does not read. It just ignores it when it's going through the code.
You can also create multiple-line comments like this: “--[[” and then it ends whenever the closing square brackets happen.
You can use comments to either comment out code for troubleshooting purposes, or to just give yourself information like I did here. This MessageBox function is complete with literally all of the information I could think of to add, including every possible value you can customize as well as comments on all of it. Please don't hesitate to also refer to the manual, but I think in most cases my comments are better written and better illustrated, since they're in line with the code, than what you'll find in the manual. I also added extra information that isn't in the manual; feel free to just read through this whole function on GitHub Hub at your leisure and refer back to it or copy pieces as often as you need. My hope is that it will contain all the information you'll need as a reference, but some of these things are better explained visually so I'm going to show you a few things.
As you can see, this comment up here shows a list of the main elements included in the MessageBox function; you have a title, you have a message, you have inputs, radio selectors, swipe selectors, states, or checkboxes, and commands – and I'll show you what all of those terms mean shortly.
For now I'm going to go down here and show you, we have a title, we have title text color and back color and an icon; so what do these numbers for the text color and the back color actually mean? Well, it's actually a reference to something in your MA3 showfile. So this one right here says “1.7.” I'm going to go into MA3 and show you exactly what that is in MA3. If we go to “Desk Lights and Color Theme” and “Edit Color Theme;” you can find these color definitions right here. So you have a 1, 2, 3, and a 4 over here, and you have 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, whatever; a whole bunch of them here, and you're actually going to be referencing the ones on the right hand side of the screen, so you're going to want to look for the number 1, then number 7; this would be the information referenced by our first table value over there that says 1.7. It is not referencing this information here, which would be 1.10, it is 1.7.
The other way you can write that would be “Global.Selected” but put that in quotes, and if you do that, that works the same way, and again you do not want to put the name of it as it appears over here, so like I have one that says “Global.AlertText;” the name of the Color Def Ref is Global.Alert but that's not what you want. You have to put this right here, which is “AlertText.” Or it would be 1.31 here as opposed to 1.59, and it all works, it just references the color theme in your show file, and that is the only way to set text colors; you can't actually just set- you can't actually set an RGB value or any other type of color mixing value. You would have to go into your show file and, you can actually create your own color theme; you can go down here to New Color Def and add a new one and make it whatever you want. You can reference that, totally, but that's what you would have to do in order to make a custom color.
The next thing I'm going to mention is obviously we have this icon here, “object_smart.” Okay, what is that? Well, we have a comment here which says “an icon for the left side of the title bar” and that is, just to go back and show you, that's this right here; that's called “object_smart.”
So where does that come from? The options can be found by using “List” in the GraphicsRoot/TextureCollect/Textures CMD line destination. What does that mean? Well, this one took me a bit to figure out so I'll make sure you understand it. It is crazy but you actually have to come in here and go “CD” or “ChangeDestination” “Root” and, what was it we said, “GraphicsRoot,” okay, so we have to type that, and now we're in here. It says “Admin@GraphicsRoot,” now we have to do that again to, what's the next one? Yeah, I'm not going to remember. You do have to do these one at a time, believe me or not. “TextureCollect,” okay, “CD Root TextureCollect” – it's all one word. So, my bad, you only use Root the first time, so you're actually going to just type “CD TextureCollect” and then let's see what's the next one is. “Textures,” okay, “CD Textures” and here we are! Now this matches what it said: GraphicsRoot/TextureCollect/Textures. Now the options can be found using “List,” right, so, now we just type the keyword “List” and, oh my goodness, what a list!
Yeah, this is a really long list. I have not read through it and I have not even gone through it to find different icons. This is a list of all the icons and you can totally go through and try them all. I have actually only used icons that I've already found in example code in different places; I have not gone and searched out my own, but those are all options that you can use.
Okay back to this. The next section here shows the values that can define what can close the MessageBox, so autocloseOnInput is false, this determines whether the MessageBox will close when you press please or enter or if it will wait for you to close it. Timeout is 10,000 milliseconds; that would be 10 seconds. timeoutResultCancel equals true; we'll talk about that in just a minute, timeoutResultID, 36, alright, I'll also wait a minute on that. Timeout – if you don't set a timeout value the default is nil, and it will actually then not do what it is doing here, which is giving you this bar and timing out after the bar hits zero, which is not nice. Or, maybe it it is nice; it depends on what you want, but yeah, whenever this hits zero it just... Closes. Great. I will come back to this information in a bit when I get to what your results actually are.
Commands are the buttons that are right here, and yes, this froze because I went away from the application and it's all confused now, but these are the command buttons. We have “Yay!” and we have “OK Whatever” and in this case they're not tied to anything, they don't do anything; but the these are commands and the way you set them is, you give them a value and you give them a name, and the name is displayed on the button and the value is returned if that is the button that is pressed, and so you'll just make commands equal to a table that's in the blue braces, and then a table within that for each of the individual buttons that you want to make.
The next type of thing that you can put in a MessageBox are inputs. So inputs are… Let's just go back and run this again. These are inputs; “Input 1,” “Input 2,” “Input 3,” and you can put things in them that are then returned whenever the MessageBox is closed. That is fantastic so we have, again you have to put the information in table constructors and then set another table for each individual input. You can give them values, such as the name which is displayed, the value; you can enter a default value, as you can see there is a default value here, and then when you type it takes that away. You can add a blackFilter. A blackFilter defines characters which cannot be entered, so it will not let you enter a black filtered character. VKPlugin has a specific list of different types of values that you can put in here. The options are in the user manual; I'll let you look those up. TextInput is definitely the one I use the most. I honestly don't know if I've ever used one other than TextInput. And then the maxTextLength down here defines how many characters you're allowed to put, so I cannot put more than 10 characters in here. Then in number two… In this one, you can put the default value as characters that are not allowed, but the whiteFilter determines which characters are allowed, so if you use a whiteFilter then anything not included cannot be entered, so in this one we whiteFiltered all the numbers. Only numbers can be entered and the plugin value is set to “NumericInput,” and I will show you in a second what that difference actually does.
And then in input three I put a Cue ID, I put numbers and a dot here because those are what we would use for making a cue, and then the VKPlugin is “CueNumberInput” and I will again show you what that does, so let's go back to MA3, and in this one the onscreen keyboard opens up like this, in this one, the onscreen keyboard opens up only with numbers, and in this one it opens up specific to entering values that have to do with a cue number. Obviously you can still attempt to type numbers if you're using a regular keyboard, or you can attempt to type numbers here, you can attempt to type letters here, and whatever, but they're not going to work.
And then we'll talk about these next, so let's go back to VSCode, and what is a state? A state is obviously written just like these others, it has a name and a state for values, so the name is displayed on it and then the state is true or false; this is really simple honestly, so I'm not actually going to explain it in any more detail; I think you can figure it out: name; state is basically the status, checked or unchecked.
And then down here we have selectors. So there's two types of selectors, swipe buttons and radio buttons, and obviously that information is all included here so I'm not really going to go into it a lot cuz I'm trying to keep the video as short as possible, but we're going to have the name, selected value, that's the value that will be selected by default, we have the type; 0 or 1 for the swipe button or radio button, and then we have the values that are options, and you're probably familiar with these types of buttons because they exist in MA3, but this is a radio selector, this is the swipe selector; you know what they are.
And we'll go back to MA3 and down here I'm going to talk about the values that are returned by the MessageBox function, so as you can see the whole MessageBox function is a table and you have to put, uh you have to, you have to separate table values by a comma, so we have table value, title, comma, next table value, title text color, comma; whenever you have a table in a table it's the same thing, that's just how you write a table, and you can just leave out as many of these things as you don't want to use, and I very, very, very, rarely use all of them. Actually, I've never used all of them except to make this example, but the results that you have here are going to be also organized in a table, so to access them you have to know the table structure so the success returns, it's a boolean; true if the table's closed by timeout or command button unless timeoutResultCancel set to true, in which case it is false, so in other words this is where this comes in. So this is going to determine what kind of result you get for a timeout, and this is an optional value. You can set the timeoutResult to be any value you want; if you want it to be… I just I set it to a number because I like the number 36, but you can set it to be, “oh no the box closed on its own!” or you know, whatever you want it to be; it's just information for you if you need that information for something. I've actually never used a timeout except for this example, but if you need it then you have that option.
And then this result value right here returns the value of the command button that was pressed or the timeoutResultID if that was defined, so the timeout- so the result here, like I said, that's the value of the command button, so that's only going to refer to the command button and it's only going to be the value, which is why you have to know what the value is. You're going to always- there's always going to be a number. You're going to be like, “if myReturnTable.result == 1 then do XYZ,” you know.
And then the inputs returns a table, so like this table, do table and then whatever value you have under that, and I will show you in another video how we can make a short function to actually retrieve those key/value pairs, but it's not too difficult, and remember the inputs are the values that you've input here, so the value will be the value this had when it closed, whether you replaced it or it's a default value. And by the way you don't have to specify a default value, just so you know.
And then for the states, those will be the states’ names and boolean values, so whether the state was checked or unchecked when you closed it, and the selectors are same thing, key/value pairs with the selector names and boolean values, so basically if you understand tables you can make really awesome use of the MessageBox function, and it is so awesome, so simple to just throw into anything at any time; I love it.
Now this method of retrieving the individual values from tables can be tedious if you have a bunch of them. Fortunately, there are solutions, but I don't have time to explain them in this video. In the next one I'm going to talk about generic for loops. These will allow you to go through the values in a table and gather just the information you need, much more quickly than you can by going through them individually. I guess you could see it as just a continuation of the work we've already been doing with tables. I'll see you soon! Happy lighting!
Comments
Post a Comment