Lua

Lua]] is a configuration language commonly used in game development. Lua scripts are executed in the same way as [[Perl]] and [[Python scripts within ‘’modo’’, and provide the same level of functionality.

As with Macros to obtain lower-level information from the various subsystems, including extracting specific mesh information that is not otherwise accessible through commands themselves.

For the official Lua documentation, visit [http://www.lua.org http://www.lua.org] .

modo Extensions to Lua

A number of new functions have been added to Lua in ‘’modo’’. The most common batch include ‘’lx’’, ‘’lxq’’, ‘’lxqt’’, ‘’lxeval’’, ‘’lxok’’, ‘’lxres’’, lxout and ‘’lxtrace’’. Errors are reported to the Event Log Viewport, so it?s useful to have one open while developing Lua scripts.

lx()

The lx function is used to execute commands using the standard modo Command System: Basics. This returns 1 if the command executed successfully, and nil if it failed for any reason. lxres can be used to get more specific information about why a command failed. Also be sure to check the Event Log viewport.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 -- lua

ok = lx( "tool.set prim.cube on" )
 if not ok then
     -- handle errors here
end
</syntaxhighlight >

=== lxq() ===

The '''lxq''' function queries a command using the standard question mark syntax, returning a table of values. Note that this always returns a table, even if there is only one value in the table.  Table keys are simple indices starting from 1.  ''table.foreach'' can be used to walk the array, or a simple for loop can be used. If there was an error querying the command, ''nil'' is returned.

Via table.foreach:

<syntaxhighlight lang="lua">
 -- lua

 function ProcessSelMaterialNames( index, name )
     -- Process material names here
 end

 -- Get an array of names, one for each selected material
 selMaterialNames = lxq( "material.name ?" )
 table.foreach( selMaterialNames, ProcessSelMaterialNames )

 -- Just look at the first value in the array.
 firstValue = selMaterialNames[1]
</syntaxhighlight >

via a form loop:

<syntaxhighlight lang="lua">
 -- lua

 -- Get an array of names, one for each selected material
 selMaterialNames = lxq( "material.name ?" )
 table.foreach( selMaterialNames, ProcessSelMaterialNames )

 -- Just look at the first value in the array.
 for i,k in ipairs(selMaterialNames) do
     -- Process 'k' (the material name) here
 end
</syntaxhighlight >

=== lxqt() ===

The '''lxqt''' function queries [[Command System: Basics#ToggleValue Arguments|ToggleValue]] commands like ''tool.set'', returning a simple ''true'' or ''false'' value. ''lxq'' can be used to get the current actual value of a ''ToggleValue'' command, which can be of any datatype and can be one of a number of possible values depending on the command. ''lxqt'' can be used to more easily see if the commands is "on" or not. This example checks to see if the ''Cube'' tool is currently active.

 <syntaxhighlight lang="lua">
 -- lua

 isActive = lxqt( "tool.set prim.cube on" )
</syntaxhighlight >

=== lxeval() ===

The '''lxeval''' function is a hyrid of ''lx'' and ''lxq''. If the command string contains a question mark, the command will be queried and returned; otherwise, the command is executed and success or failure is returned.  As with ''lxq'', querying with ''lxeval'' will always return a table.

<syntaxhighlight lang="lua">
 # lua

 -- Execute
 lxeval( "user.defNew MyValue" )
 lxeval( "user.value MyValue {Test Value}" )

 -- Query
 value = lxeval( "user.value MyValue ?" )
 if value[1] then
     -- Do something here
 end
</syntaxhighlight >

=== lxok() and lxres() ===

The results of ''lx'', ''lxq'', ''lxqt'' and ''lxeval'' can be tested with ''lxok'' and ''lxres''. '''lxok''' returns ''1'' if the last call was successful and ''0'' if not. '''lxres''' returns the LxResult code, which provides more specific details about result of the commands execution. A list of standard result codes and their meanings can be found in the error codes message table, [[msglxresult.cfg|resource:msglxresult.cfg]]

<syntaxhighlight lang="lua">
 -- Lua

 isOK = lxok
 result = lxres
</syntaxhighlight >

=== lxtrace() ===

The '''lxtrace''' function toggles tracing on and off. When tracing is enabled, all commands executed or queried  by ''lx'', ''lxq'' and the other execute/query functions are output to the ''Scripting'' sub-system of the ''Event Log'' viewport. This can also be used to see if tracing is on or not by not passing in an argument.

<syntaxhighlight lang="lua">
 -- lua

 isTracing = lxtrace()
 lxtrace( 1 )              -- Turn on tracing
</syntaxhighlight >

=== lxout() ===

The '''lxout''' function can be used to output debugging information to the ''Scripting'' sub-system of the Event Log viewport, and can be any string.

<syntaxhighlight lang="lua">
 -- lua

 lxout( "My Debug Output" )
</syntaxhighlight >

Here's another example that outputs the first element of a table representing the number of items in a scene through ''lxout''.

<syntaxhighlight lang="lua">
 -- lua

  n = lxq( "query sceneservice item.N ? all" )
  lxout( n[1].." items in scene." )
</syntaxhighlight >

=== lxoption() and lxsetOption() ===
The '''lxoption''' and '''lxsetOption''' functions allow the script to set properties that determine how the other ''lx'' functions operate. Each option is defined by a tag string and an associated value, and the options can be changed at any time.

Currently there is only one tag defined, '''queryAnglesAs''', which determines if angles queried through ''lxq'' are returned in radians or degrees. This defaults to degrees to maintain backwards compatibility with previous versions of ''modo''. While this behavior is helpful for new scripters, it is generally more useful to work in radians. The value can be set to either radians or degrees, and once set all future queries on angles through ''lxq'' will return those units.  The following shows how to change this option and query its current state.

<syntaxhighlight lang="lua">
 -- lua

 lxsetOption( "queryAnglesAs", "radians" )
 lxout( lxoption( "queryAnglesAs" ) )

Arguments

Arguments passed to a Lua script are handled in the same way as they are in a stand-alone Lua script. The global arg table contains all of the arguments, as well as the path to the script at key 0, which is standard Lua practice. The key 0 is not included in the total number of arguments. This means that #arg will return 0 if you execute a Lua script without passing any arguments to it, even though key 0 is always the script’s path.

This simple example outputs all of the arguments to the Event Log.

1
2
3
4
5
6
7
 -- lua

 lxout( "Script Path (arg[[0]): "..arg[0] );
 lxout( "Number of Arguments (#arg):  "..#arg );
 for k,v in pairs(arg) do
     lxout( "Arg "..k..": "..v )
 end

When executed like so:

1
 @C:\args.lua a b

the above would output the following to the Event Log:

1
2
3
4
5
 Script Path (arg[0]): C:\args.lua
 Number of Arguments (@arg): 2
 Arg 1: a
 Arg 2: b
 Arg 0: C:\args.lua

Exiting with error

A script can exit early by calling the Lua error function. This will open a dialog displaying the error message.

1
2
3
4
 -- lua

 if( #arg < 1 )
     error "Failed"

Progress Monitors

Progress bars, or ‘’monitors’’, are also supported in Lua through the lxmonInit and lxmonStep functions.

lxmonInit()

To initialize the progress bar, call lxmonInit with the total number of steps in the bar. lxmonInit should be called only once per script.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
 -- lua

 lxmonInit( 20 )
</syntaxhighlight >

=== lxmonStep() ===
To step the progress bar, use lxmonStep. By default, this increments the bar one step, but you can also increase the
bar by an arbitrary number steps.

<syntaxhighlight lang="lua">
 -- lua

 lxmonInit( 20 )

 lmonStep()        -- Increment by one
 lxmonStep( 2 )   - Step the progress bar by two
</syntaxhighlight >

The return value of ''lxmonStep'' is used by the script to determine if the hit the "abort" button in the progress dialog. If ''lxmonStep'' returns false, the script should abort. The following is a common test for a user abort.

<syntaxhighlight lang="lua">
 -- lua

 -- Initialize the monitor
 lxmonInit( 20 );

 for i = 0; i < 20;  i++ do

    -- Do work here

    -- Step the monitor and check for an abort
    if !lxmonStep()  then
        -- Do clean-up here
        error "User Abort";
    end

 end
</syntaxhighlight >

=== Monitor Example ===

This simple script demonstrates progress bars through the use of monitors. It busy loops so the progress bar will open. If the script executes fast enough, the progress bar will not appear.

<syntaxhighlight lang="lua">
 -- lua

 -- Initialize the monitor with 20 steps
 lxmonInit( 200 );

 -- Loop through our 200 steps
 for i=0,200 do

     -- Do work (i.e.: busy loop )
     for j=0,1000000  do
         ;
     end

     -- Step the monitor and check for an abort
     if !lxmonstep() then
         -- Clean up and exit
         error "User Abort";
     end
 end

More Information