Difference between revisions of "Scripting"
(→Commands for Visionaire Player only) |
|||
(89 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
− | + | Visionaire Studio comes with its own scripting language, which consists of, a combination of: '''Lua script''' and a '''Visionaire object model'''. The object model is used to access the Visionaire data structure in a convenient way. Almost every instance in Visionaire is represented as an object (e. g. scene, character, interface, ...), all of which can be accessed/manipulated through the scripting language. | |
− | |||
− | + | == Lua == | |
− | + | Visionaire Studio currently uses Lua version 5.4.0. | |
− | |||
− | = | + | If you want to learn more about the language, you may refer to the official online documentation on the Lua website or have a look at some tutorials: |
+ | <div style="float:right;margin:20px 0 30px 30px">[[File:Lua-logo.png]]</div> | ||
+ | * Reference Manual: https://www.lua.org/manual/5.4/ | ||
+ | * Programming in Lua: https://www.lua.org/start.html | ||
+ | * Lua tutorial: https://www.tutorialspoint.com/lua/index.htm | ||
+ | * Learn Lua in 15 Minutes: https://tylerneylon.com/a/learn-lua/ | ||
− | |||
− | + | Our community member ''AFRLme'' wrote a basic Lua introduction which you can find in this wiki: | |
− | + | * [[Basic_lua:_Index|Basic Lua: AFRLme's guide to Lua script]] | |
− | |||
− | |||
− | '' | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | == Visionaire object model == | |
− | |||
− | |||
− | |||
− | + | Each Visionaire project is saved in a hierarchical [[Data_Structure|data structure]]. Every instance of an object of that data structure is a "VisionaireObject" (TVisObj). All objects of the same type (e. g. scene or button) are stored in one table (called e. g. "Scenes" or "Buttons"). | |
− | The | + | The properties of an object can be accessed by defined fields for the specific table. These fields can contain single values (e. g. integers, strings) or tables of values as well as links to other VisionaireObjects or tables of links to VisionaireObjects. All objects and their fields are documented on the [[Data_Structure|data structure]] page. The different [[#Field types|field types]] are listed below. |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | === Accessing objects and fields === | |
− | The | + | The data structure tables are globally accessible. Object instances within the tables are usually accessed by their name, but it is also possible to use the table index. The "game" object is not contained in a table but directly accessible. |
+ | <syntaxhighlight lang="lua"> | ||
+ | -- Examples of accessing a VisionaireObject by (a unique) name | ||
+ | local char = Characters["hero"] | ||
+ | local coins = Values["coins"] | ||
− | = | + | -- The following syntax is also possible, but be aware that it only works for object names which don't contain |
+ | -- special characters or whitespaces (only A-Z, a-z, 0-9 and underscore allowed) and start with a letter | ||
+ | local char = Characters.hero | ||
− | + | -- Access a VisionaireObject by table index: get the first object in the "Characters" table | |
+ | local char = Characters[1] | ||
+ | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | Object properties are accessed through their fields: |
+ | <syntaxhighlight lang="lua"> | ||
+ | -- Example of accessing a property of a VisionaireObject | ||
+ | local char = Characters["hero"] | ||
+ | local pos = char.Position | ||
− | + | -- This leads to the same result | |
− | + | local pos = Characters["hero"].Position | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -- Get the integer value ("Int" field) of the "Value" object called "coins" | |
− | + | local num_coins = Values["coins"].Int | |
− | = | + | -- The "game" object is directly accessible |
− | + | local scr_pos = game.ScrollPosition | |
− | + | </syntaxhighlight> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | If other VisionaireObjects are linked in an object property, you can specify the complete object path to access them. This is especially helpful, if you have non-unique object names which cannot be accessed purely by their name: |
+ | <syntaxhighlight lang="lua"> | ||
+ | -- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]' | ||
+ | -- because the name is not unique; now access the different values by using the object path | ||
+ | local hero_num_coins = Characters["hero"].Values["coins"].Int | ||
+ | local villain_num_coins = Characters["villain"].Values["coins"].Int | ||
+ | local cur_num_coins = game.CurrentCharacter.Values["coins"].Int | ||
− | + | -- Object paths can be even longer | |
− | + | local door_state = Scenes["kitchen"].Objects["door"].Conditions["door_closed"] | |
− | |||
− | |||
− | |||
− | + | -- If the condition name "door_closed" is unique in the project, the following leads to the same result | |
− | + | local door_state = Conditions["door_closed"] | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Writing a field value is just as easy. However, not all fields of the data structure can be changed through script. Please refer to the [[Data_Structure|data structure]] page: | |
− | <syntaxhighlight> | + | <syntaxhighlight lang="lua"> |
− | + | -- Lower the brightness of a scene to 80% | |
− | + | Scenes["kitchen"].Brightness = 80 | |
− | |||
− | |||
− | |||
− | |||
− | = | + | -- Make the villain the playable character |
+ | game.CurrentCharacter = Characters["villain"] | ||
− | + | -- Set a condition to true | |
− | + | Conditions["door_closed"].Value = true | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -- Change the integer value of a "Value" object | |
− | + | Characters["hero"].Values["coins"].Int = 47 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | + | === Common VisionaireObject fields === | |
− | |||
− | |||
− | |||
− | |||
− | === | + | The following fields are available for all VisionaireObjects. They are read-only (except "name" which can be written with the "setName" method): |
+ | * <span class="inlinecode">id:</span> The internal id of the object (integer). | ||
+ | * <span class="inlinecode">name:</span> The internal name of the object as defined in the editor (string). Not to be confused with the "Name" property (with capitalized "N") which is available for some objects and contains the multi-language object name used in the game. | ||
+ | * <span class="inlinecode">parent:</span> Returns the parent object (TVisObj). | ||
+ | * <span class="inlinecode">tableId:</span> The id of the data structure table the object is part of (integer). | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | === Field types === |
− | + | The field types of the data structure are mapped to Lua types in the following way: | |
− | |||
− | |||
− | |||
− | The field | ||
− | |||
− | |||
− | |||
− | === | + | {| class="ts" |
− | + | |- | |
− | + | ! style="width:10%" | Field Type | |
− | + | ! style="width:5%" colspan="2" | Lua type/Structure | |
− | + | ! Description | |
− | + | |- | |
− | + | | '''t_bool''' | |
− | + | | colspan="2" | boolean | |
− | + | | true or false | |
− | + | |- | |
− | + | | '''t_int''' | |
− | === | + | | colspan="2" | number |
− | + | | integer | |
− | + | |- | |
− | + | | '''t_float''' | |
− | + | | colspan="2" | number | |
− | ; | + | | decimal |
− | + | |- | |
− | + | | '''t_string''' | |
− | + | | colspan="2" | string | |
− | + | | | |
− | + | |- | |
− | === | + | | '''t_path''' |
+ | | colspan="2" | string | ||
+ | | file path | ||
+ | |- | ||
+ | | rowspan="2" | '''t_point''' | ||
+ | | rowspan="2" | table | ||
+ | | style="width:15%" | x (int) | ||
+ | | x coordinate | ||
+ | |- | ||
+ | | y (int) | ||
+ | | y coordinate | ||
+ | |- | ||
+ | | rowspan="4" | '''t_rect''' | ||
+ | | rowspan="4" | table | ||
+ | | x (int) | ||
+ | | x coordinate of top left corner | ||
+ | |- | ||
+ | | y (int) | ||
+ | | y coordinate of top left corner | ||
+ | |- | ||
+ | | width (int) | ||
+ | | width of rectangle | ||
+ | |- | ||
+ | | height (int) | ||
+ | | height of rectangle | ||
+ | |- | ||
+ | | rowspan="5" | '''t_sprite''' | ||
+ | | rowspan="5" | table | ||
+ | | path (str) | ||
+ | | relative path to image file | ||
+ | |- | ||
+ | | position (t_point) | ||
+ | | sprite offset in case sprite is used in an animation | ||
+ | |- | ||
+ | | transparency (int) | ||
+ | | | ||
+ | |- | ||
+ | | transpcolor (int) | ||
+ | | transparent color | ||
+ | |- | ||
+ | | pause (int) | ||
+ | | pause value in milliseconds in case sprite is used in an animation | ||
+ | |- | ||
+ | | rowspan="3" | '''t_text''' | ||
+ | | rowspan="3" | table | ||
+ | | text (str) | ||
+ | | | ||
+ | |- | ||
+ | | sound (str) | ||
+ | | file path to a sound file for this text | ||
+ | |- | ||
+ | | language (int) | ||
+ | | id of the language of this text object | ||
+ | |- | ||
+ | | '''t_link''' | ||
+ | | colspan="2" | string | ||
+ | | a link to a VisionaireObject (TVisObj); the object will be returned on access; the link can be set with an object | ||
+ | |- | ||
+ | | '''t_links''' | ||
+ | | colspan="2" | table | ||
+ | | a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects | ||
+ | |- | ||
+ | | '''t_vint''' | ||
+ | | colspan="2" | table | ||
+ | | table with number (integer) entries | ||
+ | |- | ||
+ | | '''t_vfloat''' | ||
+ | | colspan="2" | table | ||
+ | | table with number (float) entries | ||
+ | |- | ||
+ | | '''t_vstring''' | ||
+ | | colspan="2" | table | ||
+ | | table with string entries | ||
+ | |- | ||
+ | | '''t_vpath''' | ||
+ | | colspan="2" | table | ||
+ | | table with t_path entries | ||
+ | |- | ||
+ | | '''t_vpoint''' | ||
+ | | colspan="2" | table | ||
+ | | table with t_point entries | ||
+ | |- | ||
+ | | '''t_vrect''' | ||
+ | | colspan="2" | table | ||
+ | | table with t_rect entries | ||
+ | |- | ||
+ | | '''t_vsprite''' | ||
+ | | colspan="2" | table | ||
+ | | table with t_sprite entries | ||
+ | |- | ||
+ | | '''t_vtext''' | ||
+ | | colspan="2" | table | ||
+ | | table with t_text entries | ||
+ | |} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | === | + | === The old-fashioned "longhand notation" === |
− | + | While the syntax described in the chapter "Accessing objects and fields" is recommended, there is another way of accessing VisionaireObjects. It dates back to the early days of scripting in Visionaire and you may come across script examples which still use this old-fashioned way. It is usually referred to as the "longhand notation" - in contrast to the much simpler "shorthand" from above. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | == | + | Use the global [[Global Command: getObject|getObject]] command to access a VisionaireObject and [[VisionaireObject Commands|object commands]] to get and set property fields: |
+ | <syntaxhighlight lang="lua"> | ||
+ | -- Example of accessing a VisionaireObject by (a unique) name | ||
+ | local char = getObject("Characters[hero]") | ||
− | + | -- Example of accessing a VisionaireObject by passing a tuple: | |
− | + | -- get the object with id=1 from the table with id=0 (characters table). | |
− | + | local char = getObject("(0,1)") | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | = | + | -- Note that in the object path, VisionaireObject names need to be prefixed with the (singular) table name |
+ | local door_state = getObject("Scenes[kitchen].SceneObjects[door].ObjectConditions[door_closed]") | ||
− | + | -- If you want to get/set a field you need the appropriate object method and have to use the field constants. | |
− | + | -- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix) | |
− | + | local is_closed = door_state:getBool(VConditionValue) | |
− | + | door_state:setValue(VConditionValue, true) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | == Add a script == | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | [[File:Script.png|thumb|250px|Scripts section]] | |
+ | Scripts are generally added in the "Scripts" section of the editor. Each script has to be declared a <span class="inlinecode">Definition script</span> or an <span class="inlinecode">Execution script</span> by (un)checking the option above the script editor (see image). A definition script is automatically run at game start, while an execution script has to be explicitly called. | ||
− | {{ | + | In your actions you can make use of scripts by using the [[Action_Parts#Call_script|Call script]] and the [[Action_Parts#Execute_a_script|Execute a script]] action parts, with the first one allowing you to select from your list of execution scripts and the second one expecting Lua code. You can use the [[Action_Parts#If_Lua_result|If Lua result]] action part to build an "if…else" query using Lua code. Besides that, a Lua query can also be part of a [[Conditions_and_Values#Conditions|Combined condition]]. |
+ | {{toc}} |
Latest revision as of 12:54, 16 January 2024
Visionaire Studio comes with its own scripting language, which consists of, a combination of: Lua script and a Visionaire object model. The object model is used to access the Visionaire data structure in a convenient way. Almost every instance in Visionaire is represented as an object (e. g. scene, character, interface, ...), all of which can be accessed/manipulated through the scripting language.
Lua
Visionaire Studio currently uses Lua version 5.4.0.
If you want to learn more about the language, you may refer to the official online documentation on the Lua website or have a look at some tutorials:
- Reference Manual: https://www.lua.org/manual/5.4/
- Programming in Lua: https://www.lua.org/start.html
- Lua tutorial: https://www.tutorialspoint.com/lua/index.htm
- Learn Lua in 15 Minutes: https://tylerneylon.com/a/learn-lua/
Our community member AFRLme wrote a basic Lua introduction which you can find in this wiki:
Visionaire object model
Each Visionaire project is saved in a hierarchical data structure. Every instance of an object of that data structure is a "VisionaireObject" (TVisObj). All objects of the same type (e. g. scene or button) are stored in one table (called e. g. "Scenes" or "Buttons").
The properties of an object can be accessed by defined fields for the specific table. These fields can contain single values (e. g. integers, strings) or tables of values as well as links to other VisionaireObjects or tables of links to VisionaireObjects. All objects and their fields are documented on the data structure page. The different field types are listed below.
Accessing objects and fields
The data structure tables are globally accessible. Object instances within the tables are usually accessed by their name, but it is also possible to use the table index. The "game" object is not contained in a table but directly accessible.
-- Examples of accessing a VisionaireObject by (a unique) name
local char = Characters["hero"]
local coins = Values["coins"]
-- The following syntax is also possible, but be aware that it only works for object names which don't contain
-- special characters or whitespaces (only A-Z, a-z, 0-9 and underscore allowed) and start with a letter
local char = Characters.hero
-- Access a VisionaireObject by table index: get the first object in the "Characters" table
local char = Characters[1]
Object properties are accessed through their fields:
-- Example of accessing a property of a VisionaireObject
local char = Characters["hero"]
local pos = char.Position
-- This leads to the same result
local pos = Characters["hero"].Position
-- Get the integer value ("Int" field) of the "Value" object called "coins"
local num_coins = Values["coins"].Int
-- The "game" object is directly accessible
local scr_pos = game.ScrollPosition
If other VisionaireObjects are linked in an object property, you can specify the complete object path to access them. This is especially helpful, if you have non-unique object names which cannot be accessed purely by their name:
-- Let's say each character has a value property called "coins"; it is not possible to use 'Values["coins"]'
-- because the name is not unique; now access the different values by using the object path
local hero_num_coins = Characters["hero"].Values["coins"].Int
local villain_num_coins = Characters["villain"].Values["coins"].Int
local cur_num_coins = game.CurrentCharacter.Values["coins"].Int
-- Object paths can be even longer
local door_state = Scenes["kitchen"].Objects["door"].Conditions["door_closed"]
-- If the condition name "door_closed" is unique in the project, the following leads to the same result
local door_state = Conditions["door_closed"]
Writing a field value is just as easy. However, not all fields of the data structure can be changed through script. Please refer to the data structure page:
-- Lower the brightness of a scene to 80%
Scenes["kitchen"].Brightness = 80
-- Make the villain the playable character
game.CurrentCharacter = Characters["villain"]
-- Set a condition to true
Conditions["door_closed"].Value = true
-- Change the integer value of a "Value" object
Characters["hero"].Values["coins"].Int = 47
Common VisionaireObject fields
The following fields are available for all VisionaireObjects. They are read-only (except "name" which can be written with the "setName" method):
- id: The internal id of the object (integer).
- name: The internal name of the object as defined in the editor (string). Not to be confused with the "Name" property (with capitalized "N") which is available for some objects and contains the multi-language object name used in the game.
- parent: Returns the parent object (TVisObj).
- tableId: The id of the data structure table the object is part of (integer).
Field types
The field types of the data structure are mapped to Lua types in the following way:
Field Type | Lua type/Structure | Description | |
---|---|---|---|
t_bool | boolean | true or false | |
t_int | number | integer | |
t_float | number | decimal | |
t_string | string | ||
t_path | string | file path | |
t_point | table | x (int) | x coordinate |
y (int) | y coordinate | ||
t_rect | table | x (int) | x coordinate of top left corner |
y (int) | y coordinate of top left corner | ||
width (int) | width of rectangle | ||
height (int) | height of rectangle | ||
t_sprite | table | path (str) | relative path to image file |
position (t_point) | sprite offset in case sprite is used in an animation | ||
transparency (int) | |||
transpcolor (int) | transparent color | ||
pause (int) | pause value in milliseconds in case sprite is used in an animation | ||
t_text | table | text (str) | |
sound (str) | file path to a sound file for this text | ||
language (int) | id of the language of this text object | ||
t_link | string | a link to a VisionaireObject (TVisObj); the object will be returned on access; the link can be set with an object | |
t_links | table | a list of VisionaireObject (TVisObj) links, can be iterated with numbers and names of the objects | |
t_vint | table | table with number (integer) entries | |
t_vfloat | table | table with number (float) entries | |
t_vstring | table | table with string entries | |
t_vpath | table | table with t_path entries | |
t_vpoint | table | table with t_point entries | |
t_vrect | table | table with t_rect entries | |
t_vsprite | table | table with t_sprite entries | |
t_vtext | table | table with t_text entries |
The old-fashioned "longhand notation"
While the syntax described in the chapter "Accessing objects and fields" is recommended, there is another way of accessing VisionaireObjects. It dates back to the early days of scripting in Visionaire and you may come across script examples which still use this old-fashioned way. It is usually referred to as the "longhand notation" - in contrast to the much simpler "shorthand" from above.
Use the global getObject command to access a VisionaireObject and object commands to get and set property fields:
-- Example of accessing a VisionaireObject by (a unique) name
local char = getObject("Characters[hero]")
-- Example of accessing a VisionaireObject by passing a tuple:
-- get the object with id=1 from the table with id=0 (characters table).
local char = getObject("(0,1)")
-- Note that in the object path, VisionaireObject names need to be prefixed with the (singular) table name
local door_state = getObject("Scenes[kitchen].SceneObjects[door].ObjectConditions[door_closed]")
-- If you want to get/set a field you need the appropriate object method and have to use the field constants.
-- A field constant starts with a "V" followed by the field name (including the aforementioned table prefix)
local is_closed = door_state:getBool(VConditionValue)
door_state:setValue(VConditionValue, true)
Add a script
Scripts are generally added in the "Scripts" section of the editor. Each script has to be declared a Definition script or an Execution script by (un)checking the option above the script editor (see image). A definition script is automatically run at game start, while an execution script has to be explicitly called.
In your actions you can make use of scripts by using the Call script and the Execute a script action parts, with the first one allowing you to select from your list of execution scripts and the second one expecting Lua code. You can use the If Lua result action part to build an "if…else" query using Lua code. Besides that, a Lua query can also be part of a Combined condition.