Tinman 3D contains a scripting language that can be used to create and configure native objects from classes found in the SDK.
The scripting functionality is provided by the ConfigScript class and its friends.
For details on how to use the scripting language, please refer to the Geodata Examples and the tutorial script:
// ------------------------------------------------------------------------------------------------- // _____ _______ ____ _____ // ,-:` \;',`'-, |__ _(_) |___ \ | __ \ // .'-;_,; ':-;_,'. | | _ _ __ _ __ ___ __ _ _ __ __) || | | | // /; '/ , _`.-\ | || || '_ \ | '_ ` _ \ / _` || '_ \ |__ < | | | | // | '`. (` /` ` \`| | || || | | || | | | | || (_| || | | | ___) || |__| | // |:. `\`-. \_ / | |_||_||_| |_||_| |_| |_| \__,_||_| |_| |____/ |_____/ // | ( `, .`\ ;'| // \ | .' `-'/ Realtime terrain processing, rendering and analysis // `. ;/ .' // `'-._____.-'` http://www.tinman3d.com - info@tinman3d.com // // ------------------------------------------------------------------------------------------------- // FILE / DATE: tutorial.tms // // COPYRIGHT: Matthias Englert, me@tinman3d.com // // AUTHOR(s): Matthias Englert, me@tinman3d.com // // DISCLAIMER: This source code is provided "as is" and without warranties as to performance or // merchantability. The author and/or distributors of this source code may have // made statements about this source code. Any such statements do not constitute // warranties and shall not be relied on by the user in deciding whether to use // this source code. // // This source code is provided without any expressed or implied warranties // whatsoever. Because of the diversity of conditions and hardware under which this // source code may be used, no warranty of fitness for a particular purpose is // offered. The user is advised to test the source code thoroughly before relying // on it. The user must assume the entire risk of using the source code. // ------------------------------------------------------------------------------------------------- // A config script can have an optional name prefix, which is used to access its public members from // other scripts in the same domain via the '::' operator, for example 'Tutorial::variable'. // The Workshop puts all scripts of a project into the same domain. script Tutorial; // ------------------------------------------------------------------------------------------------- // Script members // ------------------------------------------------------------------------------------------------- ` This is a public script variable, documented with the special 'backtick' comment, which is ` accessible via the API. variable : string = "Hello World!"; // \____________/ // This is the default value of the script variable; it can be overwritten via // the API. // \____/ // This is the variable type. If omitted, the type is infered from the default value. // \_______/ // This is the variable name. ` This is a private script variable. It cannot be accessed from other scripts. intern variable1 : string = "Hello World!"; ` This is a variable without a default value. The API must be used to specify a value. It cannot be ` browsed or inspected in the Workshop. intern variable2 : string; ` This is a variable with a value constraint. Constraint violations will cause validation failures, ` which are shown in the Messages windows. intern variable3 : number { # < 0 } = -1; ` This is a public script function. The Workshop can browse resp. inspect a script function only ` if all parameters have default values. function(` Function parameters can also be documented using the special 'backtick' comment. a : number = 10, b : number = 20) : string = "a=" + a + ", b=" + b + ", a+b=" + (a + b); // \________________________________________/ // This is the expression that is evaluated // when the function is called. // \____/ // This is the function return type. If omitted, the // type is inferred from the right-side expression. // \______________________________/ // These are the function parameters. Parameter declarations use the same syntax as script // variables, except the 'intern' keyword. Each parameter can have a leading documentation // comment. // \______/ // This is the function name. // The built-in script 'Tinman' provides some utililty functions, which are implemented externally. intern extern1 = Tinman::string_part('Hello World!', 1, 5); intern extern2 = Tinman::string_part('Hello World!', 5, 1); intern extern3 = Tinman::string_part('Hello World!', 0, 6); intern extern4 = Tinman::string_part('Hello World!', 6, 0); intern extern5 = Tinman::string_part('Hello World!', 0, -7); intern extern6 = Tinman::string_part('Hello World!', -7, 0); // ------------------------------------------------------------------------------------------------- // Data types // ------------------------------------------------------------------------------------------------- // Data type 'bool', can be true or false. typeBool : bool = true; intern typeBool1 : bool = false; // Data type 'number', represented as a 64-bit floating-point number. typeNumber : number = 123456; intern typeNumber1 : number = 0xFF; intern typeNumber2 : number = -1.234e+56; intern typeNumber3 : number = +inf; intern typeNumber4 : number = -inf; intern typeNumber5 : number = nan; // Data type 'string', a nullable character sequence. typeString : string = null; intern typeString1 : string = ""; intern typeString2 : string = "Hello'""World!"; intern typeString3 : string = 'Hello"''World!'; // Data type 'path', a nullable filesystem path. typePath : path = null; intern typePath1 : path = <c:\windows\style>; intern typePath2 : path = <\\localhost\UNC\style>; intern typePath3 : path = </unix/style>; intern typePath4 : path = <relative/to/current/directory.txt>; intern typePath5 : path = <./relative/to/script/directory.txt>; intern typePath6 : path = `alternative/syntax/for/command/line`; // Data type 'array', a nullable, fixed-length list of equally typed values. typeArray = [1,2,3,"4",5]; // Element type is inferred from first element, intern typeArray1 = [number: "1",2,3,"4",5]; // ...is specified in array expression, intern typeArray2 : number[] = ["1",2,3,4,5]; // ...or will be inferred from array type. // Data type 'enum', a pre-defined set of possible values. typeEnum = Colors.Red; intern typeEnum1 : Colors = Red; // Can omit name of enum type if inferred from context. // Data type 'object', an instance of a pre-defined class. typeObject = {Vec3: 1,2,3}; // Constructor-style with explicit class name. intern typeObject1 = Vec3 { z = 3, y = 2, x = 1 }; // Initializer-style with explicit class name. intern typeObject2 : Vec3 = {1,2,3}; // Constructor-style with inferred class name. intern typeObject3 : Vec3 = { z = 3, y = 2, x = 1 }; // Initializer-style with inferred class name. intern typeObject4 : PixelRange = {Vec2: 1, 2}; // Mismatching types are fixed automatically, // if the constructor-style syntax can be used, // passing the value as single argument. // ------------------------------------------------------------------------------------------------- // Expressions (lowest precedence first) // ------------------------------------------------------------------------------------------------- // Set operators (e.g. union, intersection) can be used on arrays that have a simple element type, // i.e. bool, number, string, path or enum. // Functional operators intern expr_1_1 = typeArray1 => # * @; // Evaluates the right-side expression for each element in // left-side array and returns an array that holds the // resulting values. // '#' refers to the array element // '@' refers to the array index intern expr_1_2 = typeArray1 ?> # > 2; // Evaluates the right-side expression for each element in // left-side array and returns an array that holds those // elements for which the resulting value is true. // '#' refers to the array element // '@' refers to the array index // Conditional operators intern expr_2 = typeBool ? "A" : "B"; // Depending on the condition value, either the left-side // (true) or right-side (false) expression is evaluated. intern expr_3 = typeBool || typeBool1; // Conditional OR with short-circuit evaluation. intern expr_4 = typeBool && typeBool1; // Conditional AND with short-circuit evaluation. // Logical operators intern expr_5_1 = typeBool | typeBool1; // bool : Evaluates both sides and computes OR. intern expr_5_2 = typeNumber | 0xFFFF; // number : Interprets both sides as 64-bit integers // and computes the bit-wise OR. intern expr_5_3 = [1,2] | [2,3]; // set : Computes the union of the given sets. intern expr_6_1 = typeBool ^ typeBool1; // bool : Evaluates both sides and computes XOR. intern expr_6_2 = typeNumber ^ 0xFFFF; // number : Interprets both sides as 64-bit integers // and computes the bit-wise XOR. intern expr_6_3 = [1,2] ^ [2,3]; // set : Computes the symmetric difference of the // given sets. intern expr_7_1 = typeBool & typeBool1; // bool : Evaluates both sides and computes AND. intern expr_7_2 = typeNumber & 0xFFFF; // number : Interprets both sides as 64-bit integers // and computes the bit-wise AND. intern expr_7_3 = [1,2] & [2,3]; // set : Computes the intersection of the given sets. // Equality operators intern expr_8_1 = typeBool == typeBool1; // Left and right values are equal? intern expr_8_2 = typeBool != typeBool1; // Left and right values are not equal? // Relational operators intern expr_9_1 = typeNumber < 1; // Left number is smaller than right one? intern expr_9_2 = typeNumber <= 1; // Left number is smaller than or equal to right one? intern expr_9_3 = typeNumber > 1; // Left number is greater than right one? intern expr_9_4 = typeNumber >= 1; // Left number is greater than or equal to right one? // Shift operators intern expr_10_1 = typeNumber << 1; // Interprets the left number as a 64-bit integer and // performs a bit-wise left shift by the given amount. intern expr_10_2 = typeNumber >> 1; // Interprets the left number as a 64-bit integer and // performs a bit-wise right shift by the given amount. // Additive operators intern expr_11_1 = typeNumber + 1; // number : Adds the left and right numbers. intern expr_11_2 = typeString2 + "1"; // string : Appends the right string to the left one. intern expr_11_3 = typePath5 + "a"; // path : Appends a suffix to the path value. intern expr_11_4 = typePath5 + <a>; // path : Concatenates the given path values. intern expr_11_5 = [1,2] + [2,3]; // array : Concatenates the given arrays. intern expr_11_6 = typeNumber - 1; // number : Subtracts the right number from the left one. intern expr_11_7 = typePath5 - 'y'; // path : Removes the path suffix, starting at the // rightmost occurence of the given character. intern expr_11_8 = [1,2,3] - [2,4]; // set : Subtracts the right set from the left one. // Multiplicative operators intern expr_12_1 = typeNumber * 2; // Multiplies the left and right numbers. intern expr_12_2 = typeNumber / 2; // Divides the left number by the right number. intern expr_12_3 = typeNumber % 2; // Computes the remainder of the division. intern expr_13_1 = typeNumber ** 10; // Raises the number to the given power. intern expr_13_2 = typeNumber \\ 10; // Extracts the nth root from the number. // Unary operators intern expr_14_1 = - typeNumber; // number : Negates the number value. intern expr_14_2 = - typePath5; // path : Removes the path suffix. intern expr_14_3 = + typeNumber; // number : Replicates the number value. intern expr_14_4 = + typePath5; // path : Returns the canonical path value. intern expr_14_5 = ! typeBool; // bool : Inverts the boolean value. intern expr_14_6 = ! typePath5; // path : Returns the last path element. intern expr_14_7 = ~ typeNumber; // number : Interprets the number value as a // 64-bit integer value and inverts the bits. intern expr_15_8 = ~ typePath5; // path : Removes the last path element. intern expr_15_9 = ~ [3,2,1,2]; // set : Collapsed the array into a sorted set. // Compound expressions intern expr_16_1 = typeObject.x; // Member access on object value. intern expr_16_2 = typeArray[2]; // Element access on array value. intern expr_16_3 = typeObject // Chained object creation: left-side expression @ Vector.Constant(); // becomes first constructor argument or field value. // Primary expressions intern expr_17_1 = "literal"; // Literal intern expr_17_2 = ["array"]; // Array creation intern expr_17_3 = {Vec2: 1,2}; // Object creation intern expr_17_4 = function(1,2); // Function call intern expr_17_5 = ("braces"); // Braced expression intern expr_17_6 = $TINMAN_3D_LICENCEKEY; // Value of environment variable
The following sections describe the basic data types that are defined for config scripts.
A boolean value which is either true or false
The following literal expression can be used for boolean values:
value : bool = true false ;
A number value.
Number literals can be in decimal notation:
value : number = 123 123.45 123E+67 123.45E+67
Integer literals can also be in hexadecimal notation:
value : number = 0x123456789ABCDEF
A sequence of Unicode characters.
String literals can be enclosed in single quotes '
or double quotes "
. Their escape sequences are ''
and ""
.
value : string = 'Hello World!' "Hello World!" 'You are here: 12°34''56.789"N 123°45''57.891"E' "You are here: 12°34'56.789""N 123°45'57.891""E"
A filesystem path to a file or directory.
Path literals can be enclosed in angle brackets < and >. Alternatively, backticks ´ can be used (for example on the command-line where angle brackets have a special meaning).
<mydataset.hgt> <../parent-directory/> ´my file.dat´
An enumerated value with a fixed set of possible value items.
value : Color = Red Green Blue
The enum name Color
of the above example is omitted in scripts because it can always be infered from the context of the usage site.
A sequence of equally typed values.
value : number[] = [1, 2, 3, 4] : string[] = ["a", 'b', "c'] : number[][] = [[1,2,3], [2,3,4], [5,6,7]]
A compound value that that aggregates named values of arbitrary types (i.e. fields).
The names, types and the order of the fields of a struct value is defined by the system.
A compound value similar to struct, with the following additions:
The following sections describe the expressions that are available in config scripts.
The following table shows the operator expressions that are available in configuration scripts:
Operator | Description | Precedence |
---|---|---|
|
Evaluates
The order of elements |
0 |
a ?> expr
|
Evaluates
The order of elements |
|
|
Evaluates a as a bool value, then evaluates either b if true or c if false . |
1 |
a || b
|
Evaluates to Uses short-circuit evaluation, i.e. |
2 |
a && b
|
Evaluates to Uses short-circuit evaluation, i.e. |
3 |
|
|
4 |
a ^ b |
|
5 |
a & b
|
|
6 |
|
Checks if Returns |
7 |
|
Evaluates Returns |
8 |
|
Evaluates Right shifting will keep the most-significant bit, so |
9 |
|
|
10 |
a - b
|
|
|
|
Evaluates a and b as a |
11 |
a / b
|
Evaluates a and b as a number , then computes the result of the division of a by b . |
|
a % b
|
Evaluates The remainder is defined as |
|
|
Evaluates a and b as a |
12 |
a \\ b
|
Evaluates a and b as a number , then raises a by the power of 1/b . |
|
|
|
13 |
|
|
|
!a
|
|
|
~a
|
|
|
|
Evaluates |
14 |
a[b]
|
Evaluates a as an array and accesses the element at zero-based index b . |
|
|
Refers to a script variable, a type field, a namespace or type name. |
15 |
|
A braced expression that overrides default precedence rules. | |
|
An array or object creation expression, see below. |
Array values are created using the following syntax:
[Colors: Red, Green, Blue] [number: 1, 2, 3, 4] [string[]: ["a","b","c"], ["1","2","3"]]
Implicit typing requires that the array type can be inferred from the surrounding context or from the contained elements.
[Red, Green, Blue] [1, 2, 3, 4] [["a","b","c"], ["1","2","3"]]
An object can only be created from a type iff values for all mandatory field have been specified. The way these values are specified depends on the syntax of the object creation. There are three ways of doing this, see below for details.
Fields are set explicitly using their names:
cat : Cat = { name = "Mimi" } ; cat = Cat { name = "Mimi"; } ; mouse : Mouse = { weight = 100 } ; mouse = Mouse { weight = 100 } ; cheese : Cheese = { taste = Bad } ; cheese = Cheese { taste = Good } ;
Fields are set implicitly according to their order:
cat : Cat = {} ; cat = {Cat} ; mouse : Mouse = { 100 } ; mouse = { Mouse : 100 } ; cheese : Cheese = { Bad } ; cheese = { Cheese : Good } ;
An object value is used as the implicit first parameter for a subsequent creation:
meal = cat @ Meal(mouse) ; = Meal { eater = cat, eaten = mouse, taste = None } ; meal = cat @ Meal { eaten = mouse, taste = Good } ; = Meal { eater = cat, eaten = mouse, taste = Good } ;