Where to Script
There are a few places where you can define a script, depending on the situation and what the script will do.
Events
The most common place to define a script is inside an event, where it will be triggered when that event is triggered. A common event is the onClick event inside of a button, which will execute the script when the button is tapped on by the user.
Events can be identified by the "on" prefix of their name. A list of events that can be accessed in qdex can be found below.
Script Tag
Another place where scripts can be defined is inside script tags. They are an ideal place to define any script that will be accessed by multiple elements, such as variables and functions. It is also where variables should first be initialized before being altered by a script inside of an event.
In the below example, a variable is defined inside of a script tag. Each time a button is pressed in the app, the variable is incremented and a paragraph outputs the new value of the variable to a paragraph.
<script> -- Defining and initialising the variable local myVariable = 5 </script> <button content="Tap this Button!"> <onClick> -- Incrementing the value myVariable = myVariable + 1 -- Displaying the new value inside of a paragraph thisPar.Text = string.format("The value of myVariable is %d", myVariable) </onClick> </button> <p name="thisPar"/>
The above example could also be written using a function, where the onClick event calls a function that performs the same actions.
<script> -- Defining and initialising the variable local myVariable = 5 --Defining a function to increment the variable and update the paragraph local function addValue() myVariable = myVariable + 1 thisPar.Text = string.format("The value of myVariable is %d", myVariable) end </script> <button content="Tap this Button!"> <onClick> addValue() </onClick> </button> <p name="thisPar"/>
It doesn't necessarily make sense to use a function in the above example, as the function performs a single action that is just as easily defined inside the onClick event. Functions are better used to define generic actions so that they can be used by multiple elements easily.
In the below example, a function is used to increment a specified variable by a specified number. Two different buttons can use this one function to perform different tasks by changing the arguments to the function.
<script> -- Defining and initialising the variables local myVariable = 5 local myOtherVariable = 8 --Defining a function to increment a variable by the specified number local function addValues(variableName, addNumber) variableName = variableName + addNumber end </script> <button content="Tap this Button!"> <onClick> -- Increment myVariable by 1 on each click addValue(myVariable, 1) </onClick> </button> <button content="Tap this Other Button!"> <onClick> -- Increment myOtherVariable by -3 on each click addValue(myOtherVariable, -3) </onClick> </button>
System Block
Although traditionally used to define a custom system with states in a simulation, the system block can also be used to pass Lua script between elements inside and outside of a simulation.
In the below example, the amplitude of a sine wave is output to a label in real time.
<label name="thisLabel" /> <simulation name="sim"> <onActivePageChanged> if active then sim:Start() else sim:Stop() end </onActivePageChanged> <solver> <series> <sine /> <system name="outputMySine"> <input name="ampValue" width="1" /> <onOutputs> thisLabel.Text = string.format("%0.2f", ampValue[1]) </onOutputs> </system> </series> </solver> </simulation>
The system block can also be used to send a value to a simulation so that it can be manipulated or streamed. In this example, the value of a toggle and a slider are put into a vector and brought into a simulation using a system. The vector is then sent to hardware over TCP/IP.
<client name="myStream" uri="tcpip://172.16.0.62:18000" /> <script> local valueVector = vector(2); </script> <toggle name="toggleName"> <onValueChanged> valueVector[1] = toggleName.Value; </onValueChanged> </toggle> <slider name="mySlider" min="0" max="15" value="0"> <onValueChanged> valueVector[2] = value; </onValueChanged> </slider> <simulation name="sim" period="0.01"> <solver name="solver2"> <series> <system name="mySystem"> <output name="myOutput" width="2" /> <onOutputs> return valueVector </onOutputs> </system> <probe ref="mySection.myStream" /> </series> </solver> </simulation>