Topic: User Interface Widgets II
Download These Files
First Steps
Make sure to create your lua script inside the folder from the zip file.
Create your Lua script outside the assets folder
Give your lua script a different name from the one provided if you intend to follow along and write your own code
Variables
When using widgets from UVI Script, we need to create variables and then assign them a value of the widget in question. The first variable here, bg, is an Image widget. We are creating something known as an object. bg is now an object from the Image widget. This widget takes a parameter that specifies the location of the graphic file.
The same process is repeated for the knobBg which is also an Image widget. The button and Knob widgets are different. They require different kinds of graphic assets. We create the btn variable and the graphic assets are assigned later in the code. We then create the knob, k1, and the graphic is assigned later. This knob takes five parameters. The first is a string that specifies the internal name. The second, 0, represents the default value. Then the second 0 is the minimum value. 2 is the maximum. And true specifies whether the values are integers. In our case, we want them to be integers.
local bg = Image('assets/wvfrm_ui_bg.png')
local knobBg = Image('assets/wvfrm_knob_bg.png')
local btn = Button('button')
local k1 = Knob('knob1', 0, 0, 2, true)FOM Variable
One of our UI widgets will control a parameter. So we need a variable that points to a specific location in the FOM. We are pointing towards the first oscillator of the only keygroup in layer 1.
local osc1 = Program.layers[1].keygroups[1].oscillators[1]
We then specify details about the background. Notice how we use the dot syntax here. When specifying an attribute, as opposed to a function, we use the dot syntax. In the code below, we are controlling the position of the background with bg.pos = {0,0}. The first parameter in that table is the x position and the other is the y position.
After that we start addressing details about the button. This includes specifying the normalImage and pressedImage for button. The normalImage refers to the default image. They both take strings they specify a file path.
bg.pos = {0,0}
btn.normalImage = 'assets/wvfrm_btn_normal.png'
btn.pressedImage = 'assets/wvfrm_btn_pressed.png'
btn.pos = {310, 230}
btn.size = {199, 68}changed
changed is a callback function for the button widget. It is triggered when the button is interacted with. We can change what this callback function does by assigning it a new function. We can see in the code below that changed is assigned a function that contains a print and a playNote(). This means that when the button changes state (when it is pressed), it will trigger the print and the playNote.
btn.changed = function()
print("btn pressed")
playNote(60, 100, 1000)
endKnob
The visual knob you see in the interface is actually the combination of a background image, knobBg, and also a foreground knob, k1. The details for the knob widget are similar but different in a few critical ways. We assign the position and size the same way. The critical difference is the function, setStripImage. A knob widget in Falcon requires a graphic "animation strip". Similar to how old cartoons are made. It's a graphic in which each frame, of a specified size, contains one frame of the animation. If you look at the parameters for setStripImage, you'll see that it takes two. The first is the path to the image strip. The second is the number of frames in the strip.
Here's another critical detail
The size of the knob must be the same of a frame in the strip. In the code below, we set the size to 50 by 50. This means the frame sizes are 50 pixels by 50 pixels BUT the frame strip is multiple frames together vertically. This means the full strip in our current example has a height of 150 pixels and a width of 50 pixels. Each frame in there is 50x50.
knobBg.pos = {210, 230}
k1.size = {50,50}
k1.pos = {210,230}
k1:setStripImage('assets/wvfrm_knob.png', 3)Knob Changed
The changed callback function is the same for the knob widget. In our example, we trigger a setParameter on the oscillator 1. We are also using a variable called self. By placing this variable inside of the function as a parameter, we are retrieving the value of the object itself, k1. This means when the knob changes, it gather the data itself. We can access the value with self.value.
If you recall the variable we created for the knob took a few parameters. The knob is specified to go from 0 to a value 2 and an integer. When we turn the knob, that self variable will be an integer between 0 and 2. Within the function we have this line, self.value * 0.33. The is simply reducing the value to a small decimal number. I do this because the parameter requires smaller values and this is the range I want.
k1.changed = function(self)
print("knob turned")
osc1:setParameter("PhaseDistortionAmount", self.value * 0.33)
endCallback Functions
Finally, we have the callback function onInit(). I created this in order to assign a default value of 0 to the Phase Distortion every time the script is loaded.
function onInit()
osc1:setParameter("PhaseDistortionAmount", 0)
end